8007060: Primitive wrap filter throws ClassCastException in test262parallel
authorhannesw
Fri, 01 Feb 2013 02:24:15 +0100
changeset 16207 ed4aec2d599c
parent 16206 83069fa0935b
child 16208 0d15274b2326
8007060: Primitive wrap filter throws ClassCastException in test262parallel Reviewed-by: sundar, jlaskey, lagergren
nashorn/src/jdk/nashorn/internal/objects/Global.java
nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java
nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java
nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java
nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuardedInvocation.java
nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
nashorn/test/script/basic/JDK-8007060.js
nashorn/test/script/basic/JDK-8007060.js.EXPECTED
--- a/nashorn/src/jdk/nashorn/internal/objects/Global.java	Thu Jan 31 18:34:42 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java	Fri Feb 01 02:24:15 2013 +0100
@@ -419,18 +419,6 @@
     }
 
     @Override
-    public MethodHandle getWrapFilter(Object obj) {
-        if (obj instanceof String || obj instanceof ConsString) {
-            return NativeString.WRAPFILTER;
-        } else if (obj instanceof Number) {
-            return NativeNumber.WRAPFILTER;
-        } else if (obj instanceof Boolean) {
-            return NativeBoolean.WRAPFILTER;
-        }
-        throw new IllegalArgumentException("Unsupported primitive: " + obj);
-    }
-
-    @Override
     public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
         if (self instanceof String || self instanceof ConsString) {
             return NativeString.lookupPrimitive(request, self);
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java	Thu Jan 31 18:34:42 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java	Fri Feb 01 02:24:15 2013 +0100
@@ -66,17 +66,6 @@
         return ((ScriptFunction)self).toSource();
     }
 
-    private static Object convertThis(final ScriptFunction func, final Object thiz) {
-        if (!(thiz instanceof ScriptObject) && func.isNonStrictFunction()) {
-            if (thiz == UNDEFINED || thiz == null) {
-                return Global.instance();
-            }
-            return JSType.toScriptObject(thiz);
-        }
-
-        return thiz;
-    }
-
     /**
      * ECMA 15.3.4.3 Function.prototype.apply (thisArg, argArray)
      *
@@ -125,12 +114,7 @@
             typeError("function.apply.expects.array");
         }
 
-        final ScriptFunction func = (ScriptFunction)self;
-        // As per ECMA 5.1 spec, "this" is passed "as is". But the spec.
-        // says 'this' is transformed when callee frame is created if callee
-        // is a non-strict function. So, we convert 'this' here if callee is
-        // not strict and not builtin function.
-        return ScriptRuntime.apply(func, convertThis(func, thiz), args);
+        return ScriptRuntime.apply((ScriptFunction)self, thiz, args);
     }
 
     /**
@@ -157,15 +141,7 @@
             arguments = ScriptRuntime.EMPTY_ARRAY;
         }
 
-        final ScriptFunction func = (ScriptFunction)self;
-
-        // As per ECMA 5.1 spec, "this" is passed "as is". But the spec.
-        // says 'this' is transformed when callee frame is created if callee
-        // is a non-strict function. So, we convert 'this' here if callee is
-        // not strict and not builtin function.
-        thiz = convertThis(func, thiz);
-
-        return ScriptRuntime.apply(func, thiz, arguments);
+        return ScriptRuntime.apply((ScriptFunction)self, thiz, arguments);
     }
 
     /**
@@ -182,12 +158,7 @@
             return UNDEFINED;
         }
 
-        // As per ECMA 5.1 spec, "this" is passed "as is". But the spec.
-        // says 'this' is transformed when callee frame is created if callee
-        // is a non-strict function. So, we convert 'this' here if callee is
-        // not strict. Note that all builtin functions are marked as strict and
-        // so 'this' transformation is not done for such functions.
-        final Object thiz = convertThis((ScriptFunction)self, (args.length == 0) ? UNDEFINED : args[0]);
+        final Object thiz = (args.length == 0) ? UNDEFINED : args[0];
 
         Object[] arguments;
         if (args.length > 1) {
--- a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Thu Jan 31 18:34:42 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Fri Feb 01 02:24:15 2013 +0100
@@ -293,7 +293,8 @@
             allArgs = ScriptRuntime.EMPTY_ARRAY;
         }
 
-        final MethodHandle   boundMethod = MH.insertArguments(BOUND_FUNCTION, 0, this, thiz, allArgs);
+        final Object boundThiz = convertThisObject(thiz);
+        final MethodHandle   boundMethod = MH.insertArguments(BOUND_FUNCTION, 0, this, boundThiz, allArgs);
         final ScriptFunction boundFunc   = makeFunction("", boundMethod, null, true);
 
         MethodHandle consHandle  = this.getConstructHandle();
--- a/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java	Thu Jan 31 18:34:42 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java	Fri Feb 01 02:24:15 2013 +0100
@@ -70,15 +70,6 @@
 
 
     /**
-     * Get a MethodHandle that converts the argument to its JavaScript object representation
-     *
-     * @param obj a JavaScript primitive object (String, Number, or Boolean)
-     *
-     * @return wrap filter methodhandle
-     */
-   public MethodHandle getWrapFilter(Object obj);
-
-    /**
      * Wrapper for {@link jdk.nashorn.internal.objects.Global#primitiveLookup(LinkRequest, Object)}
      *
      * @param request the link request for the dynamic call site.
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Thu Jan 31 18:34:42 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Fri Feb 01 02:24:15 2013 +0100
@@ -40,7 +40,6 @@
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
-import jdk.nashorn.internal.runtime.linker.NashornGuardedInvocation;
 import jdk.nashorn.internal.runtime.linker.NashornGuards;
 import jdk.nashorn.internal.runtime.options.Options;
 import org.dynalang.dynalink.CallSiteDescriptor;
@@ -69,6 +68,8 @@
 
     private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class);
 
+    private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class);
+
     /** method handle to arity setter for this ScriptFunction */
     public static final Call SET_ARITY = virtualCallNoLookup(ScriptFunction.class, "setArity", void.class, int.class);
     /** method handle to scope getter for this ScriptFunction */
