< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java

Print this page




  35 import static jdk.nashorn.internal.runtime.JSType.isString;
  36 
  37 import java.lang.invoke.MethodHandle;
  38 import java.lang.invoke.MethodHandles;
  39 import java.lang.invoke.SwitchPoint;
  40 import java.lang.reflect.Array;
  41 import java.util.Collections;
  42 import java.util.Iterator;
  43 import java.util.List;
  44 import java.util.Locale;
  45 import java.util.Map;
  46 import java.util.NoSuchElementException;
  47 import java.util.Objects;
  48 import jdk.dynalink.beans.StaticClass;
  49 import jdk.nashorn.api.scripting.JSObject;
  50 import jdk.nashorn.api.scripting.ScriptObjectMirror;
  51 import jdk.nashorn.internal.codegen.ApplySpecialization;
  52 import jdk.nashorn.internal.codegen.CompilerConstants;
  53 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
  54 import jdk.nashorn.internal.ir.debug.JSONWriter;

  55 import jdk.nashorn.internal.objects.Global;
  56 import jdk.nashorn.internal.objects.NativeObject;
  57 import jdk.nashorn.internal.parser.Lexer;
  58 import jdk.nashorn.internal.runtime.linker.Bootstrap;


  59 
  60 /**
  61  * Utilities to be called by JavaScript runtime API and generated classes.
  62  */
  63 
  64 public final class ScriptRuntime {
  65     private ScriptRuntime() {
  66     }
  67 
  68     /** Singleton representing the empty array object '[]' */
  69     public static final Object[] EMPTY_ARRAY = new Object[0];
  70 
  71     /** Unique instance of undefined. */
  72     public static final Undefined UNDEFINED = Undefined.getUndefined();
  73 
  74     /**
  75      * Unique instance of undefined used to mark empty array slots.
  76      * Can't escape the array.
  77      */
  78     public static final Undefined EMPTY = Undefined.getEmpty();


  86     /** Method handle used to enter a {@code with} scope at runtime. */
  87     public static final Call OPEN_WITH = staticCallNoLookup(ScriptRuntime.class, "openWith", ScriptObject.class, ScriptObject.class, Object.class);
  88 
  89     /**
  90      * Method used to place a scope's variable into the Global scope, which has to be done for the
  91      * properties declared at outermost script level.
  92      */
  93     public static final Call MERGE_SCOPE = staticCallNoLookup(ScriptRuntime.class, "mergeScope", ScriptObject.class, ScriptObject.class);
  94 
  95     /**
  96      * Return an appropriate iterator for the elements in a for-in construct
  97      */
  98     public static final Call TO_PROPERTY_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toPropertyIterator", Iterator.class, Object.class);
  99 
 100     /**
 101      * Return an appropriate iterator for the elements in a for-each construct
 102      */
 103     public static final Call TO_VALUE_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toValueIterator", Iterator.class, Object.class);
 104 
 105     /**





 106       * Method handle for apply. Used from {@link ScriptFunction} for looking up calls to
 107       * call sites that are known to be megamorphic. Using an invoke dynamic here would
 108       * lead to the JVM deoptimizing itself to death
 109       */
 110     public static final Call APPLY = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "apply", Object.class, ScriptFunction.class, Object.class, Object[].class);
 111 
 112     /**
 113      * Throws a reference error for an undefined variable.
 114      */
 115     public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class);
 116 
 117     /**
 118      * Throws a reference error for an undefined variable.
 119      */
 120     public static final Call THROW_CONST_TYPE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwConstTypeError", void.class, String.class);
 121 
 122     /**
 123      * Used to invalidate builtin names, e.g "Function" mapping to all properties in Function.prototype and Function.prototype itself.
 124      */
 125     public static final Call INVALIDATE_RESERVED_BUILTIN_NAME = staticCallNoLookup(ScriptRuntime.class, "invalidateReservedBuiltinName", void.class, String.class);


 346         }
 347 
 348         if (obj instanceof JSObject) {
 349             return ((JSObject)obj).values().iterator();
 350         }
 351 
 352         if (obj instanceof Map) {
 353             return ((Map<?,?>)obj).values().iterator();
 354         }
 355 
 356         if (obj instanceof Iterable) {
 357             return ((Iterable<?>)obj).iterator();
 358         }
 359 
 360         final Object wrapped = Global.instance().wrapAsObject(obj);
 361         if (wrapped instanceof ScriptObject) {
 362             return ((ScriptObject)wrapped).valueIterator();
 363         }
 364 
 365         return Collections.emptyIterator();







































































 366     }
 367 
 368     /**
 369      * Merge a scope into its prototype's map.
 370      * Merge a scope into its prototype.
 371      *
 372      * @param scope Scope to merge.
 373      * @return prototype object after merge
 374      */
 375     public static ScriptObject mergeScope(final ScriptObject scope) {
 376         final ScriptObject parentScope = scope.getProto();
 377         parentScope.addBoundProperties(scope);
 378         return parentScope;
 379     }
 380 
 381     /**
 382      * Call a function given self and args. If the number of the arguments is known in advance, you can likely achieve
 383      * better performance by creating a dynamic invoker using {@link Bootstrap#createDynamicCallInvoker(Class, Class...)}
 384      * then using its {@link MethodHandle#invokeExact(Object...)} method instead.
 385      *




  35 import static jdk.nashorn.internal.runtime.JSType.isString;
  36 
  37 import java.lang.invoke.MethodHandle;
  38 import java.lang.invoke.MethodHandles;
  39 import java.lang.invoke.SwitchPoint;
  40 import java.lang.reflect.Array;
  41 import java.util.Collections;
  42 import java.util.Iterator;
  43 import java.util.List;
  44 import java.util.Locale;
  45 import java.util.Map;
  46 import java.util.NoSuchElementException;
  47 import java.util.Objects;
  48 import jdk.dynalink.beans.StaticClass;
  49 import jdk.nashorn.api.scripting.JSObject;
  50 import jdk.nashorn.api.scripting.ScriptObjectMirror;
  51 import jdk.nashorn.internal.codegen.ApplySpecialization;
  52 import jdk.nashorn.internal.codegen.CompilerConstants;
  53 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
  54 import jdk.nashorn.internal.ir.debug.JSONWriter;
  55 import jdk.nashorn.internal.objects.AbstractIterator;
  56 import jdk.nashorn.internal.objects.Global;
  57 import jdk.nashorn.internal.objects.NativeObject;
  58 import jdk.nashorn.internal.parser.Lexer;
  59 import jdk.nashorn.internal.runtime.linker.Bootstrap;
  60 import jdk.nashorn.internal.runtime.linker.InvokeByName;
  61 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
  62 
  63 /**
  64  * Utilities to be called by JavaScript runtime API and generated classes.
  65  */
  66 
  67 public final class ScriptRuntime {
  68     private ScriptRuntime() {
  69     }
  70 
  71     /** Singleton representing the empty array object '[]' */
  72     public static final Object[] EMPTY_ARRAY = new Object[0];
  73 
  74     /** Unique instance of undefined. */
  75     public static final Undefined UNDEFINED = Undefined.getUndefined();
  76 
  77     /**
  78      * Unique instance of undefined used to mark empty array slots.
  79      * Can't escape the array.
  80      */
  81     public static final Undefined EMPTY = Undefined.getEmpty();


  89     /** Method handle used to enter a {@code with} scope at runtime. */
  90     public static final Call OPEN_WITH = staticCallNoLookup(ScriptRuntime.class, "openWith", ScriptObject.class, ScriptObject.class, Object.class);
  91 
  92     /**
  93      * Method used to place a scope's variable into the Global scope, which has to be done for the
  94      * properties declared at outermost script level.
  95      */
  96     public static final Call MERGE_SCOPE = staticCallNoLookup(ScriptRuntime.class, "mergeScope", ScriptObject.class, ScriptObject.class);
  97 
  98     /**
  99      * Return an appropriate iterator for the elements in a for-in construct
 100      */
 101     public static final Call TO_PROPERTY_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toPropertyIterator", Iterator.class, Object.class);
 102 
 103     /**
 104      * Return an appropriate iterator for the elements in a for-each construct
 105      */
 106     public static final Call TO_VALUE_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toValueIterator", Iterator.class, Object.class);
 107 
 108     /**
 109      * Return an appropriate iterator for the elements in a ES6 for-of loop
 110      */
 111     public static final Call TO_ES6_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toES6Iterator", Iterator.class, Object.class);
 112 
 113     /**
 114       * Method handle for apply. Used from {@link ScriptFunction} for looking up calls to
 115       * call sites that are known to be megamorphic. Using an invoke dynamic here would
 116       * lead to the JVM deoptimizing itself to death
 117       */
 118     public static final Call APPLY = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "apply", Object.class, ScriptFunction.class, Object.class, Object[].class);
 119 
 120     /**
 121      * Throws a reference error for an undefined variable.
 122      */
 123     public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class);
 124 
 125     /**
 126      * Throws a reference error for an undefined variable.
 127      */
 128     public static final Call THROW_CONST_TYPE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwConstTypeError", void.class, String.class);
 129 
 130     /**
 131      * Used to invalidate builtin names, e.g "Function" mapping to all properties in Function.prototype and Function.prototype itself.
 132      */
 133     public static final Call INVALIDATE_RESERVED_BUILTIN_NAME = staticCallNoLookup(ScriptRuntime.class, "invalidateReservedBuiltinName", void.class, String.class);


 354         }
 355 
 356         if (obj instanceof JSObject) {
 357             return ((JSObject)obj).values().iterator();
 358         }
 359 
 360         if (obj instanceof Map) {
 361             return ((Map<?,?>)obj).values().iterator();
 362         }
 363 
 364         if (obj instanceof Iterable) {
 365             return ((Iterable<?>)obj).iterator();
 366         }
 367 
 368         final Object wrapped = Global.instance().wrapAsObject(obj);
 369         if (wrapped instanceof ScriptObject) {
 370             return ((ScriptObject)wrapped).valueIterator();
 371         }
 372 
 373         return Collections.emptyIterator();
 374     }
 375 
 376     /**
 377      * Returns an iterator over property values used in the {@code for ... of} statement. The iterator uses the
 378      * Iterator interface defined in version 6 of the ECMAScript specification.
 379      *
 380      * @param obj object to iterate on.
 381      * @return iterator based on the ECMA 6 Iterator interface.
 382      */
 383     public static Iterator<?> toES6Iterator(final Object obj) {
 384         final Global global = Global.instance();
 385         final Object iterator = AbstractIterator.getIterator(Global.toObject(obj), global);
 386 
 387         final InvokeByName nextInvoker = AbstractIterator.getNextInvoker(global);
 388         final MethodHandle doneInvoker = AbstractIterator.getDoneInvoker(global);
 389         final MethodHandle valueInvoker = AbstractIterator.getValueInvoker(global);
 390 
 391         return new Iterator<Object>() {
 392 
 393             private Object nextResult = nextResult();
 394 
 395             private Object nextResult() {
 396                 try {
 397                     final Object next = nextInvoker.getGetter().invokeExact(iterator);
 398                     if (Bootstrap.isCallable(next)) {
 399                         return nextInvoker.getInvoker().invokeExact(next, iterator, (Object) null);
 400                     }
 401                 } catch (final RuntimeException r) {
 402                     throw r;
 403                 } catch (final Throwable t) {
 404                     throw new RuntimeException(t);
 405                 }
 406                 return null;
 407             }
 408 
 409             @Override
 410             public boolean hasNext() {
 411                 if (nextResult == null) {
 412                     return false;
 413                 }
 414                 try {
 415                     final Object done = doneInvoker.invokeExact(nextResult);
 416                     return !JSType.toBoolean(done);
 417                 } catch (final RuntimeException r) {
 418                     throw r;
 419                 } catch (final Throwable t) {
 420                     throw new RuntimeException(t);
 421                 }
 422             }
 423 
 424             @Override
 425             public Object next() {
 426                 if (nextResult == null) {
 427                     return Undefined.getUndefined();
 428                 }
 429                 try {
 430                     final Object result = nextResult;
 431                     nextResult = nextResult();
 432                     return valueInvoker.invokeExact(result);
 433                 } catch (final RuntimeException r) {
 434                     throw r;
 435                 } catch (final Throwable t) {
 436                     throw new RuntimeException(t);
 437                 }
 438             }
 439 
 440             @Override
 441             public void remove() {
 442                 throw new UnsupportedOperationException("remove");
 443             }
 444         };
 445     }
 446 
 447     /**
 448      * Merge a scope into its prototype's map.
 449      * Merge a scope into its prototype.
 450      *
 451      * @param scope Scope to merge.
 452      * @return prototype object after merge
 453      */
 454     public static ScriptObject mergeScope(final ScriptObject scope) {
 455         final ScriptObject parentScope = scope.getProto();
 456         parentScope.addBoundProperties(scope);
 457         return parentScope;
 458     }
 459 
 460     /**
 461      * Call a function given self and args. If the number of the arguments is known in advance, you can likely achieve
 462      * better performance by creating a dynamic invoker using {@link Bootstrap#createDynamicCallInvoker(Class, Class...)}
 463      * then using its {@link MethodHandle#invokeExact(Object...)} method instead.
 464      *


< prev index next >