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); |