@@ -352,7 +353,7 @@
     public abstract boolean isBuiltin();
 
     /**
-     * Is this a non-strict (not built-in) script function?
+     * Is this a non-strict and not-built-in script function?
      * @return true if neither strict nor built-in
      */
     public boolean isNonStrictFunction() {
@@ -371,42 +372,43 @@
             invokes++;
         }
 
+        final Object selfObj = convertThisObject(self);
         final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;
 
         if (isVarArg(invokeHandle)) {
             if (hasCalleeParameter()) {
-                return invokeHandle.invokeExact(self, this, args);
+                return invokeHandle.invokeExact(selfObj, this, args);
             }
-            return invokeHandle.invokeExact(self, args);
+            return invokeHandle.invokeExact(selfObj, args);
         }
 
         final int paramCount = invokeHandle.type().parameterCount();
         if (hasCalleeParameter()) {
             switch (paramCount) {
             case 2:
-                return invokeHandle.invokeExact(self, this);
+                return invokeHandle.invokeExact(selfObj, this);
             case 3:
-                return invokeHandle.invokeExact(self, this, getArg(args, 0));
+                return invokeHandle.invokeExact(selfObj, this, getArg(args, 0));
             case 4:
-                return invokeHandle.invokeExact(self, this, getArg(args, 0), getArg(args, 1));
+                return invokeHandle.invokeExact(selfObj, this, getArg(args, 0), getArg(args, 1));
             case 5:
-                return invokeHandle.invokeExact(self, this, getArg(args, 0), getArg(args, 1), getArg(args, 2));
+                return invokeHandle.invokeExact(selfObj, this, getArg(args, 0), getArg(args, 1), getArg(args, 2));
             default:
-                return invokeHandle.invokeWithArguments(withArguments(self, this, paramCount, args));
+                return invokeHandle.invokeWithArguments(withArguments(selfObj, this, paramCount, args));
             }
         }
 
         switch (paramCount) {
         case 1:
-            return invokeHandle.invokeExact(self);
+            return invokeHandle.invokeExact(selfObj);
         case 2:
-            return invokeHandle.invokeExact(self, getArg(args, 0));
+            return invokeHandle.invokeExact(selfObj, getArg(args, 0));
         case 3:
-            return invokeHandle.invokeExact(self, getArg(args, 0), getArg(args, 1));
+            return invokeHandle.invokeExact(selfObj, getArg(args, 0), getArg(args, 1));
         case 4:
-            return invokeHandle.invokeExact(self, getArg(args, 0), getArg(args, 1), getArg(args, 2));
+            return invokeHandle.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2));
         default:
