aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java')
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java44
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;
}
}