提交 0941dafb 编写于 作者: J jlaskey

8011578: -Dnashorn.unstable.relink.threshold=1 causes tests to fail.

Reviewed-by: sundar, lagergren
Contributed-by: james.laskey@oracle.com
上级 11913dc5
......@@ -104,6 +104,22 @@ public final class FindProperty {
return prototype;
}
/**
* Return the appropriate receiver for a getter.
* @return appropriate receiver
*/
public ScriptObject getGetterReceiver() {
return property != null && property.hasGetterFunction() ? self : prototype;
}
/**
* Return the appropriate receiver for a setter.
* @return appropriate receiver
*/
public ScriptObject getSetterReceiver() {
return property != null && property.hasSetterFunction() ? self : prototype;
}
/**
* Return the property that was found
* @return property
......
......@@ -901,7 +901,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final MethodHandle getter = find.getGetter(int.class);
if (getter != null) {
try {
return (int)getter.invokeExact((Object)find.getOwner());
return (int)getter.invokeExact((Object)find.getGetterReceiver());
} catch (final Error|RuntimeException e) {
throw e;
} catch (final Throwable e) {
......@@ -916,7 +916,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final MethodHandle getter = find.getGetter(long.class);
if (getter != null) {
try {
return (long)getter.invokeExact((Object)find.getOwner());
return (long)getter.invokeExact((Object)find.getGetterReceiver());
} catch (final Error|RuntimeException e) {
throw e;
} catch (final Throwable e) {
......@@ -931,7 +931,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final MethodHandle getter = find.getGetter(double.class);
if (getter != null) {
try {
return (double)getter.invokeExact((Object)find.getOwner());
return (double)getter.invokeExact((Object)find.getGetterReceiver());
} catch (final Error|RuntimeException e) {
throw e;
} catch (final Throwable e) {
......@@ -953,7 +953,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final MethodHandle getter = find.getGetter(Object.class);
if (getter != null) {
try {
return getter.invokeExact((Object)find.getOwner());
return getter.invokeExact((Object)find.getGetterReceiver());
} catch (final Error|RuntimeException e) {
throw e;
} catch (final Throwable e) {
......@@ -1679,12 +1679,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
final String name = desc.getNameToken(2);
if (request.isCallSiteUnstable()) {
return findMegaMorphicGetMethod(desc, name);
}
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final FindProperty find = findProperty(name, true);
MethodHandle methodHandle;
......@@ -1700,6 +1695,10 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
throw new AssertionError(); // never invoked with any other operation
}
if (request.isCallSiteUnstable()) {
return findMegaMorphicGetMethod(desc, name);
}
final Class<?> returnType = desc.getMethodType().returnType();
final Property property = find.getProperty();
methodHandle = find.getGetter(returnType);
......@@ -1727,7 +1726,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name) {
final GuardedInvocation inv = findGetIndexMethod(desc.getMethodType().insertParameterTypes(1, Object.class));
final MethodType mhType = desc.getMethodType().insertParameterTypes(1, Object.class);
final GuardedInvocation inv = findGetIndexMethod(mhType);
return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
}
......@@ -1890,8 +1891,8 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
final GuardedInvocation inv = findSetIndexMethod(desc.getMethodType().insertParameterTypes(1, Object.class),
NashornCallSiteDescriptor.isStrict(desc));
final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
final GuardedInvocation inv = findSetIndexMethod(type, NashornCallSiteDescriptor.isStrict(desc)).asType(type);
return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
}
......@@ -1949,7 +1950,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return GuardedInvocation to be invoked at call site.
*/
public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc, final LinkRequest request) {
final String name = desc.getNameToken(2);
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
......@@ -1973,6 +1974,24 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return createEmptyGetter(desc, name);
}
/**
* Invoke fall back if a property is not found.
* @param name Name of property.
* @return Result from call.
*/
private Object invokeNoSuchProperty(final String name) {
final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
if (find != null) {
final Object func = getObjectValue(find);
if (func instanceof ScriptFunction) {
return ScriptRuntime.apply((ScriptFunction)func, this, name);
}
}
return UNDEFINED;
}
private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) {
return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(name), NashornGuards.getMapGuard(getMap()));
......@@ -2239,310 +2258,158 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
setArray(getArray().shrink(newLength));
getArray().setLength(newLength);
}
}
}
@Override
public int getInt(final Object key) {
final int index = getArrayIndexNoThrow(key);
private int getInt(final int index, final String key) {
for (ScriptObject object = this; object != null; object = object.getProto()) {
final ArrayData array = object.getArray();
if (getArray().has(index)) {
return getArray().getInt(index);
}
if (array.has(index)) {
return array.getInt(index);
}
final FindProperty find = findProperty(convertKey(key), false);
final FindProperty find = object.findProperty(key, false);
if (find != null) {
return getIntValue(find);
if (find != null) {
return getIntValue(new FindProperty(this, find.getOwner(), find.getProperty()));
}
}
final ScriptObject proto = this.getProto();
return JSType.toInt32(invokeNoSuchProperty(key));
}
return proto != null ? proto.getInt(key) : 0;
@Override
public int getInt(final Object key) {
return getInt(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public int getInt(final double key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getInt(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getIntValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.getInt(key) : 0;
return getInt(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public int getInt(final long key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getInt(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getIntValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.getInt(key) : 0;
return getInt(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public int getInt(final int key) {
final int index = getArrayIndexNoThrow(key);
return getInt(getArrayIndexNoThrow(key), convertKey(key));
}
if (getArray().has(index)) {
return getArray().getInt(index);
}
private long getLong(final int index, final String key) {
for (ScriptObject object = this; object != null; object = object.getProto()) {
final ArrayData array = object.getArray();
final FindProperty find = findProperty(convertKey(key), false);
if (array.has(index)) {
return array.getLong(index);
}
if (find != null) {
return getIntValue(find);
}
final FindProperty find = object.findProperty(key, false);
final ScriptObject proto = this.getProto();
if (find != null) {
return getLongValue(new FindProperty(this, find.getOwner(), find.getProperty()));
}
}
return proto != null ? proto.getInt(key) : 0;
return JSType.toLong(invokeNoSuchProperty(key));
}
@Override
public long getLong(final Object key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getLong(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getLongValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.getLong(key) : 0L;
return getLong(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public long getLong(final double key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getLong(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getLongValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.getLong(key) : 0L;
return getLong(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public long getLong(final long key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getLong(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getLongValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.getLong(key) : 0L;
return getLong(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public long getLong(final int key) {
final int index = getArrayIndexNoThrow(key);
return getLong(getArrayIndexNoThrow(key), convertKey(key));
}
if (getArray().has(index)) {
return getArray().getLong(index);
}
private double getDouble(final int index, final String key) {
for (ScriptObject object = this; object != null; object = object.getProto()) {
final ArrayData array = object.getArray();
final FindProperty find = findProperty(convertKey(key), false);
if (array.has(index)) {
return array.getDouble(index);
}
if (find != null) {
return getLongValue(find);
}
final FindProperty find = object.findProperty(key, false);
final ScriptObject proto = this.getProto();
if (find != null) {
return getDoubleValue(new FindProperty(this, find.getOwner(), find.getProperty()));
}
}
return proto != null ? proto.getLong(key) : 0L;
return JSType.toNumber(invokeNoSuchProperty(key));
}
@Override
public double getDouble(final Object key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getDouble(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getDoubleValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.getDouble(key) : Double.NaN;
return getDouble(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public double getDouble(final double key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getDouble(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getDoubleValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.getDouble(key) : Double.NaN;
return getDouble(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public double getDouble(final long key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getDouble(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getDoubleValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.getDouble(key) : Double.NaN;
return getDouble(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public double getDouble(final int key) {
final int index = getArrayIndexNoThrow(key);
return getDouble(getArrayIndexNoThrow(key), convertKey(key));
}
if (getArray().has(index)) {
return getArray().getDouble(index);
}
private Object get(final int index, final String key) {
for (ScriptObject object = this; object != null; object = object.getProto()) {
final ArrayData array = object.getArray();
final FindProperty find = findProperty(convertKey(key), false);
if (array.has(index)) {
return array.getObject(index);
}
if (find != null) {
return getDoubleValue(find);
}
final FindProperty find = object.findProperty(key, false);
final ScriptObject proto = this.getProto();
if (find != null) {
return getObjectValue(new FindProperty(this, find.getOwner(), find.getProperty()));
}
}
return proto != null ? proto.getDouble(key) : Double.NaN;
return invokeNoSuchProperty(key);
}
@Override
public Object get(final Object key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getObject(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getObjectValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.get(key) : UNDEFINED;
return get(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public Object get(final double key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getObject(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getObjectValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.get(key) : UNDEFINED;
return get(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public Object get(final long key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getObject(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getObjectValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.get(key) : UNDEFINED;
return get(getArrayIndexNoThrow(key), convertKey(key));
}
@Override
public Object get(final int key) {
final int index = getArrayIndexNoThrow(key);
if (getArray().has(index)) {
return getArray().getObject(index);
}
final FindProperty find = findProperty(convertKey(key), false);
if (find != null) {
return getObjectValue(find);
}
final ScriptObject proto = this.getProto();
return proto != null ? proto.get(key) : UNDEFINED;
return get(getArrayIndexNoThrow(key), convertKey(key));
}
/**
......@@ -2613,8 +2480,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
f = null;
}
MethodHandle setter;
if (f != null) {
if (!f.getProperty().isWritable()) {
if (strict) {
......@@ -2624,9 +2489,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return;
}
setter = f.getSetter(Object.class, strict); //TODO specfields
try {
setter.invokeExact((Object)f.getOwner(), value);
final MethodHandle setter = f.getSetter(Object.class, strict); //TODO specfields
setter.invokeExact((Object)f.getSetterReceiver(), value);
} catch (final Error|RuntimeException e) {
throw e;
} catch (final Throwable e) {
......
......@@ -252,7 +252,11 @@ public final class WithObject extends ScriptObject implements Scope {
}
private static GuardedInvocation fixScopeCallSite(final GuardedInvocation link) {
return link.replaceMethods(filter(link.getInvocation(), WITHSCOPEFILTER), filterGuard(link, WITHSCOPEFILTER));
// The receiver may be an object or a ScriptObject.
final MethodType invType = link.getInvocation().type();
final MethodType newInvType = invType.changeParameterType(0, WITHSCOPEFILTER.type().returnType());
final GuardedInvocation newLink = link.asType(newInvType);
return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER), filterGuard(newLink, WITHSCOPEFILTER));
}
private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) {
......
/*
* 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-8011578 : -Dnashorn.unstable.relink.threshold=1 causes tests to fail.
*
* @test
* @option -Dnashorn.unstable.relink.threshold=1
* @run
*/
load(__DIR__ + "NASHORN-296.js");
load(__DIR__ + "NASHORN-691.js");
load(__DIR__ + "calllink.js");
load(__DIR__ + "nosuchproperty.js");
__noSuchProperty__ = function(x) {
print(x);
return x;
}
print(this["find"]);
o.foo = 33
o.foo = 44
o.foo = 3
o.foo = hello
obj1.func called
obj2.func called
no such method: func
obj4's prototype func called
MyConstructor.prototype.func
MyConstructor.prototype.func
obj1.func called
obj2.func called
new obj3.func called
new obj4.func called
all new MyConstructor.prototype.func
all new MyConstructor.prototype.func
obj.__noSuchProperty__ for foo
new obj.__noSuchProperty__ for foo
proto.__noSuchProperty__ for foo
new proto.__noSuchProperty__ for foo
find
find
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册