-            return invokeHandle.invokeWithArguments(withArguments(self, null, paramCount, args));
+            return invokeHandle.invokeWithArguments(withArguments(selfObj, null, paramCount, args));
         }
     }
 
@@ -912,6 +914,14 @@
         return (result instanceof ScriptObject || !JSType.isPrimitive(result))? result : allocation;
     }
 
+    @SuppressWarnings("unused")
+    private static Object wrapFilter(final Object obj) {
+        if (obj instanceof ScriptObject || !isPrimitiveThis(obj)) {
+            return obj;
+        }
+        return ((GlobalObject) Context.getGlobalTrusted()).wrapAsObject(obj);
+    }
+
     /**
      * dyn:call call site signature: (callee, thiz, [args...])
      * generated method signature:   (thiz, callee, [args...])
@@ -933,11 +943,13 @@
             final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class,
                     type.parameterCount() - 2);
 
-            return new GuardedInvocation(addPrimitiveWrap(collector, desc, request),
+            return new GuardedInvocation(collector,
                     desc.getMethodType().parameterType(0) == ScriptFunction.class ? null : NashornGuards.getScriptFunctionGuard());
         }
 
         MethodHandle boundHandle;
+        MethodHandle guard = null;
+
         if (hasCalleeParameter()) {
             final MethodHandle callHandle = getBestSpecializedInvokeHandle(type);
 
@@ -956,14 +968,23 @@
                 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);
+
+                // For non-strict functions, check whether this-object is primitive type.
+                // If so add a to-object-wrapper argument filter.
+                // Else install a guard that will trigger a relink when the argument becomes primitive.
+                if (isNonStrictFunction()) {
+                    if (isPrimitiveThis(request.getArguments()[1])) {
+                        boundHandle = MH.filterArguments(boundHandle, 1, WRAPFILTER);
+                    } else {
+                        guard = NashornGuards.getNonStrictFunctionGuard(this);
+                    }
+                }
             }
         } else {
             final MethodHandle callHandle = getBestSpecializedInvokeHandle(type.dropParameterTypes(0, 1));
 
             if(NashornCallSiteDescriptor.isScope(desc)) {
-                boundHandle = MH.bindTo(callHandle, isNonStrictFunction()? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
+                boundHandle = MH.bindTo(callHandle, isNonStrictFunction() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
                 boundHandle = MH.dropArguments(boundHandle, 0, Object.class, Object.class);
             } else {
                 boundHandle = MH.dropArguments(callHandle, 0, Object.class);
@@ -971,7 +992,7 @@
         }
 
         boundHandle = pairArguments(boundHandle, type);
-        return new NashornGuardedInvocation(boundHandle, null, NashornGuards.getFunctionGuard(this), isNonStrictFunction());
+        return new GuardedInvocation(boundHandle, guard == null ? NashornGuards.getFunctionGuard(this) : guard);
    }
 
     /**
@@ -997,16 +1018,25 @@
         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)));
+    /**
+     * Convert this argument for non-strict functions according to ES 10.4.3
+     *
+     * @param thiz the this argument
+     *
+     * @return the converted this object
+     */
+    protected Object convertThisObject(final Object thiz) {
+        if (!(thiz instanceof ScriptObject) && isNonStrictFunction()) {
+            if (JSType.nullOrUndefined(thiz)) {
+                return Context.getGlobalTrusted();
+            }
+
+            if (isPrimitiveThis(thiz)) {
+                return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(thiz);
             }
         }
-        return mh;
+
+        return thiz;
     }
 
     private static boolean isPrimitiveThis(Object obj) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Jan 31 18:34:42 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Feb 01 02:24:15 2013 +0100
@@ -64,7 +64,6 @@
 import jdk.nashorn.internal.runtime.linker.Lookup;
 import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
-import jdk.nashorn.internal.runtime.linker.NashornGuardedInvocation;
 import jdk.nashorn.internal.runtime.linker.NashornGuards;
 import org.dynalang.dynalink.CallSiteDescriptor;
 import org.dynalang.dynalink.linker.GuardedInvocation;
