diff options
Diffstat (limited to 'src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java')
-rw-r--r-- | src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java index 7665be7f..2a536bbf 100644 --- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java +++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java @@ -26,17 +26,18 @@ package jdk.nashorn.internal.runtime.linker; import static jdk.nashorn.internal.lookup.Lookup.MH; - import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; +import java.lang.invoke.SwitchPoint; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.internal.dynalink.support.Guards; -import jdk.nashorn.internal.lookup.Lookup; +import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.FindProperty; +import jdk.nashorn.internal.runtime.GlobalConstants; import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.UserAccessorProperty; /** * Implements lookup of methods to link for dynamic operations on JavaScript primitive values (booleans, strings, and @@ -59,6 +60,7 @@ public final class PrimitiveLookup { * creates a transient native wrapper of the same type as {@code wrappedReceiver} for subsequent invocations of the * method - it will be combined into the returned invocation as an argument filter on the receiver. * @return a guarded invocation representing the operation at the call site when performed on a JavaScript primitive + * @param protoFilter A method handle that walks up the proto chain of this receiver object * type {@code receiverClass}. */ public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Class<?> receiverClass, @@ -77,6 +79,7 @@ public final class PrimitiveLookup { * @param wrapFilter A method handle that takes a primitive value of type guarded by the {@code guard} and * creates a transient native wrapper of the same type as {@code wrappedReceiver} for subsequent invocations of the * method - it will be combined into the returned invocation as an argument filter on the receiver. + * @param protoFilter A method handle that walks up the proto chain of this receiver object * @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}). */ @@ -84,37 +87,42 @@ public final class PrimitiveLookup { final ScriptObject wrappedReceiver, final MethodHandle wrapFilter, final MethodHandle protoFilter) { final CallSiteDescriptor desc = request.getCallSiteDescriptor(); - final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); - 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) { + //checks whether the property name is hard-coded in the call-site (i.e. a getProp vs a getElem, or setProp vs setElem) + //if it is we can make assumptions on the property: that if it is not defined on primitive wrapper itself it never will be. + //so in that case we can skip creation of primitive wrapper and start our search with the prototype. + if (desc.getNameTokenCount() > 2) { final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); final FindProperty find = wrappedReceiver.findProperty(name, true); - if(find == null) { + + if (find == null) { // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it. return null; - } else if (find.isInherited() && !find.getProperty().hasGetterFunction(find.getOwner())) { + } + + final SwitchPoint sp = find.getProperty().getBuiltinSwitchPoint(); //can use this instead of proto filter + if (sp instanceof Context.BuiltinSwitchPoint && !sp.hasBeenInvalidated()) { + return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null); + } + + if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { // If property is found in the prototype object bind the method handle directly to // the proto filter instead of going through wrapper instantiation below. final ScriptObject proto = wrappedReceiver.getProto(); final GuardedInvocation link = proto.lookup(desc, request); if (link != null) { - final MethodHandle invocation = link.getInvocation(); + final MethodHandle invocation = link.getInvocation(); //this contains the builtin switchpoint + final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class)); final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter); final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter); + return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard)); } } } + final GuardedInvocation link = wrappedReceiver.lookup(desc, request); if (link != null) { MethodHandle method = link.getInvocation(); @@ -124,8 +132,10 @@ public final class PrimitiveLookup { assert receiverType.isAssignableFrom(wrapType.returnType()); method = MH.filterArguments(method, 0, MH.asType(wrapFilter, wrapType.changeReturnType(receiverType))); } - return new GuardedInvocation(method, guard, link.getSwitchPoint()); + + return new GuardedInvocation(method, guard, link.getSwitchPoints(), null); } + return null; } } |