diff options
Diffstat (limited to 'src/jdk/nashorn/internal/runtime/ScriptObject.java')
-rw-r--r-- | src/jdk/nashorn/internal/runtime/ScriptObject.java | 417 |
1 files changed, 221 insertions, 196 deletions
diff --git a/src/jdk/nashorn/internal/runtime/ScriptObject.java b/src/jdk/nashorn/internal/runtime/ScriptObject.java index 1942ec22..93517201 100644 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java @@ -28,6 +28,7 @@ package jdk.nashorn.internal.runtime; import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall; import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; +import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE; @@ -39,7 +40,6 @@ import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow; import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; -import static jdk.nashorn.internal.lookup.Lookup.MH; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -61,12 +61,13 @@ import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.nashorn.internal.codegen.CompilerConstants.Call; 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.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.linker.Bootstrap; -import jdk.nashorn.internal.lookup.Lookup; -import jdk.nashorn.internal.lookup.MethodHandleFactory; +import jdk.nashorn.internal.runtime.linker.LinkerCallSite; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.linker.NashornGuards; @@ -901,7 +902,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr final MethodHandle getter = find.getGetter(int.class); if (getter != null) { try { - return (int)getter.invokeExact((Object)find.getOwner()); + return (int)getter.invokeExact((Object)find.getGetterReceiver()); } catch (final Error|RuntimeException e) { throw e; } catch (final Throwable e) { @@ -916,7 +917,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr final MethodHandle getter = find.getGetter(long.class); if (getter != null) { try { - return (long)getter.invokeExact((Object)find.getOwner()); + return (long)getter.invokeExact((Object)find.getGetterReceiver()); } catch (final Error|RuntimeException e) { throw e; } catch (final Throwable e) { @@ -931,7 +932,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr final MethodHandle getter = find.getGetter(double.class); if (getter != null) { try { - return (double)getter.invokeExact((Object)find.getOwner()); + return (double)getter.invokeExact((Object)find.getGetterReceiver()); } catch (final Error|RuntimeException e) { throw e; } catch (final Throwable e) { @@ -953,7 +954,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr final MethodHandle getter = find.getGetter(Object.class); if (getter != null) { try { - return getter.invokeExact((Object)find.getOwner()); + return getter.invokeExact((Object)find.getGetterReceiver()); } catch (final Error|RuntimeException e) { throw e; } catch (final Throwable e) { @@ -1679,12 +1680,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr * @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(2); - - if (request.isCallSiteUnstable()) { - return findMegaMorphicGetMethod(desc, name); - } - + final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); final FindProperty find = findProperty(name, true); MethodHandle methodHandle; @@ -1700,6 +1696,10 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr throw new AssertionError(); // never invoked with any other operation } + if (request.isCallSiteUnstable()) { + return findMegaMorphicGetMethod(desc, name); + } + final Class<?> returnType = desc.getMethodType().returnType(); final Property property = find.getProperty(); methodHandle = find.getGetter(returnType); @@ -1727,7 +1727,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr } private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name) { - final GuardedInvocation inv = findGetIndexMethod(desc.getMethodType().insertParameterTypes(1, Object.class)); + final MethodType mhType = desc.getMethodType().insertParameterTypes(1, Object.class); + final GuardedInvocation inv = findGetIndexMethod(mhType); + return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard()); } @@ -1890,8 +1892,8 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr } private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) { - final GuardedInvocation inv = findSetIndexMethod(desc.getMethodType().insertParameterTypes(1, Object.class), - NashornCallSiteDescriptor.isStrict(desc)); + 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()); } @@ -1949,7 +1951,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr * @return GuardedInvocation to be invoked at call site. */ public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc, final LinkRequest request) { - final String name = desc.getNameToken(2); + final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true); final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc); @@ -1973,6 +1975,24 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr return createEmptyGetter(desc, name); } + /** + * Invoke fall back if a property is not found. + * @param name Name of property. + * @return Result from call. + */ + private Object invokeNoSuchProperty(final String name) { + final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true); + + if (find != null) { + final Object func = getObjectValue(find); + + if (func instanceof ScriptFunction) { + return ScriptRuntime.apply((ScriptFunction)func, this, name); + } + } + + return UNDEFINED; + } private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) { return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(name), NashornGuards.getMapGuard(getMap())); @@ -2120,8 +2140,11 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr * * Make sure arguments are paired correctly. * @param methodHandle MethodHandle to adjust. - * @param callType MethodType of caller. - * @param callerVarArg true if the caller is vararg, false otherwise, null if it should be inferred. + * @param callType MethodType of the call site. + * @param callerVarArg true if the caller is vararg, false otherwise, null if it should be inferred from the + * {@code callType}; basically, if the last parameter type of the call site is an array, it'll be considered a + * variable arity call site. These are ordinarily rare; Nashorn code generator creates variable arity call sites + * when the call has more than {@link LinkerCallSite#ARGLIMIT} parameters. * * @return method handle with adjusted arguments */ @@ -2136,7 +2159,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr final int callCount = callType.parameterCount(); final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray(); - final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : (callCount > 1 && + final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : (callCount > 0 && callType.parameterType(callCount - 1).isArray()); if (callCount < parameterCount) { @@ -2239,310 +2262,314 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr setArray(getArray().shrink(newLength)); getArray().setLength(newLength); } - } + } - @Override - public int getInt(final Object key) { - final int index = getArrayIndexNoThrow(key); + private int getInt(final int index, final String key) { + if (isValidArrayIndex(index)) { + for (ScriptObject object = this; ; ) { + final FindProperty find = object.findProperty(key, false, false, this); - if (getArray().has(index)) { - return getArray().getInt(index); - } + if (find != null) { + return getIntValue(find); + } - final FindProperty find = findProperty(convertKey(key), false); + if ((object = object.getProto()) == null) { + break; + } - if (find != null) { - return getIntValue(find); - } + final ArrayData array = object.getArray(); + + if (array.has(index)) { + return array.getInt(index); + } + } + } else { + final FindProperty find = findProperty(key, true); - final ScriptObject proto = this.getProto(); + if (find != null) { + return getIntValue(find); + } + } - return proto != null ? proto.getInt(key) : 0; + return JSType.toInt32(invokeNoSuchProperty(key)); } @Override - public int getInt(final double key) { + public int getInt(final Object key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getInt(index); + if (array.has(index)) { + return array.getInt(index); } - final FindProperty find = findProperty(convertKey(key), false); + return getInt(index, convertKey(key)); + } - if (find != null) { - return getIntValue(find); - } + @Override + public int getInt(final double key) { + final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - final ScriptObject proto = this.getProto(); + if (array.has(index)) { + return array.getInt(index); + } - return proto != null ? proto.getInt(key) : 0; + return getInt(index, convertKey(key)); } @Override public int getInt(final long key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getInt(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getIntValue(find); + if (array.has(index)) { + return array.getInt(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.getInt(key) : 0; + return getInt(index, convertKey(key)); } @Override public int getInt(final int key) { - final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getInt(index); + if (array.has(key)) { + return array.getInt(key); } - final FindProperty find = findProperty(convertKey(key), false); + return getInt(key, convertKey(key)); + } - if (find != null) { - return getIntValue(find); - } + private long getLong(final int index, final String key) { + if (isValidArrayIndex(index)) { + for (ScriptObject object = this; ; ) { + final FindProperty find = object.findProperty(key, false, false, this); - final ScriptObject proto = this.getProto(); + if (find != null) { + return getLongValue(find); + } - return proto != null ? proto.getInt(key) : 0; + if ((object = object.getProto()) == null) { + break; + } + + final ArrayData array = object.getArray(); + + if (array.has(index)) { + return array.getLong(index); + } + } + } else { + final FindProperty find = findProperty(key, true); + + if (find != null) { + return getLongValue(find); + } + } + + return JSType.toLong(invokeNoSuchProperty(key)); } @Override public long getLong(final Object key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getLong(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getLongValue(find); + if (array.has(index)) { + return array.getLong(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.getLong(key) : 0L; + return getLong(index, convertKey(key)); } @Override public long getLong(final double key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getLong(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getLongValue(find); + if (array.has(index)) { + return array.getLong(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.getLong(key) : 0L; + return getLong(index, convertKey(key)); } @Override public long getLong(final long key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getLong(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getLongValue(find); + if (array.has(index)) { + return array.getLong(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.getLong(key) : 0L; + return getLong(index, convertKey(key)); } @Override public long getLong(final int key) { - final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getLong(index); + if (array.has(key)) { + return array.getLong(key); } - final FindProperty find = findProperty(convertKey(key), false); + return getLong(key, convertKey(key)); + } - if (find != null) { - return getLongValue(find); - } + private double getDouble(final int index, final String key) { + if (isValidArrayIndex(index)) { + for (ScriptObject object = this; ; ) { + final FindProperty find = object.findProperty(key, false, false, this); - final ScriptObject proto = this.getProto(); + if (find != null) { + return getDoubleValue(find); + } + + if ((object = object.getProto()) == null) { + break; + } + + final ArrayData array = object.getArray(); + + if (array.has(index)) { + return array.getDouble(index); + } + } + } else { + final FindProperty find = findProperty(key, true); - return proto != null ? proto.getLong(key) : 0L; + if (find != null) { + return getDoubleValue(find); + } + } + + return JSType.toNumber(invokeNoSuchProperty(key)); } @Override public double getDouble(final Object key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getDouble(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getDoubleValue(find); + if (array.has(index)) { + return array.getDouble(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.getDouble(key) : Double.NaN; + return getDouble(index, convertKey(key)); } @Override public double getDouble(final double key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getDouble(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getDoubleValue(find); + if (array.has(index)) { + return array.getDouble(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.getDouble(key) : Double.NaN; + return getDouble(index, convertKey(key)); } @Override public double getDouble(final long key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getDouble(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getDoubleValue(find); + if (array.has(index)) { + return array.getDouble(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.getDouble(key) : Double.NaN; + return getDouble(index, convertKey(key)); } @Override public double getDouble(final int key) { - final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getDouble(index); + if (array.has(key)) { + return array.getDouble(key); } - final FindProperty find = findProperty(convertKey(key), false); + return getDouble(key, convertKey(key)); + } - if (find != null) { - return getDoubleValue(find); - } + private Object get(final int index, final String key) { + if (isValidArrayIndex(index)) { + for (ScriptObject object = this; ; ) { + final FindProperty find = object.findProperty(key, false, false, this); + + if (find != null) { + return getObjectValue(find); + } + + if ((object = object.getProto()) == null) { + break; + } + + final ArrayData array = object.getArray(); + + if (array.has(index)) { + return array.getObject(index); + } + } + } else { + final FindProperty find = findProperty(key, true); - final ScriptObject proto = this.getProto(); + if (find != null) { + return getObjectValue(find); + } + } - return proto != null ? proto.getDouble(key) : Double.NaN; + return invokeNoSuchProperty(key); } @Override public Object get(final Object key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getObject(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getObjectValue(find); + if (array.has(index)) { + return array.getObject(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.get(key) : UNDEFINED; + return get(index, convertKey(key)); } @Override public Object get(final double key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getObject(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getObjectValue(find); + if (array.has(index)) { + return array.getObject(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.get(key) : UNDEFINED; + return get(index, convertKey(key)); } @Override public Object get(final long key) { final int index = getArrayIndexNoThrow(key); + final ArrayData array = getArray(); - if (getArray().has(index)) { - return getArray().getObject(index); - } - - final FindProperty find = findProperty(convertKey(key), false); - - if (find != null) { - return getObjectValue(find); + if (array.has(index)) { + return array.getObject(index); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.get(key) : UNDEFINED; + return get(index, convertKey(key)); } @Override public Object get(final int key) { - final int index = getArrayIndexNoThrow(key); - - if (getArray().has(index)) { - return getArray().getObject(index); - } - - final FindProperty find = findProperty(convertKey(key), false); + final ArrayData array = getArray(); - if (find != null) { - return getObjectValue(find); + if (array.has(key)) { + return array.getObject(key); } - final ScriptObject proto = this.getProto(); - - return proto != null ? proto.get(key) : UNDEFINED; + return get(key, convertKey(key)); } /** @@ -2554,7 +2581,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr */ private void doesNotHave(final int index, final Object value, final boolean strict) { final long oldLength = getArray().length(); - final long longIndex = index & 0xffff_ffffL; + final long longIndex = index & JSType.MAX_UINT; if (!getArray().has(index)) { final String key = convertKey(longIndex); @@ -2613,8 +2640,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr f = null; } - MethodHandle setter; - if (f != null) { if (!f.getProperty().isWritable()) { if (strict) { @@ -2624,9 +2649,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr return; } - setter = f.getSetter(Object.class, strict); //TODO specfields try { - setter.invokeExact((Object)f.getOwner(), value); + final MethodHandle setter = f.getSetter(Object.class, strict); //TODO specfields + setter.invokeExact((Object)f.getSetterReceiver(), value); } catch (final Error|RuntimeException e) { throw e; } catch (final Throwable e) { |