@@ -1712,11 +1711,9 @@
         if (methodHandle != null) {
             assert methodHandle.type().returnType().equals(returnType);
             final ScriptFunction getter = find.getGetterFunction();
-            final boolean nonStrict = getter != null && getter.isNonStrictFunction();
             if (find.isSelf()) {
-                return new NashornGuardedInvocation(methodHandle, null, ObjectClassGenerator.OBJECT_FIELDS_ONLY &&
-                        NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType() ? null : guard,
-                            nonStrict);
+                return new GuardedInvocation(methodHandle, ObjectClassGenerator.OBJECT_FIELDS_ONLY &&
+                        NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType() ? null : guard);
             }
 
             final ScriptObject prototype = find.getOwner();
@@ -1724,7 +1721,7 @@
             if (!property.hasGetterFunction()) {
                 methodHandle = bindTo(methodHandle, prototype);
             }
-            return new NashornGuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(name), guard, nonStrict);
+            return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(name), guard);
         }
 
         assert !NashornCallSiteDescriptor.isFastScope(desc);
--- a/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Thu Jan 31 18:34:42 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Fri Feb 01 02:24:15 2013 +0100
@@ -33,7 +33,6 @@
 import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator;
 import jdk.nashorn.internal.runtime.linker.Lookup;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
-import jdk.nashorn.internal.runtime.linker.NashornGuardedInvocation;
 import jdk.nashorn.internal.runtime.linker.NashornGuards;
 
 import org.dynalang.dynalink.CallSiteDescriptor;
