src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java

Print this page
rev 758 : 8021350: Share script classes between threads/globals within context
Reviewed-by: lagergren, sundar

*** 33,42 **** --- 33,43 ---- 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.FindProperty; import jdk.nashorn.internal.runtime.ScriptObject; /** * Implements lookup of methods to link for dynamic operations on JavaScript primitive values (booleans, strings, and * numbers). This class is only public so it can be accessed by classes in the {@code jdk.nashorn.internal.objects}
*** 59,70 **** * 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 * type {@code receiverClass}. */ public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Class<?> receiverClass, ! final ScriptObject wrappedReceiver, final MethodHandle 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 request the link request for the dynamic call site. --- 60,72 ---- * 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 * type {@code receiverClass}. */ public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Class<?> receiverClass, ! final ScriptObject wrappedReceiver, final MethodHandle wrapFilter, ! final MethodHandle protoFilter) { ! return lookupPrimitive(request, Guards.getInstanceOfGuard(receiverClass), wrappedReceiver, wrapFilter, protoFilter); } /** * Returns a guarded invocation representing the linkage for a dynamic operation on a primitive Java value. * @param request the link request for the dynamic call site.
*** 77,87 **** * 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 * type (that is implied by both {@code guard} and {@code wrappedReceiver}). */ 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) || "setElem".equals(operator)) { MethodType type = desc.getMethodType(); MethodHandle method = MH.asType(Lookup.EMPTY_SETTER, MH.type(void.class, Object.class, type.parameterType(1))); --- 79,90 ---- * 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 * type (that is implied by both {@code guard} and {@code wrappedReceiver}). */ public static GuardedInvocation lookupPrimitive(final LinkRequest request, final MethodHandle guard, ! 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)));
*** 91,103 **** return new GuardedInvocation(method, guard); } if(desc.getNameTokenCount() > 2) { final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); ! if(wrappedReceiver.findProperty(name, true) == null) { // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it. return null; } } final GuardedInvocation link = wrappedReceiver.lookup(desc, request); if (link != null) { MethodHandle method = link.getInvocation(); --- 94,120 ---- return new GuardedInvocation(method, guard); } if(desc.getNameTokenCount() > 2) { final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); ! final FindProperty find = wrappedReceiver.findProperty(name, true); ! 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())) { + // 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 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();