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