gt:                     return Array.get(array, index++);
context: /*
   * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  package jdk.nashorn.internal.runtime;
  
  import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
  import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
  import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
  import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
  import static jdk.nashorn.internal.runtime.ECMAErrors.syntaxError;
  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
  import static jdk.nashorn.internal.runtime.JSType.isString;
  
  import java.lang.invoke.MethodHandle;
  import java.lang.invoke.MethodHandles;
  import java.lang.invoke.SwitchPoint;
  import java.lang.reflect.Array;
  import java.util.Collections;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Locale;
  import java.util.Map;
  import java.util.NoSuchElementException;
  import java.util.Objects;
  import jdk.internal.dynalink.beans.StaticClass;
  import jdk.nashorn.api.scripting.JSObject;
  import jdk.nashorn.api.scripting.ScriptObjectMirror;
  import jdk.nashorn.internal.codegen.ApplySpecialization;
  import jdk.nashorn.internal.codegen.CompilerConstants;
  import jdk.nashorn.internal.codegen.CompilerConstants.Call;
  import jdk.nashorn.internal.ir.debug.JSONWriter;
  import jdk.nashorn.internal.objects.Global;
  import jdk.nashorn.internal.objects.NativeObject;
  import jdk.nashorn.internal.parser.Lexer;
  import jdk.nashorn.internal.runtime.linker.Bootstrap;
  
  /**
   * Utilities to be called by JavaScript runtime API and generated classes.
   */
  
  public final class ScriptRuntime {
      private ScriptRuntime() {
      }
  
      /** Singleton representing the empty array object '[]' */
      public static final Object[] EMPTY_ARRAY = new Object[0];
  
      /** Unique instance of undefined. */
      public static final Undefined UNDEFINED = Undefined.getUndefined();
  
      /**
       * Unique instance of undefined used to mark empty array slots.
       * Can't escape the array.
       */
      public static final Undefined EMPTY = Undefined.getEmpty();
  
      /** Method handle to generic + operator, operating on objects */
      public static final Call ADD = staticCallNoLookup(ScriptRuntime.class, "ADD", Object.class, Object.class, Object.class);
  
      /** Method handle to generic === operator, operating on objects */
      public static final Call EQ_STRICT = staticCallNoLookup(ScriptRuntime.class, "EQ_STRICT", boolean.class, Object.class, Object.class);
  
      /** Method handle used to enter a {@code with} scope at runtime. */
      public static final Call OPEN_WITH = staticCallNoLookup(ScriptRuntime.class, "openWith", ScriptObject.class, ScriptObject.class, Object.class);
  
      /**
       * Method used to place a scope's variable into the Global scope, which has to be done for the
       * properties declared at outermost script level.
       */
      public static final Call MERGE_SCOPE = staticCallNoLookup(ScriptRuntime.class, "mergeScope", ScriptObject.class, ScriptObject.class);
  
      /**
       * Return an appropriate iterator for the elements in a for-in construct
       */
      public static final Call TO_PROPERTY_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toPropertyIterator", Iterator.class, Object.class);
  
      /**
       * Return an appropriate iterator for the elements in a for-each construct
       */
      public static final Call TO_VALUE_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toValueIterator", Iterator.class, Object.class);
  
      /**
        * Method handle for apply. Used from {@link ScriptFunction} for looking up calls to
        * call sites that are known to be megamorphic. Using an invoke dynamic here would
        * lead to the JVM deoptimizing itself to death
        */
      public static final Call APPLY = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "apply", Object.class, ScriptFunction.class, Object.class, Object[].class);
  
      /**
       * Throws a reference error for an undefined variable.
       */
      public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class);
  
      /**
       * Throws a reference error for an undefined variable.
       */
      public static final Call THROW_CONST_TYPE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwConstTypeError", void.class, String.class);
  
      /**
       * Used to invalidate builtin names, e.g "Function" mapping to all properties in Function.prototype and Function.prototype itself.
       */
      public static final Call INVALIDATE_RESERVED_BUILTIN_NAME = staticCallNoLookup(ScriptRuntime.class, "invalidateReservedBuiltinName", void.class, String.class);
  
      /**
       * Converts a switch tag value to a simple integer. deflt value if it can't.
       *
       * @param tag   Switch statement tag value.
       * @param deflt default to use if not convertible.
       * @return int tag value (or deflt.)
       */
      public static int switchTagAsInt(final Object tag, final int deflt) {
          if (tag instanceof Number) {
              final double d = ((Number)tag).doubleValue();
              if (isRepresentableAsInt(d)) {
                  return (int)d;
              }
          }
          return deflt;
      }
  
      /**
       * Converts a switch tag value to a simple integer. deflt value if it can't.
       *
       * @param tag   Switch statement tag value.
       * @param deflt default to use if not convertible.
       * @return int tag value (or deflt.)
       */
      public static int switchTagAsInt(final boolean tag, final int deflt) {
          return deflt;
      }
  
      /**
       * Converts a switch tag value to a simple integer. deflt value if it can't.
       *
       * @param tag   Switch statement tag value.
       * @param deflt default to use if not convertible.
       * @return int tag value (or deflt.)
       */
      public static int switchTagAsInt(final long tag, final int deflt) {
          return isRepresentableAsInt(tag) ? (int)tag : deflt;
      }
  
      /**
       * Converts a switch tag value to a simple integer. deflt value if it can't.
       *
       * @param tag   Switch statement tag value.
       * @param deflt default to use if not convertible.
       * @return int tag value (or deflt.)
       */
      public static int switchTagAsInt(final double tag, final int deflt) {
          return isRepresentableAsInt(tag) ? (int)tag : deflt;
      }
  
      /**
       * This is the builtin implementation of {@code Object.prototype.toString}
       * @param self reference
       * @return string representation as object
       */
      public static String builtinObjectToString(final Object self) {
          String className;
          // Spec tells us to convert primitives by ToObject..
          // But we don't need to -- all we need is the right class name
          // of the corresponding primitive wrapper type.
  
          final JSType type = JSType.ofNoFunction(self);
  
          switch (type) {
          case BOOLEAN:
              className = "Boolean";
              break;
          case NUMBER:
              className = "Number";
              break;
          case STRING:
              className = "String";
              break;
          // special case of null and undefined
          case NULL:
              className = "Null";
              break;
          case UNDEFINED:
              className = "Undefined";
              break;
          case OBJECT:
              if (self instanceof ScriptObject) {
                  className = ((ScriptObject)self).getClassName();
              } else if (self instanceof JSObject) {
                  className = ((JSObject)self).getClassName();
              } else {
                  className = self.getClass().getName();
              }
              break;
          default:
              // Nashorn extension: use Java class name
              className = self.getClass().getName();
              break;
          }
  
          final StringBuilder sb = new StringBuilder();
          sb.append("[object ");
          sb.append(className);
          sb.append(']');
  
          return sb.toString();
      }
  
      /**
       * This is called whenever runtime wants to throw an error and wants to provide
       * meaningful information about an object. We don't want to call toString which
       * ends up calling "toString" from script world which may itself throw error.
       * When we want to throw an error, we don't additional error from script land
       * -- which may sometimes lead to infinite recursion.
       *
       * @param obj Object to converted to String safely (without calling user script)
       * @return safe String representation of the given object
       */
      public static String safeToString(final Object obj) {
          return JSType.toStringImpl(obj, true);
      }
  
      /**
       * Returns an iterator over property identifiers used in the {@code for...in} statement. Note that the ECMAScript
       * 5.1 specification, chapter 12.6.4. uses the terminology "property names", which seems to imply that the property
       * identifiers are expected to be strings, but this is not actually spelled out anywhere, and Nashorn will in some
       * cases deviate from this. Namely, we guarantee to always return an iterator over {@link String} values for any
       * built-in JavaScript object. We will however return an iterator over {@link Integer} objects for native Java
       * arrays and {@link List} objects, as well as arbitrary objects representing keys of a {@link Map}. Therefore, the
       * expression {@code typeof i} within a {@code for(i in obj)} statement can return something other than
       * {@code string} when iterating over native Java arrays, {@code List}, and {@code Map} objects.
       * @param obj object to iterate on.
       * @return iterator over the object's property names.
       */
      public static Iterator<?> toPropertyIterator(final Object obj) {
          if (obj instanceof ScriptObject) {
              return ((ScriptObject)obj).propertyIterator();
          }
  
          if (obj != null && obj.getClass().isArray()) {
              return new RangeIterator(Array.getLength(obj));
          }
  
          if (obj instanceof JSObject) {
              return ((JSObject)obj).keySet().iterator();
          }
  
          if (obj instanceof List) {
              return new RangeIterator(((List<?>)obj).size());
          }
  
          if (obj instanceof Map) {
              return ((Map<?,?>)obj).keySet().iterator();
          }
  
          final Object wrapped = Global.instance().wrapAsObject(obj);
          if (wrapped instanceof ScriptObject) {
              return ((ScriptObject)wrapped).propertyIterator();
          }
  
          return Collections.emptyIterator();
      }
  
      private static final class RangeIterator implements Iterator<Integer> {
          private final int length;
          private int index;
  
          RangeIterator(final int length) {
              this.length = length;
          }
  
          @Override
          public boolean hasNext() {
              return index < length;
          }
  
          @Override
          public Integer next() {
              return index++;
          }
  
          @Override
          public void remove() {
              throw new UnsupportedOperationException("remove");
          }
      }
  
      /**
       * Returns an iterator over property values used in the {@code for each...in} statement. Aside from built-in JS
       * objects, it also operates on Java arrays, any {@link Iterable}, as well as on {@link Map} objects, iterating over
       * map values.
       * @param obj object to iterate on.
       * @return iterator over the object's property values.
       */
      public static Iterator<?> toValueIterator(final Object obj) {
          if (obj instanceof ScriptObject) {
              return ((ScriptObject)obj).valueIterator();
          }
  
          if (obj != null && obj.getClass().isArray()) {
              final Object array  = obj;
              final int    length = Array.getLength(obj);
  
              return new Iterator<Object>() {
                  private int index = 0;
  
                  @Override
                  public boolean hasNext() {
                      return index < length;
                  }
  
                  @Override
                  public Object next() {
                      if (index >= length) {
                          throw new NoSuchElementException();
                      }
  