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

Print this page

        

*** 35,45 **** import java.lang.invoke.MethodType; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; import jdk.nashorn.internal.objects.annotations.SpecializedFunction; - import jdk.nashorn.internal.parser.Token; import jdk.nashorn.internal.runtime.linker.MethodHandleFactory; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.linker.NashornGuards; import jdk.nashorn.internal.runtime.options.Options; import org.dynalang.dynalink.CallSiteDescriptor; --- 35,44 ----
*** 68,305 **** private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class); private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class); - /** method handle to arity setter for this ScriptFunction */ - public static final Call SET_ARITY = virtualCallNoLookup(ScriptFunction.class, "setArity", void.class, int.class); /** method handle to scope getter for this ScriptFunction */ public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class); /** Should specialized function and specialized constructors for the builtin be used if available? */ private static final boolean DISABLE_SPECIALIZATION = Options.getBooleanProperty("nashorn.scriptfunction.specialization.disable"); ! /** Name of function or null. */ ! private final String name; ! ! /** Source of function. */ ! private final Source source; ! ! /** Start position and length in source. */ ! private final long token; ! ! /** Reference to code for this method. */ ! private final MethodHandle invokeHandle; ! ! /** Reference to code for this method when called to create "new" object */ ! protected MethodHandle constructHandle; /** Reference to constructor prototype. */ protected Object prototype; - /** Constructor to create a new instance. */ - private MethodHandle allocator; - - /** Map for new instance constructor. */ - private PropertyMap allocatorMap; - /** The parent scope. */ private final ScriptObject scope; - /** Specializations - see @SpecializedFunction */ - private MethodHandle[] invokeSpecializations; - - /** Specializations - see @SpecializedFunction */ - private MethodHandle[] constructSpecializations; - - /** This field is either computed in constructor or set explicitly by calling setArity method. */ - private int arity; - /** * Constructor * * @param name function name * @param methodHandle method handle to function (if specializations are present, assumed to be most generic) * @param map property map * @param scope scope * @param specs specialized version of this function - other method handles - */ - protected ScriptFunction( - final String name, - final MethodHandle methodHandle, - final PropertyMap map, - final ScriptObject scope, - final MethodHandle[] specs) { - this(name, methodHandle, map, scope, null, 0, needsCallee(methodHandle), specs); - } - - /** - * Heuristic to figure out if the method handle has a callee argument. If it's type is either - * {@code (boolean, Object, ScriptFunction, ...)} or {@code (Object, ScriptFunction, ...)}, then we'll assume it has - * a callee argument. We need this as the constructor above is not passed this information, and can't just blindly - * assume it's false (notably, it's being invoked for creation of new scripts, and scripts have scopes, therefore - * they also always receive a callee. - * @param methodHandle the examined method handle - * @return true if the method handle expects a callee, false otherwise - */ - private static boolean needsCallee(MethodHandle methodHandle) { - final MethodType type = methodHandle.type(); - final int len = type.parameterCount(); - if(len == 0) { - return false; - } - if(type.parameterType(0) == boolean.class) { - return len > 2 && type.parameterType(2) == ScriptFunction.class; - } - return len > 1 && type.parameterType(1) == ScriptFunction.class; - } - - /** - * Constructor * - * @param name function name - * @param methodHandle method handle to function (if specializations are present, assumed to be most generic) - * @param map property map - * @param scope scope - * @param source the source - * @param token token - * @param allocator method handle to this function's allocator - see JO$ classes - * @param allocatorMap property map to be used for all constructors - * @param needsCallee does this method use the {@code callee} variable - * @param specs specialized version of this function - other method handles */ protected ScriptFunction( final String name, final MethodHandle methodHandle, final PropertyMap map, final ScriptObject scope, ! final Source source, ! final long token, ! final MethodHandle allocator, ! final PropertyMap allocatorMap, ! final boolean needsCallee, ! final MethodHandle[] specs) { ! ! this(name, methodHandle, map, scope, source, token, needsCallee, specs); ! ! //this is the internal constructor ! this.allocator = allocator; ! this.allocatorMap = allocatorMap; } /** * Constructor * ! * @param name function name ! * @param methodHandle method handle to function (if specializations are present, assumed to be most generic) * @param map property map * @param scope scope - * @param source the source - * @param token token - * @param needsCallee does this method use the {@code callee} variable - * @param specs specialized version of this function - other method handles */ protected ScriptFunction( ! final String name, ! final MethodHandle methodHandle, final PropertyMap map, ! final ScriptObject scope, ! final Source source, ! final long token, ! final boolean needsCallee, ! final MethodHandle[] specs) { super(map); if (Context.DEBUG) { constructorCount++; } ! this.name = name; ! this.source = source; ! this.token = token; this.scope = scope; - if(needsCallee) { - setHasCalleeParameter(); - } - - final MethodType type = methodHandle.type(); - final int paramCount = type.parameterCount(); - final boolean isVarArg = type.parameterType(paramCount - 1).isArray(); - - final MethodHandle mh = MH.asType(methodHandle, adaptType(type, needsCallee, isVarArg)); - - this.arity = isVarArg ? -1 : paramCount - 1; //drop the self param for arity - - if (needsCallee && !isVarArg) { - this.arity--; - } - - if (scope != null) { - this.invokeHandle = mh; - this.constructHandle = mh; - } else if (isConstructor(mh)) { - if (!isVarArg) { - this.arity--; // drop the boolean flag for arity - } - /* - * We insert a boolean argument to tell if the method was invoked as - * constructor or not if the method handle's first argument is boolean. - */ - this.invokeHandle = MH.insertArguments(mh, 0, false); - this.constructHandle = MH.insertArguments(mh, 0, true); - - if (specs != null) { - this.invokeSpecializations = new MethodHandle[specs.length]; - this.constructSpecializations = new MethodHandle[specs.length]; - for (int i = 0; i < specs.length; i++) { - this.invokeSpecializations[i] = MH.insertArguments(specs[i], 0, false); - this.constructSpecializations[i] = MH.insertArguments(specs[i], 0, true); - } - } - } else { - this.invokeHandle = mh; - this.constructHandle = mh; - this.invokeSpecializations = specs; - this.constructSpecializations = specs; - } - } - - /** - * Takes a method type, and returns a (potentially different method type) that the method handles used by - * ScriptFunction must conform to in order to be usable in {@link #invoke(Object, Object...)} and - * {@link #construct(Object, Object...)}. The returned method type will be sure to return {@code Object}, and will - * have all its parameters turned into {@code Object} as well, except for the following ones: - * <ul> - * <li>an optional first {@code boolean} parameter, used for some functions to distinguish method and constructor - * invocation,</li> - * <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li> - * <li>the second (or, in presence of boolean parameter, third) argument, which is forced to be - * {@link ScriptFunction}, in case the function receives itself (callee) as an argument</li> - * @param type the original type - * @param hasCallee true if the function uses the callee argument - * @param isVarArg if the function is a vararg - * @return the new type, conforming to the rules above. - */ - private static MethodType adaptType(final MethodType type, final boolean hasCallee, final boolean isVarArg) { - // Generify broadly - MethodType newType = type.generic().changeReturnType(Object.class); - if(isVarArg) { - // Change back to vararg if we over-generified it - newType = newType.changeParameterType(type.parameterCount() - 1, Object[].class); - } - final boolean hasBoolean = type.parameterType(0) == boolean.class; - if(hasBoolean) { - // Restore the initial boolean argument - newType = newType.changeParameterType(0, boolean.class); - } - if(hasCallee) { - // Restore the ScriptFunction argument - newType = newType.changeParameterType(hasBoolean ? 2 : 1, ScriptFunction.class); - } - return newType; } @Override public String getClassName() { return "Function"; --- 67,132 ---- private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class); private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class); /** method handle to scope getter for this ScriptFunction */ public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class); /** Should specialized function and specialized constructors for the builtin be used if available? */ private static final boolean DISABLE_SPECIALIZATION = Options.getBooleanProperty("nashorn.scriptfunction.specialization.disable"); ! private final ScriptFunctionData data; /** Reference to constructor prototype. */ protected Object prototype; /** The parent scope. */ private final ScriptObject scope; /** * Constructor * * @param name function name * @param methodHandle method handle to function (if specializations are present, assumed to be most generic) * @param map property map * @param scope scope * @param specs specialized version of this function - other method handles * */ protected ScriptFunction( final String name, final MethodHandle methodHandle, final PropertyMap map, final ScriptObject scope, ! final MethodHandle[] specs, ! final boolean strict, ! final boolean builtin) { ! this (new ScriptFunctionData(name, methodHandle, specs, strict, builtin), map, scope); } /** * Constructor * ! * @param data static function data * @param map property map * @param scope scope */ protected ScriptFunction( ! final ScriptFunctionData data, final PropertyMap map, ! final ScriptObject scope) { super(map); if (Context.DEBUG) { constructorCount++; } ! this.data = data; this.scope = scope; } @Override public String getClassName() { return "Function";
*** 327,365 **** /** * Get the arity of this ScriptFunction * @return arity */ public final int getArity() { ! return arity; } /** * Set the arity of this ScriptFunction * @param arity arity */ public final void setArity(final int arity) { ! this.arity = arity; } /** * Is this a ECMAScript 'use strict' function? * @return true if function is in strict mode */ ! public abstract boolean isStrict(); /** * Is this a ECMAScript built-in function (like parseInt, Array.isArray) ? * @return true if built-in */ ! public abstract boolean isBuiltin(); /** ! * Is this a non-strict and not-built-in script function? ! * @return true if neither strict nor built-in */ ! public boolean isNonStrictFunction() { ! return !isStrict() && !isBuiltin(); } /** * Execute this script function. * @param self Target object. --- 154,197 ---- /** * Get the arity of this ScriptFunction * @return arity */ public final int getArity() { ! return data.getArity(); } /** * Set the arity of this ScriptFunction * @param arity arity */ public final void setArity(final int arity) { ! data.setArity(arity); } /** * Is this a ECMAScript 'use strict' function? * @return true if function is in strict mode */ ! public boolean isStrict() { ! return data.isStrict(); ! } /** * Is this a ECMAScript built-in function (like parseInt, Array.isArray) ? * @return true if built-in */ ! public boolean isBuiltin() { ! return data.isBuiltin(); ! } /** ! * Returns true if this is a non-strict, non-built-in function that requires non-primitive this argument ! * according to ECMA 10.4.3. ! * @return true if this argument must be an object */ ! public boolean needsWrappedThis() { ! return data.needsWrappedThis(); } /** * Execute this script function. * @param self Target object.
*** 370,416 **** public Object invoke(final Object self, final Object... arguments) throws Throwable { if (Context.DEBUG) { invokes++; } final Object selfObj = convertThisObject(self); final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; ! if (isVarArg(invokeHandle)) { ! if (hasCalleeParameter()) { ! return invokeHandle.invokeExact(selfObj, this, args); } ! return invokeHandle.invokeExact(selfObj, args); } ! final int paramCount = invokeHandle.type().parameterCount(); ! if (hasCalleeParameter()) { switch (paramCount) { case 2: ! return invokeHandle.invokeExact(selfObj, this); case 3: ! return invokeHandle.invokeExact(selfObj, this, getArg(args, 0)); case 4: ! return invokeHandle.invokeExact(selfObj, this, getArg(args, 0), getArg(args, 1)); case 5: ! return invokeHandle.invokeExact(selfObj, this, getArg(args, 0), getArg(args, 1), getArg(args, 2)); default: ! return invokeHandle.invokeWithArguments(withArguments(selfObj, this, paramCount, args)); } } switch (paramCount) { case 1: ! return invokeHandle.invokeExact(selfObj); case 2: ! return invokeHandle.invokeExact(selfObj, getArg(args, 0)); case 3: ! return invokeHandle.invokeExact(selfObj, getArg(args, 0), getArg(args, 1)); case 4: ! return invokeHandle.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2)); default: ! return invokeHandle.invokeWithArguments(withArguments(selfObj, null, paramCount, args)); } } private static Object getArg(final Object[] args, final int i) { return i < args.length ? args[i] : UNDEFINED; --- 202,249 ---- public Object invoke(final Object self, final Object... arguments) throws Throwable { if (Context.DEBUG) { invokes++; } + final MethodHandle invoker = data.getGenericInvoker(); final Object selfObj = convertThisObject(self); final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments; ! if (data.isVarArg()) { ! if (data.needsCallee()) { ! return invoker.invokeExact(selfObj, this, args); } ! return invoker.invokeExact(selfObj, args); } ! final int paramCount = invoker.type().parameterCount(); ! if (data.needsCallee()) { switch (paramCount) { case 2: ! return invoker.invokeExact(selfObj, this); case 3: ! return invoker.invokeExact(selfObj, this, getArg(args, 0)); case 4: ! return invoker.invokeExact(selfObj, this, getArg(args, 0), getArg(args, 1)); case 5: ! return invoker.invokeExact(selfObj, this, getArg(args, 0), getArg(args, 1), getArg(args, 2)); default: ! return invoker.invokeWithArguments(withArguments(selfObj, this, paramCount, args)); } } switch (paramCount) { case 1: ! return invoker.invokeExact(selfObj); case 2: ! return invoker.invokeExact(selfObj, getArg(args, 0)); case 3: ! return invoker.invokeExact(selfObj, getArg(args, 0), getArg(args, 1)); case 4: ! return invoker.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2)); default: ! return invoker.invokeWithArguments(withArguments(selfObj, null, paramCount, args)); } } private static Object getArg(final Object[] args, final int i) { return i < args.length ? args[i] : UNDEFINED;
*** 422,469 **** * @param args Call arguments. * @return ScriptFunction result. * @throws Throwable if there is an exception/error with the constructor invocation or thrown from it */ public Object construct(final Object self, final Object... args) throws Throwable { ! if (constructHandle == null) { typeError("not.a.constructor", ScriptRuntime.safeToString(this)); } ! if (isVarArg(constructHandle)) { ! if (hasCalleeParameter()) { ! return constructHandle.invokeExact(self, this, args); } ! return constructHandle.invokeExact(self, args); } ! final int paramCount = constructHandle.type().parameterCount(); ! if (hasCalleeParameter()) { switch (paramCount) { case 2: ! return constructHandle.invokeExact(self, this); case 3: ! return constructHandle.invokeExact(self, this, getArg(args, 0)); case 4: ! return constructHandle.invokeExact(self, this, getArg(args, 0), getArg(args, 1)); case 5: ! return constructHandle.invokeExact(self, this, getArg(args, 0), getArg(args, 1), getArg(args, 2)); default: ! return constructHandle.invokeWithArguments(withArguments(self, this, args)); } } switch(paramCount) { case 1: ! return constructHandle.invokeExact(self); case 2: ! return constructHandle.invokeExact(self, getArg(args, 0)); case 3: ! return constructHandle.invokeExact(self, getArg(args, 0), getArg(args, 1)); case 4: ! return constructHandle.invokeExact(self, getArg(args, 0), getArg(args, 1), getArg(args, 2)); default: ! return constructHandle.invokeWithArguments(withArguments(self, null, args)); } } private static Object[] withArguments(final Object self, final ScriptFunction function, final Object... args) { return withArguments(self, function, args.length + (function == null ? 1 : 2), args); // + 2 to include self and function --- 255,303 ---- * @param args Call arguments. * @return ScriptFunction result. * @throws Throwable if there is an exception/error with the constructor invocation or thrown from it */ public Object construct(final Object self, final Object... args) throws Throwable { ! if (data.getConstructor() == null) { typeError("not.a.constructor", ScriptRuntime.safeToString(this)); } ! final MethodHandle constructor = data.getGenericConstructor(); ! if (data.isVarArg()) { ! if (data.needsCallee()) { ! return constructor.invokeExact(self, this, args); } ! return constructor.invokeExact(self, args); } ! final int paramCount = constructor.type().parameterCount(); ! if (data.needsCallee()) { switch (paramCount) { case 2: ! return constructor.invokeExact(self, this); case 3: ! return constructor.invokeExact(self, this, getArg(args, 0)); case 4: ! return constructor.invokeExact(self, this, getArg(args, 0), getArg(args, 1)); case 5: ! return constructor.invokeExact(self, this, getArg(args, 0), getArg(args, 1), getArg(args, 2)); default: ! return constructor.invokeWithArguments(withArguments(self, this, args)); } } switch(paramCount) { case 1: ! return constructor.invokeExact(self); case 2: ! return constructor.invokeExact(self, getArg(args, 0)); case 3: ! return constructor.invokeExact(self, getArg(args, 0), getArg(args, 1)); case 4: ! return constructor.invokeExact(self, getArg(args, 0), getArg(args, 1), getArg(args, 2)); default: ! return constructor.invokeWithArguments(withArguments(self, null, args)); } } private static Object[] withArguments(final Object self, final ScriptFunction function, final Object... args) { return withArguments(self, function, args.length + (function == null ? 1 : 2), args); // + 2 to include self and function
*** 507,519 **** typeError("not.a.constructor", ScriptRuntime.safeToString(this)); } ScriptObject object = null; ! if (allocator != null) { try { ! object = (ScriptObject)allocator.invokeExact(allocatorMap); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { throw new RuntimeException(t); } --- 341,353 ---- typeError("not.a.constructor", ScriptRuntime.safeToString(this)); } ScriptObject object = null; ! if (data.getAllocator() != null) { try { ! object = (ScriptObject)data.getAllocator().invokeExact(data.getAllocatorMap()); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { throw new RuntimeException(t); }
*** 544,610 **** * @param args other arguments (beside self) to bind the function to * @return the bound function */ public abstract ScriptFunction makeBoundFunction(Object self, Object[] args); - /** - * Test if a methodHandle refers to a constructor. - * @param methodHandle MethodHandle to test. - * @return True if method is a constructor. - */ - private static boolean isConstructor(final MethodHandle methodHandle) { - return methodHandle.type().parameterCount() >= 1 && methodHandle.type().parameterType(0) == boolean.class; - } - - /** - * Test if a methodHandle refers to a variable argument method. - * @param methodHandle MethodHandle to test. - * @return True if variable arguments. - */ - public boolean isVarArg(final MethodHandle methodHandle) { - return hasCalleeParameter() - ? methodHandle.type().parameterCount() == 3 && methodHandle.type().parameterType(2).isArray() - : methodHandle.type().parameterCount() == 2 && methodHandle.type().parameterType(1).isArray(); - } @Override public final String safeToString() { return toSource(); } @Override public String toString() { ! final StringBuilder sb = new StringBuilder(); ! ! sb.append(super.toString()) ! .append(" [ ") ! .append(invokeHandle) ! .append(", ") ! .append((name == null || name.isEmpty()) ? "<anonymous>" : name); ! ! if (source != null) { ! sb.append(" @ ") ! .append(source.getName()) ! .append(':') ! .append(source.getLine(Token.descPosition(token))); ! } ! sb.append(" ]"); ! ! return sb.toString(); } /** * Get this function as a String containing its source code. If no source code * exists in this ScriptFunction, its contents will be displayed as {@code [native code]} * @return string representation of this function's source */ public final String toSource() { ! if (source != null && token != 0) { ! return source.getString(Token.descPosition(token), Token.descLength(token)); ! } ! ! return "function " + (name == null ? "" : name) + "() { [native code] }"; } /** * Get the prototype object for this function * @return prototype --- 378,405 ---- * @param args other arguments (beside self) to bind the function to * @return the bound function */ public abstract ScriptFunction makeBoundFunction(Object self, Object[] args); @Override public final String safeToString() { return toSource(); } @Override public String toString() { ! return data.toString(); } /** * Get this function as a String containing its source code. If no source code * exists in this ScriptFunction, its contents will be displayed as {@code [native code]} * @return string representation of this function's source */ public final String toSource() { ! return data.toSource(); } /** * Get the prototype object for this function * @return prototype
*** 694,714 **** * Return the most appropriate invoke handle if there are specializations * @param type most specific method type to look for invocation with * @return invoke method handle */ public final MethodHandle getBestSpecializedInvokeHandle(final MethodType type) { ! return candidateWithLowestWeight(type, getInvokeHandle(), invokeSpecializations); } /** * Get the invoke handle - the most generic (and if no specializations are in place, only) invocation * method handle for this ScriptFunction * @see SpecializedFunction * @return invokeHandle */ public final MethodHandle getInvokeHandle() { ! return invokeHandle; } /** * Return the invoke handle bound to a given ScriptObject self reference. * If callee parameter is required result is rebound to this. --- 489,509 ---- * Return the most appropriate invoke handle if there are specializations * @param type most specific method type to look for invocation with * @return invoke method handle */ public final MethodHandle getBestSpecializedInvokeHandle(final MethodType type) { ! return candidateWithLowestWeight(type, getInvokeHandle(), data.getInvokeSpecializations()); } /** * Get the invoke handle - the most generic (and if no specializations are in place, only) invocation * method handle for this ScriptFunction * @see SpecializedFunction * @return invokeHandle */ public final MethodHandle getInvokeHandle() { ! return data.getInvoker(); } /** * Return the invoke handle bound to a given ScriptObject self reference. * If callee parameter is required result is rebound to this.
*** 716,791 **** * @param self self reference * @return bound invoke handle */ public final MethodHandle getBoundInvokeHandle(final ScriptObject self) { final MethodHandle bound = MH.bindTo(getInvokeHandle(), self); ! return hasCalleeParameter() ? MH.bindTo(bound, this) : bound; } - /** - * Check whether the ScriptFunction has callee parameter - * @return true if callee parameter - */ - protected abstract boolean hasCalleeParameter(); - - /** - * Flag ScriptFunction as needing a callee parameter - */ - protected abstract void setHasCalleeParameter(); /** * Get the construct handle - the most generic (and if no specializations are in place, only) constructor * method handle for this ScriptFunction * @see SpecializedConstructor * @param type type for wanted constructor * @return construct handle */ public final MethodHandle getConstructHandle(final MethodType type) { ! return candidateWithLowestWeight(type, getConstructHandle(), constructSpecializations); } /** * Get a method handle to the constructor for this function * @return constructor handle */ public final MethodHandle getConstructHandle() { ! return constructHandle; } /** * Set a method handle to the constructor for this function * @param constructHandle constructor handle */ public final void setConstructHandle(final MethodHandle constructHandle) { ! this.constructHandle = constructHandle; ! this.constructSpecializations = null; } /** * Get the name for this function * @return the name */ public final String getName() { ! return name; } /** * Does this script function need to be compiled. This determined by * null checking invokeHandle * * @return true if this needs compilation */ public final boolean needsCompilation() { ! return invokeHandle == null; } /** * Get token for this function * @return token */ public final long getToken() { ! return token; } /** * Get the scope for this function * @return the scope --- 511,575 ---- * @param self self reference * @return bound invoke handle */ public final MethodHandle getBoundInvokeHandle(final ScriptObject self) { final MethodHandle bound = MH.bindTo(getInvokeHandle(), self); ! return data.needsCallee() ? MH.bindTo(bound, this) : bound; } /** * Get the construct handle - the most generic (and if no specializations are in place, only) constructor * method handle for this ScriptFunction * @see SpecializedConstructor * @param type type for wanted constructor * @return construct handle */ public final MethodHandle getConstructHandle(final MethodType type) { ! return candidateWithLowestWeight(type, getConstructHandle(), data.getConstructSpecializations()); } /** * Get a method handle to the constructor for this function * @return constructor handle */ public final MethodHandle getConstructHandle() { ! return data.getConstructor(); } /** * Set a method handle to the constructor for this function * @param constructHandle constructor handle */ public final void setConstructHandle(final MethodHandle constructHandle) { ! data.setConstructor(constructHandle); } /** * Get the name for this function * @return the name */ public final String getName() { ! return data.getName(); } /** * Does this script function need to be compiled. This determined by * null checking invokeHandle * * @return true if this needs compilation */ public final boolean needsCompilation() { ! return data.getInvoker() == null; } /** * Get token for this function * @return token */ public final long getToken() { ! return data.getToken(); } /** * Get the scope for this function * @return the scope
*** 905,915 **** // apply new filter final Class<?>[] ctorArgs = ctorType.dropParameterTypes(0, 1).parameterArray(); // drop self MethodHandle handle = MH.foldArguments(MH.dropArguments(NEWFILTER, 2, ctorArgs), constructor); ! if (hasCalleeParameter()) { handle = MH.foldArguments(handle, ALLOCATE); } else { handle = MH.filterArguments(handle, 0, ALLOCATE); } --- 689,699 ---- // apply new filter final Class<?>[] ctorArgs = ctorType.dropParameterTypes(0, 1).parameterArray(); // drop self MethodHandle handle = MH.foldArguments(MH.dropArguments(NEWFILTER, 2, ctorArgs), constructor); ! if (data.needsCallee()) { handle = MH.foldArguments(handle, ALLOCATE); } else { handle = MH.filterArguments(handle, 0, ALLOCATE); }
*** 956,971 **** } MethodHandle boundHandle; MethodHandle guard = null; ! if (hasCalleeParameter()) { final MethodHandle callHandle = getBestSpecializedInvokeHandle(type); if(NashornCallSiteDescriptor.isScope(desc)) { // (this, callee, args...) => (callee, args...) => (callee, [this], args...) ! boundHandle = MH.bindTo(callHandle, isNonStrictFunction() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED); boundHandle = MH.dropArguments(boundHandle, 1, Object.class); } else { // (this, callee, args...) permute => (callee, this, args...) which is what we get in final MethodType oldType = callHandle.type(); final int[] reorder = new int[oldType.parameterCount()]; --- 740,755 ---- } MethodHandle boundHandle; MethodHandle guard = null; ! if (data.needsCallee()) { final MethodHandle callHandle = getBestSpecializedInvokeHandle(type); if(NashornCallSiteDescriptor.isScope(desc)) { // (this, callee, args...) => (callee, args...) => (callee, [this], args...) ! boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED); boundHandle = MH.dropArguments(boundHandle, 1, Object.class); } else { // (this, callee, args...) permute => (callee, this, args...) which is what we get in final MethodType oldType = callHandle.type(); final int[] reorder = new int[oldType.parameterCount()];
*** 978,988 **** boundHandle = MethodHandles.permuteArguments(callHandle, newType, reorder); // For non-strict functions, check whether this-object is primitive type. // If so add a to-object-wrapper argument filter. // Else install a guard that will trigger a relink when the argument becomes primitive. ! if (isNonStrictFunction()) { if (isPrimitiveThis(request.getArguments()[1])) { boundHandle = MH.filterArguments(boundHandle, 1, WRAPFILTER); } else { guard = NashornGuards.getNonStrictFunctionGuard(this); } --- 762,772 ---- boundHandle = MethodHandles.permuteArguments(callHandle, newType, reorder); // For non-strict functions, check whether this-object is primitive type. // If so add a to-object-wrapper argument filter. // Else install a guard that will trigger a relink when the argument becomes primitive. ! if (needsWrappedThis()) { if (isPrimitiveThis(request.getArguments()[1])) { boundHandle = MH.filterArguments(boundHandle, 1, WRAPFILTER); } else { guard = NashornGuards.getNonStrictFunctionGuard(this); }
*** 990,1000 **** } } else { final MethodHandle callHandle = getBestSpecializedInvokeHandle(type.dropParameterTypes(0, 1)); if(NashornCallSiteDescriptor.isScope(desc)) { ! boundHandle = MH.bindTo(callHandle, isNonStrictFunction() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED); boundHandle = MH.dropArguments(boundHandle, 0, Object.class, Object.class); } else { boundHandle = MH.dropArguments(callHandle, 0, Object.class); } } --- 774,784 ---- } } else { final MethodHandle callHandle = getBestSpecializedInvokeHandle(type.dropParameterTypes(0, 1)); if(NashornCallSiteDescriptor.isScope(desc)) { ! boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED); boundHandle = MH.dropArguments(boundHandle, 0, Object.class, Object.class); } else { boundHandle = MH.dropArguments(callHandle, 0, Object.class); } }
*** 1010,1026 **** */ MethodHandle getCallMethodHandle(final MethodType type, final String bindName) { MethodHandle methodHandle = getBestSpecializedInvokeHandle(type); if (bindName != null) { ! if (hasCalleeParameter()) { methodHandle = MH.insertArguments(methodHandle, 1, this, bindName); } else { methodHandle = MH.insertArguments(methodHandle, 1, bindName); } } else { ! if (hasCalleeParameter()) { methodHandle = MH.insertArguments(methodHandle, 1, this); } } return pairArguments(methodHandle, type); --- 794,810 ---- */ MethodHandle getCallMethodHandle(final MethodType type, final String bindName) { MethodHandle methodHandle = getBestSpecializedInvokeHandle(type); if (bindName != null) { ! if (data.needsCallee()) { methodHandle = MH.insertArguments(methodHandle, 1, this, bindName); } else { methodHandle = MH.insertArguments(methodHandle, 1, bindName); } } else { ! if (data.needsCallee()) { methodHandle = MH.insertArguments(methodHandle, 1, this); } } return pairArguments(methodHandle, type);
*** 1032,1042 **** * @param thiz the this argument * * @return the converted this object */ protected Object convertThisObject(final Object thiz) { ! if (!(thiz instanceof ScriptObject) && isNonStrictFunction()) { if (JSType.nullOrUndefined(thiz)) { return Context.getGlobalTrusted(); } if (isPrimitiveThis(thiz)) { --- 816,826 ---- * @param thiz the this argument * * @return the converted this object */ protected Object convertThisObject(final Object thiz) { ! if (!(thiz instanceof ScriptObject) && needsWrappedThis()) { if (JSType.nullOrUndefined(thiz)) { return Context.getGlobalTrusted(); } if (isPrimitiveThis(thiz)) {