src/jdk/nashorn/internal/runtime/ScriptFunction.java
Print this page
rev 755 : 8035948: Redesign property listeners for shared classes
Reviewed-by: sundar, lagergren
rev 758 : 8021350: Share script classes between threads/globals within context
Reviewed-by: lagergren, sundar
rev 760 : 8037400: Remove getInitialMap getters and GlobalObject interface
Reviewed-by: lagergren, jlaskey, attila
@@ -36,10 +36,11 @@
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
/**
* Runtime representation of a JavaScript function.
@@ -64,10 +65,12 @@
/** Method handle for allocate function for this ScriptFunction */
static final MethodHandle ALLOCATE = findOwnMH("allocate", Object.class);
private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class);
+ private static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
+
/** method handle to scope getter for this ScriptFunction */
public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class);
private static final MethodHandle IS_FUNCTION_MH = findOwnMH("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class);
@@ -78,33 +81,32 @@
/** The parent scope. */
private final ScriptObject scope;
private final ScriptFunctionData data;
+ /** The property map used for newly allocated object when function is used as constructor. */
+ protected PropertyMap 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 specs specialized version of this function - other method handles
- * @param strict is this a strict mode function?
- * @param builtin is this a built in function?
- * @param isConstructor is this a constructor?
+ * @param flags {@link ScriptFunctionData} flags
*/
protected ScriptFunction(
final String name,
final MethodHandle methodHandle,
final PropertyMap map,
final ScriptObject scope,
final MethodHandle[] specs,
- final boolean strict,
- final boolean builtin,
- final boolean isConstructor) {
+ final int flags) {
- this(new FinalScriptFunctionData(name, methodHandle, specs, strict, builtin, isConstructor), map, scope);
+ this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope);
}
/**
* Constructor
*
@@ -123,10 +125,11 @@
constructorCount++;
}
this.data = data;
this.scope = scope;
+ this.allocatorMap = data.getAllocatorMap();
}
@Override
public String getClassName() {
return "Function";
@@ -227,20 +230,20 @@
if (Context.DEBUG) {
allocations++;
}
assert !isBoundFunction(); // allocate never invoked on bound functions
- final ScriptObject object = data.allocate();
+ final ScriptObject object = data.allocate(allocatorMap);
if (object != null) {
Object prototype = getPrototype();
if (prototype instanceof ScriptObject) {
- object.setProto((ScriptObject)prototype);
+ object.setInitialProto((ScriptObject)prototype);
}
if (object.getProto() == null) {
- object.setProto(getObjectPrototype());
+ object.setInitialProto(getObjectPrototype());
}
}
return object;
}
@@ -471,11 +474,18 @@
@SuppressWarnings("unused")
private static Object wrapFilter(final Object obj) {
if (obj instanceof ScriptObject || !ScriptFunctionData.isPrimitiveThis(obj)) {
return obj;
}
- return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(obj);
+ return Context.getGlobal().wrapAsObject(obj);
+ }
+
+
+ @SuppressWarnings("unused")
+ private static Object globalFilter(final Object object) {
+ // replace whatever we get with the current global object
+ return Context.getGlobal();
}
/**
* dyn:call call site signature: (callee, thiz, [args...])
* generated method signature: (callee, thiz, [args...])
@@ -489,52 +499,47 @@
* (4) for normal this-calls, drop callee.
*/
@Override
protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final MethodType type = desc.getMethodType();
+ final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
if (request.isCallSiteUnstable()) {
- // (this, callee, args...) => (this, callee, args[])
- final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class,
- type.parameterCount() - 2);
+ // (callee, this, args...) => (callee, this, args[])
+ final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2);
// If call site is statically typed to take a ScriptFunction, we don't need a guard, otherwise we need a
// generic "is this a ScriptFunction?" guard.
return new GuardedInvocation(collector, ScriptFunction.class.isAssignableFrom(desc.getMethodType().parameterType(0))
? null : NashornGuards.getScriptFunctionGuard());
}
MethodHandle boundHandle;
MethodHandle guard = null;
- final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
-
if (data.needsCallee()) {
final MethodHandle callHandle = getBestInvoker(type, request.getArguments());
- if (scopeCall) {
+ if (scopeCall && needsWrappedThis()) {
// Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
- // (callee, this, args...) => (callee, args...)
- boundHandle = MH.insertArguments(callHandle, 1, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
- // (callee, args...) => (callee, [this], args...)
- boundHandle = MH.dropArguments(boundHandle, 1, Object.class);
-
+ // (callee, this, args...) => (callee, [this], args...)
+ boundHandle = MH.filterArguments(callHandle, 1, GLOBALFILTER);
} else {
// It's already (callee, this, args...), just what we need
boundHandle = callHandle;
}
} else {
final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1), request.getArguments());
if (data.isBuiltin() && "extend".equals(data.getName())) {
// NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
// current lookup as its "this" so it can do security-sensitive creation of adapter classes.
boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class);
- } else if (scopeCall) {
+ } else if (scopeCall && needsWrappedThis()) {
// Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
- // (this, args...) => (args...)
- boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
- // (args...) => ([callee], [this], args...)
- boundHandle = MH.dropArguments(boundHandle, 0, Object.class, Object.class);
+ // (this, args...) => ([this], args...)
+ boundHandle = MH.filterArguments(callHandle, 0, GLOBALFILTER);
+ // ([this], args...) => ([callee], [this], args...)
+ boundHandle = MH.dropArguments(boundHandle, 0, Object.class);
} else {
// (this, args...) => ([callee], this, args...)
boundHandle = MH.dropArguments(callHandle, 0, Object.class);
}
}