src/jdk/nashorn/internal/runtime/ScriptObject.java
Print this page
*** 64,73 ****
--- 64,74 ----
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
import jdk.nashorn.internal.objects.DataPropertyDescriptor;
+ import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
*** 129,144 ****
/** Indexed array data. */
private ArrayData arrayData;
static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class);
static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class);
! static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class);
static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
static final MethodHandle SETSPILLWITHNEW = findOwnMH("setSpillWithNew", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
static final MethodHandle SETSPILLWITHGROW = findOwnMH("setSpillWithGrow", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, int.class, Object.class, Object.class);
private static final MethodHandle TRUNCATINGFILTER = findOwnMH("truncatingFilter", Object[].class, int.class, Object[].class);
private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
private static final ArrayList<MethodHandle> protoFilters = new ArrayList<>();
--- 130,146 ----
/** Indexed array data. */
private ArrayData arrayData;
static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class);
static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class);
! static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class, boolean.class);
static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
static final MethodHandle SETSPILLWITHNEW = findOwnMH("setSpillWithNew", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
static final MethodHandle SETSPILLWITHGROW = findOwnMH("setSpillWithGrow", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, int.class, Object.class, Object.class);
+ static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
private static final MethodHandle TRUNCATINGFILTER = findOwnMH("truncatingFilter", Object[].class, int.class, Object[].class);
private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
private static final ArrayList<MethodHandle> protoFilters = new ArrayList<>();
*** 1738,1748 ****
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
if (request.isCallSiteUnstable() || hasWithScope()) {
! return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator));
}
final FindProperty find = findProperty(name, true);
MethodHandle methodHandle;
--- 1740,1750 ----
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
if (request.isCallSiteUnstable() || hasWithScope()) {
! return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator), isScope() && NashornCallSiteDescriptor.isScope(desc));
}
final FindProperty find = findProperty(name, true);
MethodHandle methodHandle;
*** 1763,1810 ****
final Class<?> returnType = desc.getMethodType().returnType();
final Property property = find.getProperty();
methodHandle = find.getGetter(returnType);
! final boolean noGuard = ObjectClassGenerator.OBJECT_FIELDS_ONLY && NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType();
! // getMap() is fine as we have the prototype switchpoint depending on where the property was found
! final MethodHandle guard = noGuard ? null : NashornGuards.getMapGuard(getMap());
final ScriptObject owner = find.getOwner();
if (methodHandle != null) {
assert methodHandle.type().returnType().equals(returnType);
if (find.isSelf()) {
return new GuardedInvocation(methodHandle, guard);
}
if (!property.hasGetterFunction(owner)) {
! // If not a scope bind to actual prototype as changing prototype will change the property map.
! // For scopes we install a filter that replaces the self object with the prototype owning the property.
! methodHandle = isScope() ?
! addProtoFilter(methodHandle, find.getProtoChainLength()) :
! bindTo(methodHandle, owner);
}
! return new GuardedInvocation(methodHandle, noGuard ? null : getProtoSwitchPoint(name, owner), guard);
}
assert !NashornCallSiteDescriptor.isFastScope(desc);
return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard);
}
! private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
! final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
final MethodHandle guard = getScriptObjectGuard(desc.getMethodType());
return new GuardedInvocation(invoker, guard);
}
@SuppressWarnings("unused")
! private Object megamorphicGet(final String key, final boolean isMethod) {
final FindProperty find = findProperty(key, true);
if (find != null) {
return getObjectValue(find);
}
return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key);
}
/**
--- 1765,1812 ----
final Class<?> returnType = desc.getMethodType().returnType();
final Property property = find.getProperty();
methodHandle = find.getGetter(returnType);
! // Get the appropriate guard for this callsite and property.
! final MethodHandle guard = NashornGuards.getGuard(this, property, desc);
final ScriptObject owner = find.getOwner();
if (methodHandle != null) {
assert methodHandle.type().returnType().equals(returnType);
if (find.isSelf()) {
return new GuardedInvocation(methodHandle, guard);
}
if (!property.hasGetterFunction(owner)) {
! // Add a filter that replaces the self object with the prototype owning the property.
! methodHandle = addProtoFilter(methodHandle, find.getProtoChainLength());
}
! return new GuardedInvocation(methodHandle, guard == null ? null : getProtoSwitchPoint(name, owner), guard);
}
assert !NashornCallSiteDescriptor.isFastScope(desc);
return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard);
}
! private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name,
! final boolean isMethod, final boolean isScope) {
! final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, isScope);
final MethodHandle guard = getScriptObjectGuard(desc.getMethodType());
return new GuardedInvocation(invoker, guard);
}
@SuppressWarnings("unused")
! private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
final FindProperty find = findProperty(key, true);
if (find != null) {
return getObjectValue(find);
}
+ if (isScope) {
+ throw referenceError("not.defined", key);
+ }
return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key);
}
/**
*** 1994,2003 ****
--- 1996,2014 ----
} else {
obj.set(desc.getNameToken(2), value, isStrict);
}
}
+ @SuppressWarnings("unused")
+ private static Object globalFilter(final Object object) {
+ ScriptObject sobj = (ScriptObject) object;
+ while (sobj != null && !(sobj instanceof Global)) {
+ sobj = sobj.getProto();
+ }
+ return sobj;
+ }
+
private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
final GuardedInvocation inv = findSetIndexMethod(type, NashornCallSiteDescriptor.isStrict(desc));
return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
}
*** 2821,2831 ****
} else if (!isExtensible()) {
if (strict) {
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
}
} else {
! spill(key, value);
}
}
private void spill(final String key, final Object value) {
addSpillProperty(key, 0).setObjectValue(this, this, value, false);
--- 2832,2850 ----
} else if (!isExtensible()) {
if (strict) {
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
}
} else {
! ScriptObject sobj = this;
! // undefined scope properties are set in the global object.
! if (isScope()) {
! while (sobj != null && !(sobj instanceof Global)) {
! sobj = sobj.getProto();
! }
! assert sobj != null : "no parent global object in scope";
! }
! sobj.spill(key, value);
}
}
private void spill(final String key, final Object value) {
addSpillProperty(key, 0).setObjectValue(this, this, value, false);