@@ -41,8 +40,8 @@
 
 /**
  * Instances of this class are quite ephemeral; they only exist for the duration of an invocation of
- * {@link ScriptObject#findSetMethod(CallSiteDescriptor, boolean)} and serve as the actual encapsulation of the
- * algorithm for creating an appropriate property setter method.
+ * {@link ScriptObject#findSetMethod(CallSiteDescriptor, org.dynalang.dynalink.linker.LinkRequest)} and
+ * serve as the actual encapsulation of the algorithm for creating an appropriate property setter method.
  */
 class SetMethodCreator {
     // See constructor parameters for description of fields
@@ -89,19 +88,16 @@
     private class SetMethod {
         private final MethodHandle methodHandle;
         private final Property property;
-        private final boolean nonStrict;
 
         /**
          * Creates a new lookup result.
          * @param methodHandle the actual method handle
          * @param property the property object. Can be null in case we're creating a new property in the global object.
-         * @param nonStrict True if an existing property with a non-strict function as property setter is discovered.
          */
-        SetMethod(final MethodHandle methodHandle, final Property property, final boolean nonStrict) {
+        SetMethod(final MethodHandle methodHandle, final Property property) {
             assert methodHandle != null;
             this.methodHandle = methodHandle;
             this.property = property;
-            this.nonStrict = nonStrict;
         }
 
         /**
@@ -109,7 +105,7 @@
          * @return the composed guarded invocation that represents the dynamic setter method for the property.
          */
         GuardedInvocation createGuardedInvocation() {
-            return new NashornGuardedInvocation(methodHandle, null, getGuard(), nonStrict);
+            return new GuardedInvocation(methodHandle, getGuard());
         }
 
         private MethodHandle getGuard() {
@@ -162,17 +158,12 @@
         } else {
             boundHandle = methodHandle;
         }
-        return new SetMethod(boundHandle, property, getExistingSetterNonStrictFlag());
-    }
-
-    private boolean getExistingSetterNonStrictFlag() {
-        final ScriptFunction setter = find.getSetterFunction();
-        return setter != null && setter.isNonStrictFunction();
+        return new SetMethod(boundHandle, property);
     }
 
     private SetMethod createGlobalPropertySetter() {
         final ScriptObject global = Context.getGlobalTrusted();
-        return new SetMethod(ScriptObject.bindTo(global.addSpill(getName()), global), null, false);
+        return new SetMethod(ScriptObject.bindTo(global.addSpill(getName()), global), null);
     }
 
     private SetMethod createNewPropertySetter() {
@@ -192,7 +183,7 @@
         final int nextSpill = getMap().getSpillLength();
 
         final Property property = createSpillProperty(nextSpill);
-        return new SetMethod(createSpillMethodHandle(nextSpill, property), property, false);
+        return new SetMethod(createSpillMethodHandle(nextSpill, property), property);
     }
 
     private Property createSpillProperty(final int nextSpill) {
@@ -222,7 +213,7 @@
         final Property property = new SpillProperty(getName(), 0, nextEmbed, ScriptObject.GET_EMBED[nextEmbed], ScriptObject.SET_EMBED[nextEmbed]);
         //TODO specfields
         final MethodHandle methodHandle = MH.insertArguments(ScriptObject.SETEMBED, 0, desc, getMap(), getNewMap(property), property.getSetter(Object.class, getMap()), nextEmbed);
-        return new SetMethod(methodHandle, property, false);
+        return new SetMethod(methodHandle, property);
     }
 
     private PropertyMap getNewMap(Property property) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuardedInvocation.java	Thu Jan 31 18:34:42 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime.linker;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.SwitchPoint;
-import org.dynalang.dynalink.linker.GuardedInvocation;
-
-/**
- * Guarded invocation with Nashorn specific bits.
- */
-public class NashornGuardedInvocation extends GuardedInvocation {
-
-    private final boolean nonStrict;
-
-    /**
-     * Constructor
-     *
-     * @param invocation  invocation target
-     * @param switchPoint SwitchPoint that will, when invalidated, require relinking callsite, null if no SwitchPoint
-     * @param guard       guard that will, when failed, require relinking callsite, null if no guard
-     * @param nonStrict   non-strict invocation target flag
-     */
-    public NashornGuardedInvocation(final MethodHandle invocation, final SwitchPoint switchPoint, final MethodHandle guard, final boolean nonStrict) {
-        super(invocation, switchPoint, guard);
-        this.nonStrict = nonStrict;
-
-    }
-
-    /**
-     * Is the target of this invocation a non-strict function?
-     * @return true if invocation target is non-strict
-     */
-    public boolean isNonStrict() {
-        return nonStrict;
-    }
-
-    /**
-     * Check whether the target of this invocation is a non-strict script function.
-     * @param inv guarded invocation
-     * @return true if invocation target is non-strict
-     */
-    public static boolean isNonStrict(final GuardedInvocation inv) {
-        return inv instanceof NashornGuardedInvocation && ((NashornGuardedInvocation)inv).isNonStrict();
-    }
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java	Thu Jan 31 18:34:42 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java	Fri Feb 01 02:24:15 2013 +0100
@@ -41,6 +41,7 @@
     private static final MethodHandle IS_SCRIPTFUNCTION        = findOwnMH("isScriptFunction", boolean.class, Object.class);
     private static final MethodHandle IS_MAP                   = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
     private static final MethodHandle IS_FUNCTION_MH           = findOwnMH("isFunctionMH", boolean.class, Object.class, MethodHandle.class);
+    private static final MethodHandle IS_NONSTRICT_FUNCTION    = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, MethodHandle.class);
     private static final MethodHandle IS_INSTANCEOF_2          = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
 
     // don't create me!
@@ -99,6 +100,20 @@
         return MH.insertArguments(IS_FUNCTION_MH, 1, function.getInvokeHandle());
     }
 
+    /**
+     * Get a guard that checks if a {@link ScriptFunction} is equal to
+     * a known ScriptFunction using reference comparison, and whether the type of
+     * the second argument (this-object) is not a JavaScript primitive type.
+     *
+     * @param function The ScriptFunction to check against. This will be bound to the guard method handle
+     *
+     * @return method handle for guard
+     */
+    public static MethodHandle getNonStrictFunctionGuard(final ScriptFunction function) {
+        assert function.getInvokeHandle() != null;
+        return MH.insertArguments(IS_NONSTRICT_FUNCTION, 2, function.getInvokeHandle());
+    }
+
     @SuppressWarnings("unused")
     private static boolean isScriptObject(final Object self) {
         return self instanceof ScriptObject;
@@ -120,6 +135,11 @@
     }
 
     @SuppressWarnings("unused")
+    private static boolean isNonStrictFunction(final Object self, final Object arg, final MethodHandle mh) {
+        return self instanceof ScriptFunction && ((ScriptFunction)self).getInvokeHandle() == mh && arg instanceof ScriptObject;
+    }
+
+    @SuppressWarnings("unused")
     private static boolean isInstanceOf2(final Object self, final Class<?> class1, final Class<?> class2) {
         return class1.isInstance(self) || class2.isInstance(self);
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Thu Jan 31 18:34:42 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Fri Feb 01 02:24:15 2013 +0100
@@ -101,7 +101,7 @@
         if (link != null) {
             MethodHandle method = link.getInvocation();
             final Class<?> receiverType = method.type().parameterType(0);
-            if (receiverType != Object.class || NashornGuardedInvocation.isNonStrict(link)) {
+            if (receiverType != Object.class) {
                 final MethodType wrapType = wrapFilter.type();
                 assert receiverType.isAssignableFrom(wrapType.returnType());
                 method = MH.filterArguments(method, 0, MH.asType(wrapFilter, wrapType.changeReturnType(receiverType)));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8007060.js	Fri Feb 01 02:24:15 2013 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8007060 : Primitive wrap filter throws ClassCastException in test262parallel
+ *
+ * @test
+ * @run
+ */
+
+Object.prototype.T = function() {
+    print(this, typeof this);
+};
+
+function F() {
+    print(this, typeof this);
+}
+
+
+function test(obj) {
+   obj.T();
+}
+
+// Ordinary callsite - call often so we go to megamorphic
+test(1);
+test({});
+test("hello");
+test(1);
+test({});
+test("hello");
+test(1);
+test({});
+test("hello");
+test(1);
+test({});
+test("hello");
+test(1);
+test({});
+test("hello");
+test(1);
+test({});
+test("hello");
+test(1);
+test({});
+test("hello");
+test(1);
+test({});
+test("hello");
+
+// Dynamic invoker callsite used by NativeArray
+[1, 2, 3].filter(F, 1);
+[1, 2, 3].filter(F, {});
+[1, 2, 3].filter(F, "hello");
+[1, 2, 3].filter(F, 1);
+[1, 2, 3].filter(F, {});
+[1, 2, 3].filter(F, "hello");
+[1, 2, 3].filter(F, 1);
+[1, 2, 3].filter(F, {});
+[1, 2, 3].filter(F, "hello");
+[1, 2, 3].filter(F, 1);
+[1, 2, 3].filter(F, {});
+[1, 2, 3].filter(F, "hello");
+[1, 2, 3].filter(F, 1);
+[1, 2, 3].filter(F, {});
+[1, 2, 3].filter(F, "hello");
+[1, 2, 3].filter(F, 1);
+[1, 2, 3].filter(F, {});
+[1, 2, 3].filter(F, "hello");
+[1, 2, 3].filter(F, 1);
+[1, 2, 3].filter(F, {});
+[1, 2, 3].filter(F, "hello");
+[1, 2, 3].filter(F, 1);
+[1, 2, 3].filter(F, {});
+[1, 2, 3].filter(F, "hello");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8007060.js.EXPECTED	Fri Feb 01 02:24:15 2013 +0100
@@ -0,0 +1,96 @@
+1 object
+[object Object] object
+hello object
+1 object
+[object Object] object
+hello object
+1 object
+[object Object] object
+hello object
+1 object
+[object Object] object
+hello object
+1 object
+[object Object] object
+hello object
+1 object
+[object Object] object
+hello object
+1 object
+[object Object] object
+hello object
+1 object
+[object Object] object
+hello object
+1 object
+1 object
+1 object
+[object Object] object
+[object Object] object
+[object Object] object
+hello object
+hello object
+hello object
+1 object
+1 object
+1 object
+[object Object] object
+[object Object] object
+[object Object] object
+hello object
+hello object
+hello object
+1 object
+1 object
+1 object
+[object Object] object
+[object Object] object
+[object Object] object
+hello object
+hello object
+hello object
+1 object
+1 object
+1 object
+[object Object] object
+[object Object] object
+[object Object] object
+hello object
+hello object
+hello object
+1 object
+1 object
+1 object
+[object Object] object
+[object Object] object
+[object Object] object
+hello object
+hello object
+hello object
+1 object
+1 object
+1 object
+[object Object] object
+[object Object] object
+[object Object] object
+hello object
+hello object
+hello object
+1 object
+1 object
+1 object
+[object Object] object
+[object Object] object
+[object Object] object
+hello object
+hello object
+hello object
+1 object
+1 object
+1 object
+[object Object] object
+[object Object] object
+[object Object] object
+hello object
+hello object
+hello object