8006766: Array-like access to characters of a string is slow
Reviewed-by: lagergren, attila
--- 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
--- 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);
}
/**
--- 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;
}
--- 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) {
--- 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")
--- 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")
--- 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()}
--- 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);
}
}
--- 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);
--- 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);
--- 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);
--- 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)) {
--- 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);
}
/**
--- 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);