nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java
changeset 16195 3f6c0ab2597a
parent 16188 d6390b0ea32a
child 16202 f6665e456589
--- 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);