# HG changeset patch # User hannesw # Date 1359131731 -3600 # Node ID 3f6c0ab2597ae094560ca70cbd38c1fc4f77e418 # Parent 3d0b930f4b47f5d3dd173c57e1c152cd8dbd56aa 8006766: Array-like access to characters of a string is slow Reviewed-by: lagergren, attila diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/objects/Global.java --- a/nashorn/src/jdk/nashorn/internal/objects/Global.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java Fri Jan 25 17:35:31 2013 +0100 @@ -55,9 +55,9 @@ import jdk.nashorn.internal.runtime.ScriptingFunctions; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.linker.InvokeByName; -import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.scripts.JO$; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; /** * Representation of global scope. @@ -427,22 +427,19 @@ } else if (obj instanceof Boolean) { return NativeBoolean.WRAPFILTER; } - throw new IllegalArgumentException("Unsupported primitive value: " + obj); + throw new IllegalArgumentException("Unsupported primitive: " + obj); } @Override - public GuardedInvocation numberLookup(final NashornCallSiteDescriptor callSite, final Number self) { - return NativeNumber.lookupPrimitive(callSite, self); - } - - @Override - public GuardedInvocation stringLookup(final NashornCallSiteDescriptor callSite, final CharSequence self) { - return NativeString.lookupPrimitive(callSite, self); - } - - @Override - public GuardedInvocation booleanLookup(final NashornCallSiteDescriptor callSite, final Boolean self) { - return NativeBoolean.lookupPrimitive(callSite, self); + public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) { + if (self instanceof String || self instanceof ConsString) { + return NativeString.lookupPrimitive(request, self); + } else if (self instanceof Number) { + return NativeNumber.lookupPrimitive(request, self); + } else if (self instanceof Boolean) { + return NativeBoolean.lookupPrimitive(request, self); + } + throw new IllegalArgumentException("Unsupported primitive: " + self); } @Override diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java Fri Jan 25 17:35:31 2013 +0100 @@ -38,9 +38,9 @@ import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.linker.MethodHandleFactory; -import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.linker.PrimitiveLookup; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; /** * ECMA 15.6 Boolean Objects. @@ -153,12 +153,12 @@ /** * Lookup the appropriate method for an invoke dynamic call. * - * @param desc The invoke dynamic callsite descriptor. + * @param request The link request * @param receiver The receiver for the call * @return Link to be invoked at call site. */ - public static GuardedInvocation lookupPrimitive(final NashornCallSiteDescriptor desc, final Object receiver) { - return PrimitiveLookup.lookupPrimitive(desc, Boolean.class, new NativeBoolean((Boolean)receiver), WRAPFILTER); + public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) { + return PrimitiveLookup.lookupPrimitive(request, Boolean.class, new NativeBoolean((Boolean)receiver), WRAPFILTER); } /** diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Fri Jan 25 17:35:31 2013 +0100 @@ -47,6 +47,7 @@ import jdk.nashorn.internal.runtime.linker.MethodHandleFactory; import org.dynalang.dynalink.CallSiteDescriptor; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; /** * This class is the implementation of the Nashorn-specific global object named {@code JSAdapter}. It can be @@ -580,10 +581,10 @@ } @Override - protected GuardedInvocation findCallMethodMethod(final CallSiteDescriptor desc, final boolean megaMorphic) { + protected GuardedInvocation findCallMethodMethod(final CallSiteDescriptor desc, final LinkRequest request) { if (overrides && super.hasOwnProperty(desc.getNameToken(2))) { try { - final GuardedInvocation inv = super.findCallMethodMethod(desc, megaMorphic); + final GuardedInvocation inv = super.findCallMethodMethod(desc, request); if (inv != null) { return inv; } @@ -596,11 +597,11 @@ } @Override - protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final boolean megaMorphic, final String operation) { + protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operation) { final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); if (overrides && super.hasOwnProperty(name)) { try { - final GuardedInvocation inv = super.findGetMethod(desc, megaMorphic, operation); + final GuardedInvocation inv = super.findGetMethod(desc, request, operation); if (inv != null) { return inv; } @@ -633,10 +634,10 @@ } @Override - protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final boolean megaMorphic) { + protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { if (overrides && super.hasOwnProperty(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) { try { - final GuardedInvocation inv = super.findSetMethod(desc, megaMorphic); + final GuardedInvocation inv = super.findSetMethod(desc, request); if (inv != null) { return inv; } diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Fri Jan 25 17:35:31 2013 +0100 @@ -34,6 +34,7 @@ import org.dynalang.dynalink.CallSiteDescriptor; import org.dynalang.dynalink.beans.StaticClass; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; /** * This is "JavaImporter" constructor. This constructor allows you to use Java types omitting explicit package names. @@ -107,13 +108,13 @@ } @Override - public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc) { - return createAndSetProperty(desc) ? super.lookup(desc) : super.noSuchProperty(desc); + public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc, final LinkRequest request) { + return createAndSetProperty(desc) ? super.lookup(desc, request) : super.noSuchProperty(desc, request); } @Override - public GuardedInvocation noSuchMethod(final CallSiteDescriptor desc) { - return createAndSetProperty(desc) ? super.lookup(desc) : super.noSuchMethod(desc); + public GuardedInvocation noSuchMethod(final CallSiteDescriptor desc, final LinkRequest request) { + return createAndSetProperty(desc) ? super.lookup(desc, request) : super.noSuchMethod(desc, request); } private boolean createAndSetProperty(final CallSiteDescriptor desc) { diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java Fri Jan 25 17:35:31 2013 +0100 @@ -46,9 +46,9 @@ import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.linker.MethodHandleFactory; -import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.linker.PrimitiveLookup; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; /** * ECMA 15.7 Number Objects. @@ -317,12 +317,12 @@ /** * Lookup the appropriate method for an invoke dynamic call. - * @param desc The call site descriptor. + * @param request The link request * @param receiver receiver of call * @return Link to be invoked at call site. */ - public static GuardedInvocation lookupPrimitive(final NashornCallSiteDescriptor desc, final Object receiver) { - return PrimitiveLookup.lookupPrimitive(desc, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER); + public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) { + return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER); } @SuppressWarnings("unused") diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/objects/NativeString.java --- a/nashorn/src/jdk/nashorn/internal/objects/NativeString.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java Fri Jan 25 17:35:31 2013 +0100 @@ -55,10 +55,11 @@ import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.arrays.ArrayIndex; 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.linker.PrimitiveLookup; +import org.dynalang.dynalink.CallSiteDescriptor; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; /** @@ -123,6 +124,59 @@ return value.length(); } + // This is to provide array-like access to string characters without creating a NativeString wrapper. + @Override + protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) { + final Object self = request.getReceiver(); + final Class returnType = desc.getMethodType().returnType(); + + if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) { + try { + MethodHandle mh = MethodHandles.lookup().findStatic(NativeString.class, "get", desc.getMethodType()); + return new GuardedInvocation(mh, NashornGuards.getInstanceOf2Guard(String.class, ConsString.class)); + } catch (final NoSuchMethodException | IllegalAccessException e) { + // Shouldn't happen. Fall back to super + } + } + return super.findGetIndexMethod(desc, request); + } + + @SuppressWarnings("unused") + private static Object get(final Object self, final Object key) { + final CharSequence cs = JSType.toCharSequence(self); + final int index = getArrayIndexNoThrow(key); + if (index >= 0 && index < cs.length()) { + return String.valueOf(cs.charAt(index)); + } + return ((ScriptObject) Global.toObject(self)).get(key); + } + + @SuppressWarnings("unused") + private static Object get(final Object self, final double key) { + if (isRepresentableAsInt(key)) { + return get(self, (int)key); + } + return ((ScriptObject) Global.toObject(self)).get(key); + } + + @SuppressWarnings("unused") + private static Object get(final Object self, final long key) { + final CharSequence cs = JSType.toCharSequence(self); + if (key >= 0 && key < cs.length()) { + return String.valueOf(cs.charAt((int)key)); + } + return ((ScriptObject) Global.toObject(self)).get(key); + } + + @SuppressWarnings("unused") + private static Object get(final Object self, final int key) { + final CharSequence cs = JSType.toCharSequence(self); + if (key >= 0 && key < cs.length()) { + return String.valueOf(cs.charAt(key)); + } + return ((ScriptObject) Global.toObject(self)).get(key); + } + // String characters can be accessed with array-like indexing.. @Override public Object get(final Object key) { @@ -1066,13 +1120,13 @@ /** * Lookup the appropriate method for an invoke dynamic call. * - * @param desc the call site descriptor + * @param request the link request * @param receiver receiver of call * @return Link to be invoked at call site. */ - public static GuardedInvocation lookupPrimitive(final NashornCallSiteDescriptor desc, final Object receiver) { + public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) { final MethodHandle guard = NashornGuards.getInstanceOf2Guard(String.class, ConsString.class); - return PrimitiveLookup.lookupPrimitive(desc, guard, new NativeString((CharSequence)receiver), WRAPFILTER); + return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER); } @SuppressWarnings("unused") diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java --- a/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java Fri Jan 25 17:35:31 2013 +0100 @@ -26,8 +26,8 @@ package jdk.nashorn.internal.runtime; import java.lang.invoke.MethodHandle; -import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; /** * Runtime interface to the global scope of the current context. @@ -79,34 +79,15 @@ public MethodHandle getWrapFilter(Object obj); /** - * Wrapper for {@link jdk.nashorn.internal.objects.Global#numberLookup(NashornCallSiteDescriptor, Number)} + * Wrapper for {@link jdk.nashorn.internal.objects.Global#primitiveLookup(LinkRequest, Object)} * - * @param callSite call site descriptor + * @param request the link request for the dynamic call site. * @param self self reference * * @return guarded invocation */ - public GuardedInvocation numberLookup(NashornCallSiteDescriptor callSite, Number self); + public GuardedInvocation primitiveLookup(LinkRequest request, Object self); - /** - * Wrapper for {@link jdk.nashorn.internal.objects.Global#stringLookup(NashornCallSiteDescriptor, CharSequence)} - * - * @param callSite call site descriptor - * @param self self reference - * - * @return guarded invocation - */ - public GuardedInvocation stringLookup(NashornCallSiteDescriptor callSite, CharSequence self); - - /** - * Wrapper for {@link jdk.nashorn.internal.objects.Global#booleanLookup(NashornCallSiteDescriptor, Boolean)} - * - * @param callSite call site descriptor - * @param self self reference - * - * @return guarded invocation - */ - public GuardedInvocation booleanLookup(NashornCallSiteDescriptor callSite, Boolean self); /** * Wrapper for {@link jdk.nashorn.internal.objects.Global#newObject()} diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java --- a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Fri Jan 25 17:35:31 2013 +0100 @@ -31,6 +31,7 @@ import org.dynalang.dynalink.CallSiteDescriptor; import org.dynalang.dynalink.beans.StaticClass; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; /** * An object that exposes Java packages and classes as its properties. Packages are exposed as objects that have further @@ -155,10 +156,11 @@ /** * Handle creation of new attribute. * @param desc the call site descriptor + * @param request the link request * @return Link to be invoked at call site. */ @Override - public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc) { + public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc, final LinkRequest request) { final String propertyName = desc.getNameToken(2); final String fullName = name.isEmpty() ? propertyName : name + "." + propertyName; @@ -178,12 +180,12 @@ set(propertyName, StaticClass.forClass(javaClass), strict); } - return super.lookup(desc); + return super.lookup(desc, request); } @Override - public GuardedInvocation noSuchMethod(final CallSiteDescriptor desc) { - return noSuchProperty(desc); + public GuardedInvocation noSuchMethod(final CallSiteDescriptor desc, final LinkRequest request) { + return noSuchProperty(desc, request); } } diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java Fri Jan 25 17:35:31 2013 +0100 @@ -45,6 +45,7 @@ import jdk.nashorn.internal.runtime.options.Options; import org.dynalang.dynalink.CallSiteDescriptor; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; /** * Runtime representation of a JavaScript function. @@ -907,15 +908,15 @@ * (4) for normal this-calls, drop callee. */ @Override - protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final boolean megaMorphic) { + protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) { final MethodType type = desc.getMethodType(); - if(megaMorphic) { + if (request.isCallSiteUnstable()) { // (this, callee, args...) => (this, callee, args[]) final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2); - return new GuardedInvocation(collector, + return new GuardedInvocation(addPrimitiveWrap(collector, desc, request), desc.getMethodType().parameterType(0) == ScriptFunction.class ? null : NashornGuards.getScriptFunctionGuard()); } @@ -938,6 +939,8 @@ assert reorder[1] == 0; final MethodType newType = oldType.changeParameterType(0, oldType.parameterType(1)).changeParameterType(1, oldType.parameterType(0)); boundHandle = MethodHandles.permuteArguments(callHandle, newType, reorder); + // thiz argument may be a JS primitive needing a wrapper + boundHandle = addPrimitiveWrap(boundHandle, desc, request); } } else { final MethodHandle callHandle = getBestSpecializedInvokeHandle(type.dropParameterTypes(0, 1)); @@ -977,6 +980,23 @@ return pairArguments(methodHandle, type); } + private MethodHandle addPrimitiveWrap(final MethodHandle mh, final CallSiteDescriptor desc, final LinkRequest request) { + // Check whether thiz is a JS primitive type and needs an object wrapper for non-strict function + if (!NashornCallSiteDescriptor.isScope(desc) && isNonStrictFunction()) { + Object self = request.getArguments()[1]; + if (isPrimitiveThis(self)) { + MethodHandle wrapFilter = ((GlobalObject) Context.getGlobalTrusted()).getWrapFilter(self); + return MH.filterArguments(mh, 1, MH.asType(wrapFilter, wrapFilter.type().changeReturnType(Object.class))); + } + } + return mh; + } + + private static boolean isPrimitiveThis(Object obj) { + return obj instanceof String || obj instanceof ConsString || + obj instanceof Number || obj instanceof Boolean; + } + private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { final Class own = ScriptFunction.class; final MethodType mt = MH.type(rtype, types); diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Jan 25 17:35:31 2013 +0100 @@ -68,6 +68,7 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards; import org.dynalang.dynalink.CallSiteDescriptor; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; import org.dynalang.dynalink.support.CallSiteDescriptorFactory; /** @@ -1506,22 +1507,11 @@ * with the appropriate guard(s). * * @param desc call site descriptor + * @param request the link request * * @return GuardedInvocation for the callsite */ - public final GuardedInvocation lookup(final CallSiteDescriptor desc) { - return lookup(desc, false); - } - - /** - * Lookup the appropriate method for an invoke dynamic call. - * - * @param desc The descriptor of the call site. - * @param megaMorphic if the call site is considered megamorphic - * - * @return GuardedInvocation to be invoked at call site. - */ - public GuardedInvocation lookup(final CallSiteDescriptor desc, final boolean megaMorphic) { + public GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request) { final int c = desc.getNameTokenCount(); // JavaScript is "immune" to all currently defined Dynalink composite operation - getProp is the same as getElem // is the same as getMethod as JavaScript objects have a single namespace for all three. Therefore, we don't @@ -1535,16 +1525,16 @@ case "getProp": case "getElem": case "getMethod": - return c > 2 ? findGetMethod(desc, megaMorphic, operator) : findGetIndexMethod(desc); + return c > 2 ? findGetMethod(desc, request, operator) : findGetIndexMethod(desc, request); case "setProp": case "setElem": - return c > 2 ? findSetMethod(desc, megaMorphic) : findSetIndexMethod(desc); + return c > 2 ? findSetMethod(desc, request) : findSetIndexMethod(desc); case "call": - return findCallMethod(desc, megaMorphic); + return findCallMethod(desc, request); case "new": return findNewMethod(desc); case "callMethod": - return findCallMethodMethod(desc, megaMorphic); + return findCallMethodMethod(desc, request); default: return null; } @@ -1565,12 +1555,12 @@ * Find the appropriate CALL method for an invoke dynamic call. * This generates "not a function" always * - * @param desc the call site descriptor. - * @param megaMorphic is this call site megaMorphic, as reported by Dynalink - then just do apply + * @param desc the call site descriptor. + * @param request the link request * * @return GuardedInvocation to be invoed at call site. */ - protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final boolean megaMorphic) { + protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) { return notAFunction(); } @@ -1585,17 +1575,17 @@ * one for "dyn:call". Explicit support for "dyn:callMethod" is provided for the benefit of potential external * callers. The implementation itself actually folds a "dyn:getMethod" method handle into a "dyn:call" method handle. * - * @param desc The call site descriptor. - * @param megaMorphic is this call site megaMorphic, as reported by Dynalink - then just do apply + * @param desc the call site descriptor. + * @param request the link request * * @return GuardedInvocation to be invoked at call site. */ - protected GuardedInvocation findCallMethodMethod(final CallSiteDescriptor desc, final boolean megaMorphic) { + protected GuardedInvocation findCallMethodMethod(final CallSiteDescriptor desc, final LinkRequest request) { // R(P0, P1, ...) final MethodType callType = desc.getMethodType(); // use type Object(P0) for the getter final CallSiteDescriptor getterType = desc.changeMethodType(MethodType.methodType(Object.class, callType.parameterType(0))); - final GuardedInvocation getter = findGetMethod(getterType, megaMorphic, "getMethod"); + final GuardedInvocation getter = findGetMethod(getterType, request, "getMethod"); // Object(P0) => Object(P0, P1, ...) final MethodHandle argDroppingGetter = MH.dropArguments(getter.getInvocation(), 1, callType.parameterList().subList(1, callType.parameterCount())); @@ -1608,16 +1598,16 @@ /** * Find the appropriate GET method for an invoke dynamic call. * - * @param desc the call site descriptor - * @param megaMorphic is this call site megaMorphic, as reported by Dynalink - then just do apply - * @param operator operator for get: getProp, getMethod, getElem etc + * @param desc the call site descriptor + * @param request the link request + * @param operator operator for get: getProp, getMethod, getElem etc * * @return GuardedInvocation to be invoked at call site. */ - protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final boolean megaMorphic, final String operator) { + protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) { final String name = desc.getNameToken(2); - if (megaMorphic) { + if (request.isCallSiteUnstable()) { return findMegaMorphicGetMethod(desc, name); } @@ -1627,9 +1617,9 @@ if (find == null) { if ("getProp".equals(operator)) { - return noSuchProperty(desc); + return noSuchProperty(desc, request); } else if ("getMethod".equals(operator)) { - return noSuchMethod(desc); + return noSuchMethod(desc, request); } else if ("getElem".equals(operator)) { return createEmptyGetter(desc, name); } @@ -1673,11 +1663,12 @@ /** * Find the appropriate GETINDEX method for an invoke dynamic call. * - * @param desc the call site descriptor + * @param desc the call site descriptor + * @param request the link request * * @return GuardedInvocation to be invoked at call site. */ - private static GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc) { + protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) { return findGetIndexMethod(desc.getMethodType()); } @@ -1708,14 +1699,14 @@ /** * Find the appropriate SET method for an invoke dynamic call. * - * @param desc the call site descriptor - * @param megaMorphic is this call site megaMorphic, as reported by Dynalink - then just do apply + * @param desc the call site descriptor + * @param request the link request * * @return GuardedInvocation to be invoked at call site. */ - protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final boolean megaMorphic) { + protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); - if(megaMorphic) { + if(request.isCallSiteUnstable()) { return findMegaMorphicSetMethod(desc, name); } @@ -1861,9 +1852,10 @@ /** * Fall back if a function property is not found. * @param desc The call site descriptor + * @param request the link request * @return GuardedInvocation to be invoked at call site. */ - public GuardedInvocation noSuchMethod(final CallSiteDescriptor desc) { + public GuardedInvocation noSuchMethod(final CallSiteDescriptor desc, final LinkRequest request) { final String name = desc.getNameToken(2); final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true); final boolean scopeCall = isScope() && NashornCallSiteDescriptor.isScope(desc); @@ -1887,9 +1879,10 @@ /** * Fall back if a property is not found. * @param desc the call site descriptor. + * @param request the link request * @return GuardedInvocation to be invoked at call site. */ - public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc) { + public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc, final LinkRequest request) { final String name = desc.getNameToken(2); final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true); final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc); diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/runtime/WithObject.java --- a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java Fri Jan 25 17:35:31 2013 +0100 @@ -32,6 +32,7 @@ import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import org.dynalang.dynalink.CallSiteDescriptor; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; import org.dynalang.dynalink.support.CallSiteDescriptorFactory; @@ -86,7 +87,7 @@ @Override - public GuardedInvocation lookup(final CallSiteDescriptor desc, final boolean megaMorphic) { + public GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request) { // With scopes can never be observed outside of Nashorn code, so all call sites that can address it will of // necessity have a Nashorn descriptor - it is safe to cast. final NashornCallSiteDescriptor ndesc = (NashornCallSiteDescriptor)desc; @@ -111,7 +112,7 @@ } if (find != null) { - link = self.lookup(desc); + link = self.lookup(desc, request); if (link != null) { return fixExpressionCallSite(ndesc, link); @@ -125,7 +126,7 @@ } if (find != null) { - return fixScopeCallSite(scope.lookup(desc)); + return fixScopeCallSite(scope.lookup(desc, request)); } // the property is not found - now check for @@ -155,11 +156,11 @@ if (find != null) { switch (operator) { case "getMethod": - link = self.noSuchMethod(desc); + link = self.noSuchMethod(desc, request); break; case "getProp": case "getElem": - link = self.noSuchProperty(desc); + link = self.noSuchProperty(desc, request); break; default: break; @@ -174,7 +175,7 @@ // still not found, may be scope can handle with it's own // __noSuchProperty__, __noSuchMethod__ etc. - link = scope.lookup(desc); + link = scope.lookup(desc, request); if (link != null) { return fixScopeCallSite(link); diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Fri Jan 25 17:35:31 2013 +0100 @@ -30,9 +30,6 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import jdk.nashorn.internal.runtime.ConsString; -import jdk.nashorn.internal.runtime.Context; -import jdk.nashorn.internal.runtime.GlobalObject; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Undefined; @@ -75,23 +72,9 @@ return null; } - GuardedInvocation inv; + final GuardedInvocation inv; if (self instanceof ScriptObject) { - inv = ((ScriptObject)self).lookup(desc, request.isCallSiteUnstable()); - - if (self instanceof ScriptFunction && "call".equals(desc.getNameToken(CallSiteDescriptor.OPERATOR))) { - - // Add toObject wrapper for non-object self argument to non-strict functions - assert request.getArguments().length >= 2 : "No self argument in script function callsite"; - Object thisObject = request.getArguments()[1]; - // Add wrapper filter for primitive this-object on non-strict functions - if (NashornGuardedInvocation.isNonStrict(inv) && isPrimitive(thisObject)) { - MethodHandle wrapFilter = ((GlobalObject) Context.getGlobal()).getWrapFilter(thisObject); - MethodHandle invocation = MH.filterArguments(inv.getInvocation(), 1, - MH.asType(wrapFilter, wrapFilter.type().changeReturnType(Object.class))); - inv = new GuardedInvocation(invocation, inv.getSwitchPoint(), inv.getGuard()); - } - } + inv = ((ScriptObject)self).lookup(desc, request); } else if (self instanceof Undefined) { inv = Undefined.lookup(desc); } else { @@ -153,13 +136,6 @@ JavaAdapterFactory.isAutoConvertibleFromFunction(clazz); } - private static boolean isPrimitive(Object obj) { - return obj instanceof Boolean || - obj instanceof Number || - obj instanceof String || - obj instanceof ConsString; - } - @Override public Comparison compareConversion(final Class sourceType, final Class targetType1, final Class targetType2) { if(ScriptObject.class.isAssignableFrom(sourceType)) { diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Fri Jan 25 17:35:31 2013 +0100 @@ -64,14 +64,7 @@ final GlobalObject global = (GlobalObject) Context.getGlobal(); final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor) request.getCallSiteDescriptor(); - if (self instanceof Number) { - return Bootstrap.asType(global.numberLookup(desc, (Number) self), linkerServices, desc); - } else if (self instanceof String || self instanceof ConsString) { - return Bootstrap.asType(global.stringLookup(desc, (CharSequence) self), linkerServices, desc); - } else if (self instanceof Boolean) { - return Bootstrap.asType(global.booleanLookup(desc, (Boolean) self), linkerServices, desc); - } - throw new AssertionError(); // Can't reach here + return Bootstrap.asType(global.primitiveLookup(request, self), linkerServices, desc); } /** diff -r 3d0b930f4b47 -r 3f6c0ab2597a nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Thu Jan 24 22:38:58 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Fri Jan 25 17:35:31 2013 +0100 @@ -32,6 +32,7 @@ import jdk.nashorn.internal.runtime.ScriptObject; import org.dynalang.dynalink.CallSiteDescriptor; import org.dynalang.dynalink.linker.GuardedInvocation; +import org.dynalang.dynalink.linker.LinkRequest; import org.dynalang.dynalink.support.CallSiteDescriptorFactory; import org.dynalang.dynalink.support.Guards; @@ -47,7 +48,7 @@ /** * Returns a guarded invocation representing the linkage for a dynamic operation on a primitive Java value. - * @param desc the descriptor of the call site identifying the dynamic operation. + * @param request the link request for the dynamic call site. * @param receiverClass the class of the receiver value (e.g., {@link java.lang.Boolean}, {@link java.lang.String} etc.) * @param wrappedReceiver a transient JavaScript native wrapper object created as the object proxy for the primitive * value; see ECMAScript 5.1, section 8.7.1 for discussion of using {@code [[Get]]} on a property reference with a @@ -58,14 +59,14 @@ * @return a guarded invocation representing the operation at the call site when performed on a JavaScript primitive * type {@code receiverClass}. */ - public static GuardedInvocation lookupPrimitive(final CallSiteDescriptor desc, final Class receiverClass, + public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Class receiverClass, final ScriptObject wrappedReceiver, final MethodHandle wrapFilter) { - return lookupPrimitive(desc, Guards.getInstanceOfGuard(receiverClass), wrappedReceiver, wrapFilter); + return lookupPrimitive(request, Guards.getInstanceOfGuard(receiverClass), wrappedReceiver, wrapFilter); } /** * Returns a guarded invocation representing the linkage for a dynamic operation on a primitive Java value. - * @param desc the descriptor of the call site identifying the dynamic operation. + * @param request the link request for the dynamic call site. * @param guard an explicit guard that will be used for the returned guarded invocation. * @param wrappedReceiver a transient JavaScript native wrapper object created as the object proxy for the primitive * value; see ECMAScript 5.1, section 8.7.1 for discussion of using {@code [[Get]]} on a property reference with a @@ -76,12 +77,17 @@ * @return a guarded invocation representing the operation at the call site when performed on a JavaScript primitive * type (that is implied by both {@code guard} and {@code wrappedReceiver}). */ - public static GuardedInvocation lookupPrimitive(final CallSiteDescriptor desc, final MethodHandle guard, + public static GuardedInvocation lookupPrimitive(final LinkRequest request, final MethodHandle guard, final ScriptObject wrappedReceiver, final MethodHandle wrapFilter) { + final CallSiteDescriptor desc = request.getCallSiteDescriptor(); final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); - if ("setProp".equals(operator) && desc.getNameTokenCount() > 2) { - return new GuardedInvocation(MH.asType(Lookup.EMPTY_SETTER, MH.type(void.class, Object.class, - desc.getMethodType().parameterType(1))), guard); + if ("setProp".equals(operator) || "setElem".equals(operator)) { + MethodType type = desc.getMethodType(); + MethodHandle method = MH.asType(Lookup.EMPTY_SETTER, MH.type(void.class, Object.class, type.parameterType(1))); + if (type.parameterCount() == 3) { + method = MH.dropArguments(method, 2, type.parameterType(2)); + } + return new GuardedInvocation(method, guard); } if(desc.getNameTokenCount() > 2) { @@ -91,7 +97,7 @@ return null; } } - final GuardedInvocation link = wrappedReceiver.lookup(desc); + final GuardedInvocation link = wrappedReceiver.lookup(desc, request); if (link != null) { MethodHandle method = link.getInvocation(); final Class receiverType = method.type().parameterType(0);