src/jdk/nashorn/internal/runtime/ScriptFunction.java

Print this page




  49     /** Method handle for prototype getter for this ScriptFunction */
  50     public static final MethodHandle G$PROTOTYPE = findOwnMH("G$prototype", Object.class, Object.class);
  51 
  52     /** Method handle for prototype setter for this ScriptFunction */
  53     public static final MethodHandle S$PROTOTYPE = findOwnMH("S$prototype", void.class, Object.class, Object.class);
  54 
  55     /** Method handle for length getter for this ScriptFunction */
  56     public static final MethodHandle G$LENGTH = findOwnMH("G$length", int.class, Object.class);
  57 
  58     /** Method handle for name getter for this ScriptFunction */
  59     public static final MethodHandle G$NAME = findOwnMH("G$name", Object.class, Object.class);
  60 
  61     /** Method handle used for implementing sync() in mozilla_compat */
  62     public static final MethodHandle INVOKE_SYNC = findOwnMH("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class);
  63 
  64     /** Method handle for allocate function for this ScriptFunction */
  65     static final MethodHandle ALLOCATE = findOwnMH("allocate", Object.class);
  66 
  67     private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class);
  68 


  69     /** method handle to scope getter for this ScriptFunction */
  70     public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class);
  71 
  72     private static final MethodHandle IS_FUNCTION_MH  = findOwnMH("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class);
  73 
  74     private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class);
  75 
  76     private static final MethodHandle ADD_ZEROTH_ELEMENT = findOwnMH("addZerothElement", Object[].class, Object[].class, Object.class);
  77 
  78     /** The parent scope. */
  79     private final ScriptObject scope;
  80 
  81     private final ScriptFunctionData data;
  82 
  83     /** The property map used for newly allocated object when function is used as constructor. */
  84     protected PropertyMap allocatorMap;
  85 
  86     /**
  87      * Constructor
  88      *
  89      * @param name          function name
  90      * @param methodHandle  method handle to function (if specializations are present, assumed to be most generic)
  91      * @param map           property map
  92      * @param scope         scope
  93      * @param specs         specialized version of this function - other method handles
  94      * @param strict        is this a strict mode function?
  95      * @param builtin       is this a built in function?
  96      * @param isConstructor is this a constructor?
  97      */
  98     protected ScriptFunction(
  99             final String name,
 100             final MethodHandle methodHandle,
 101             final PropertyMap map,
 102             final ScriptObject scope,
 103             final MethodHandle[] specs,
 104             final boolean strict,
 105             final boolean builtin,
 106             final boolean isConstructor) {
 107 
 108         this(new FinalScriptFunctionData(name, methodHandle, specs, strict, builtin, isConstructor), map, scope);
 109     }
 110 
 111     /**
 112      * Constructor
 113      *
 114      * @param data          static function data
 115      * @param map           property map
 116      * @param scope         scope
 117      */
 118     protected ScriptFunction(
 119             final ScriptFunctionData data,
 120             final PropertyMap map,
 121             final ScriptObject scope) {
 122 
 123         super(map);
 124 
 125         if (Context.DEBUG) {
 126             constructorCount++;
 127         }
 128 


 463      * @return the allocations
 464      */
 465     public static int getAllocations() {
 466         return allocations;
 467     }
 468 
 469     @Override
 470     protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
 471         final MethodType type = desc.getMethodType();
 472         return new GuardedInvocation(pairArguments(data.getBestConstructor(type.changeParameterType(0, ScriptFunction.class), null), type), null, getFunctionGuard(this));
 473     }
 474 
 475     @SuppressWarnings("unused")
 476     private static Object wrapFilter(final Object obj) {
 477         if (obj instanceof ScriptObject || !ScriptFunctionData.isPrimitiveThis(obj)) {
 478             return obj;
 479         }
 480         return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(obj);
 481     }
 482 







 483     /**
 484      * dyn:call call site signature: (callee, thiz, [args...])
 485      * generated method signature:   (callee, thiz, [args...])
 486      *
 487      * cases:
 488      * (a) method has callee parameter
 489      *   (1) for local/scope calls, we just bind thiz and drop the second argument.
 490      *   (2) for normal this-calls, we have to swap thiz and callee to get matching signatures.
 491      * (b) method doesn't have callee parameter (builtin functions)
 492      *   (3) for local/scope calls, bind thiz and drop both callee and thiz.
 493      *   (4) for normal this-calls, drop callee.
 494      */
 495     @Override
 496     protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
 497         final MethodType type = desc.getMethodType();

 498 
 499         if (request.isCallSiteUnstable()) {
 500             // (this, callee, args...) => (this, callee, args[])
 501             final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class,
 502                     type.parameterCount() - 2);
 503 
 504             // If call site is statically typed to take a ScriptFunction, we don't need a guard, otherwise we need a
 505             // generic "is this a ScriptFunction?" guard.
 506             return new GuardedInvocation(collector, ScriptFunction.class.isAssignableFrom(desc.getMethodType().parameterType(0))
 507                     ? null : NashornGuards.getScriptFunctionGuard());
 508         }
 509 
 510         MethodHandle boundHandle;
 511         MethodHandle guard = null;
 512 
 513         final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
 514 
 515         if (data.needsCallee()) {
 516             final MethodHandle callHandle = getBestInvoker(type, request.getArguments());
 517             if (scopeCall) {
 518                 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
 519                 // (callee, this, args...) => (callee, args...)
 520                 boundHandle = MH.insertArguments(callHandle, 1, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
 521                 // (callee, args...) => (callee, [this], args...)
 522                 boundHandle = MH.dropArguments(boundHandle, 1, Object.class);
 523 
 524             } else {
 525                 // It's already (callee, this, args...), just what we need
 526                 boundHandle = callHandle;
 527             }
 528         } else {
 529             final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1), request.getArguments());
 530             if (data.isBuiltin() && "extend".equals(data.getName())) {
 531                 // NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
 532                 // current lookup as its "this" so it can do security-sensitive creation of adapter classes.
 533                 boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class);
 534             } else if (scopeCall) {
 535                 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
 536                 // (this, args...) => (args...)
 537                 boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
 538                 // (args...) => ([callee], [this], args...)
 539                 boundHandle = MH.dropArguments(boundHandle, 0, Object.class, Object.class);
 540             } else {
 541                 // (this, args...) => ([callee], this, args...)
 542                 boundHandle = MH.dropArguments(callHandle, 0, Object.class);
 543             }
 544         }
 545 
 546         // For non-strict functions, check whether this-object is primitive type.
 547         // If so add a to-object-wrapper argument filter.
 548         // Else install a guard that will trigger a relink when the argument becomes primitive.
 549         if (!scopeCall && needsWrappedThis()) {
 550             if (ScriptFunctionData.isPrimitiveThis(request.getArguments()[1])) {
 551                 boundHandle = MH.filterArguments(boundHandle, 1, WRAPFILTER);
 552             } else {
 553                 guard = getNonStrictFunctionGuard(this);
 554             }
 555         }
 556 
 557         boundHandle = pairArguments(boundHandle, type);
 558 
 559         return new GuardedInvocation(boundHandle, guard == null ? getFunctionGuard(this) : guard);




  49     /** Method handle for prototype getter for this ScriptFunction */
  50     public static final MethodHandle G$PROTOTYPE = findOwnMH("G$prototype", Object.class, Object.class);
  51 
  52     /** Method handle for prototype setter for this ScriptFunction */
  53     public static final MethodHandle S$PROTOTYPE = findOwnMH("S$prototype", void.class, Object.class, Object.class);
  54 
  55     /** Method handle for length getter for this ScriptFunction */
  56     public static final MethodHandle G$LENGTH = findOwnMH("G$length", int.class, Object.class);
  57 
  58     /** Method handle for name getter for this ScriptFunction */
  59     public static final MethodHandle G$NAME = findOwnMH("G$name", Object.class, Object.class);
  60 
  61     /** Method handle used for implementing sync() in mozilla_compat */
  62     public static final MethodHandle INVOKE_SYNC = findOwnMH("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class);
  63 
  64     /** Method handle for allocate function for this ScriptFunction */
  65     static final MethodHandle ALLOCATE = findOwnMH("allocate", Object.class);
  66 
  67     private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class);
  68 
  69     private static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
  70 
  71     /** method handle to scope getter for this ScriptFunction */
  72     public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class);
  73 
  74     private static final MethodHandle IS_FUNCTION_MH  = findOwnMH("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class);
  75 
  76     private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class);
  77 
  78     private static final MethodHandle ADD_ZEROTH_ELEMENT = findOwnMH("addZerothElement", Object[].class, Object[].class, Object.class);
  79 
  80     /** The parent scope. */
  81     private final ScriptObject scope;
  82 
  83     private final ScriptFunctionData data;
  84 
  85     /** The property map used for newly allocated object when function is used as constructor. */
  86     protected PropertyMap allocatorMap;
  87 
  88     /**
  89      * Constructor
  90      *
  91      * @param name          function name
  92      * @param methodHandle  method handle to function (if specializations are present, assumed to be most generic)
  93      * @param map           property map
  94      * @param scope         scope
  95      * @param specs         specialized version of this function - other method handles
  96      * @param flags         {@link ScriptFunctionData} flags


  97      */
  98     protected ScriptFunction(
  99             final String name,
 100             final MethodHandle methodHandle,
 101             final PropertyMap map,
 102             final ScriptObject scope,
 103             final MethodHandle[] specs,
 104             final int flags) {


 105 
 106         this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope);
 107     }
 108 
 109     /**
 110      * Constructor
 111      *
 112      * @param data          static function data
 113      * @param map           property map
 114      * @param scope         scope
 115      */
 116     protected ScriptFunction(
 117             final ScriptFunctionData data,
 118             final PropertyMap map,
 119             final ScriptObject scope) {
 120 
 121         super(map);
 122 
 123         if (Context.DEBUG) {
 124             constructorCount++;
 125         }
 126 


 461      * @return the allocations
 462      */
 463     public static int getAllocations() {
 464         return allocations;
 465     }
 466 
 467     @Override
 468     protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
 469         final MethodType type = desc.getMethodType();
 470         return new GuardedInvocation(pairArguments(data.getBestConstructor(type.changeParameterType(0, ScriptFunction.class), null), type), null, getFunctionGuard(this));
 471     }
 472 
 473     @SuppressWarnings("unused")
 474     private static Object wrapFilter(final Object obj) {
 475         if (obj instanceof ScriptObject || !ScriptFunctionData.isPrimitiveThis(obj)) {
 476             return obj;
 477         }
 478         return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(obj);
 479     }
 480 
 481 
 482     @SuppressWarnings("unused")
 483     private static Object globalFilter(final Object object) {
 484         // replace whatever we get with the current global object
 485         return Context.getGlobalTrusted();
 486     }
 487 
 488     /**
 489      * dyn:call call site signature: (callee, thiz, [args...])
 490      * generated method signature:   (callee, thiz, [args...])
 491      *
 492      * cases:
 493      * (a) method has callee parameter
 494      *   (1) for local/scope calls, we just bind thiz and drop the second argument.
 495      *   (2) for normal this-calls, we have to swap thiz and callee to get matching signatures.
 496      * (b) method doesn't have callee parameter (builtin functions)
 497      *   (3) for local/scope calls, bind thiz and drop both callee and thiz.
 498      *   (4) for normal this-calls, drop callee.
 499      */
 500     @Override
 501     protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
 502         final MethodType type = desc.getMethodType();
 503         final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
 504 
 505         if (request.isCallSiteUnstable()) {
 506             // (callee, this, args...) => (callee, this, args[])
 507             final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2);

 508 
 509             // If call site is statically typed to take a ScriptFunction, we don't need a guard, otherwise we need a
 510             // generic "is this a ScriptFunction?" guard.
 511             return new GuardedInvocation(collector, ScriptFunction.class.isAssignableFrom(desc.getMethodType().parameterType(0))
 512                     ? null : NashornGuards.getScriptFunctionGuard());
 513         }
 514 
 515         MethodHandle boundHandle;
 516         MethodHandle guard = null;
 517 


 518         if (data.needsCallee()) {
 519             final MethodHandle callHandle = getBestInvoker(type, request.getArguments());
 520             if (scopeCall && needsWrappedThis()) {
 521                 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
 522                 // (callee, this, args...) => (callee, [this], args...)
 523                 boundHandle = MH.filterArguments(callHandle, 1, GLOBALFILTER);



 524             } else {
 525                 // It's already (callee, this, args...), just what we need
 526                 boundHandle = callHandle;
 527             }
 528         } else {
 529             final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1), request.getArguments());
 530             if (data.isBuiltin() && "extend".equals(data.getName())) {
 531                 // NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
 532                 // current lookup as its "this" so it can do security-sensitive creation of adapter classes.
 533                 boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class);
 534             } else if (scopeCall && needsWrappedThis()) {
 535                 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
 536                 // (this, args...) => ([this], args...)
 537                 boundHandle = MH.filterArguments(callHandle, 0, GLOBALFILTER);
 538                 // ([this], args...) => ([callee], [this], args...)
 539                 boundHandle = MH.dropArguments(boundHandle, 0, Object.class);
 540             } else {
 541                 // (this, args...) => ([callee], this, args...)
 542                 boundHandle = MH.dropArguments(callHandle, 0, Object.class);
 543             }
 544         }
 545 
 546         // For non-strict functions, check whether this-object is primitive type.
 547         // If so add a to-object-wrapper argument filter.
 548         // Else install a guard that will trigger a relink when the argument becomes primitive.
 549         if (!scopeCall && needsWrappedThis()) {
 550             if (ScriptFunctionData.isPrimitiveThis(request.getArguments()[1])) {
 551                 boundHandle = MH.filterArguments(boundHandle, 1, WRAPFILTER);
 552             } else {
 553                 guard = getNonStrictFunctionGuard(this);
 554             }
 555         }
 556 
 557         boundHandle = pairArguments(boundHandle, type);
 558 
 559         return new GuardedInvocation(boundHandle, guard == null ? getFunctionGuard(this) : guard);