mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-01 03:30:34 +00:00
8007060: Primitive wrap filter throws ClassCastException in test262parallel
Reviewed-by: sundar, jlaskey, lagergren
This commit is contained in:
parent
fe52eb5992
commit
4f2891ca8d
@ -418,18 +418,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
|
||||
@ -66,17 +66,6 @@ public final class NativeFunction {
|
||||
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 @@ public final class NativeFunction {
|
||||
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 @@ public final class NativeFunction {
|
||||
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 @@ public final class NativeFunction {
|
||||
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) {
|
||||
|
||||
@ -293,7 +293,8 @@ public class ScriptFunctionImpl extends ScriptFunction {
|
||||
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();
|
||||
|
||||
@ -69,15 +69,6 @@ public interface GlobalObject {
|
||||
public Object wrapAsObject(Object obj);
|
||||
|
||||
|
||||
/**
|
||||
* 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)}
|
||||
*
|
||||
|
||||
@ -40,7 +40,6 @@ import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
|
||||
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 @@ public abstract class ScriptFunction extends ScriptObject {
|
||||
|
||||
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 class ScriptFunction extends ScriptObject {
|
||||
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 @@ public abstract class ScriptFunction extends ScriptObject {
|
||||
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 @@ public abstract class ScriptFunction extends ScriptObject {
|
||||
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 @@ public abstract class ScriptFunction extends ScriptObject {
|
||||
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 @@ public abstract class ScriptFunction extends ScriptObject {
|
||||
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 @@ public abstract class ScriptFunction extends ScriptObject {
|
||||
}
|
||||
|
||||
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 @@ public abstract class ScriptFunction extends ScriptObject {
|
||||
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) {
|
||||
|
||||
@ -64,7 +64,6 @@ import jdk.nashorn.internal.runtime.linker.Bootstrap;
|
||||
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 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
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 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
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);
|
||||
|
||||
@ -33,7 +33,6 @@ import java.lang.invoke.MethodHandle;
|
||||
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 @@ import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
|
||||
/**
|
||||
* 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 @@ class SetMethodCreator {
|
||||
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 @@ class SetMethodCreator {
|
||||
* @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 @@ class SetMethodCreator {
|
||||
} 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 @@ class SetMethodCreator {
|
||||
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 @@ class SetMethodCreator {
|
||||
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) {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -41,6 +41,7 @@ public final class NashornGuards {
|
||||
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 @@ public final class NashornGuards {
|
||||
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;
|
||||
@ -119,6 +134,11 @@ public final class NashornGuards {
|
||||
return self instanceof ScriptFunction && ((ScriptFunction)self).getInvokeHandle() == mh;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
@ -101,7 +101,7 @@ public class PrimitiveLookup {
|
||||
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)));
|
||||
|
||||
94
nashorn/test/script/basic/JDK-8007060.js
Normal file
94
nashorn/test/script/basic/JDK-8007060.js
Normal file
@ -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");
|
||||
96
nashorn/test/script/basic/JDK-8007060.js.EXPECTED
Normal file
96
nashorn/test/script/basic/JDK-8007060.js.EXPECTED
Normal file
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user