8136694: Megemorphic scope access does not throw ReferenceError when property is missing
Reviewed-by: attila, hannesw
This commit is contained in:
parent
f74c628ffe
commit
c2898271c9
@ -2402,17 +2402,15 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
|
||||
*/
|
||||
protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) {
|
||||
final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
|
||||
final Object func = (find != null)? find.getObjectValue() : null;
|
||||
|
||||
Object ret = UNDEFINED;
|
||||
|
||||
if (find != null) {
|
||||
final Object func = find.getObjectValue();
|
||||
|
||||
if (func instanceof ScriptFunction) {
|
||||
final ScriptFunction sfunc = (ScriptFunction)func;
|
||||
final Object self = isScope && sfunc.isStrict()? UNDEFINED : this;
|
||||
ret = ScriptRuntime.apply(sfunc, self, name);
|
||||
}
|
||||
if (func instanceof ScriptFunction) {
|
||||
final ScriptFunction sfunc = (ScriptFunction)func;
|
||||
final Object self = isScope && sfunc.isStrict()? UNDEFINED : this;
|
||||
ret = ScriptRuntime.apply(sfunc, self, name);
|
||||
} else if (isScope) {
|
||||
throw referenceError("not.defined", name);
|
||||
}
|
||||
|
||||
if (isValid(programPoint)) {
|
||||
@ -2438,6 +2436,9 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable {
|
||||
|
||||
final Object value = find.getObjectValue();
|
||||
if (!(value instanceof ScriptFunction)) {
|
||||
if (isScope) {
|
||||
throw referenceError("not.defined", name);
|
||||
}
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
||||
* JDK-8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook
|
||||
*
|
||||
* @test
|
||||
* @fork
|
||||
* @option -Dnashorn.unstable.relink.threshold=16
|
||||
* @run
|
||||
*/
|
||||
|
||||
@ -40,7 +42,9 @@ function func(obj) {
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < 20; i++) {
|
||||
var LIMIT = 20; // should be more than megamorphic threshold set via @option
|
||||
|
||||
for (var i = 0; i < LIMIT; i++) {
|
||||
var obj = {};
|
||||
obj.foo = i;
|
||||
obj[i] = i;
|
||||
@ -51,3 +55,30 @@ for (var i = 0; i < 20; i++) {
|
||||
// callsite inside func should see __noSuchProperty__
|
||||
// hook on global scope object.
|
||||
func({});
|
||||
|
||||
function checkFoo() {
|
||||
with({}) {
|
||||
try {
|
||||
foo;
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var oldNoSuchProperty = this.__noSuchProperty__;
|
||||
delete this.__noSuchProperty__;
|
||||
|
||||
// keep deleting/restorting __noSuchProperty__ alternatively
|
||||
// to make "foo" access in checkFoo function megamorphic!
|
||||
|
||||
for (var i = 0; i < LIMIT; i++) {
|
||||
// no __noSuchProperty__ and 'with' scope object has no 'foo'
|
||||
delete __noSuchProperty__;
|
||||
Assert.assertFalse(checkFoo(), "Expected false in iteration " + i);
|
||||
|
||||
// __noSuchProperty__ is exists but 'with' scope object has no 'foo'
|
||||
this.__noSuchProperty__ = oldNoSuchProperty;
|
||||
Assert.assertTrue(checkFoo(), "Expected true in iteration " + i);
|
||||
}
|
||||
|
74
nashorn/test/script/basic/JDK-8136694.js
Normal file
74
nashorn/test/script/basic/JDK-8136694.js
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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-8136694: Megemorphic scope access does not throw ReferenceError when property is missing
|
||||
*
|
||||
* @test
|
||||
* @fork
|
||||
* @option -Dnashorn.unstable.relink.threshold=16
|
||||
* @run
|
||||
*/
|
||||
|
||||
function checkFoo() {
|
||||
try {
|
||||
// The 'foo' access becomes megamorphic
|
||||
foo;
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Similar check for 'with' blocks as well.
|
||||
function checkFooInWith() {
|
||||
with({}) {
|
||||
try {
|
||||
// The 'foo' access becomes megamorphic
|
||||
foo;
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loop(checker) {
|
||||
// LIMIT has to be more than the megamorphic threashold
|
||||
// set via @option in this test header!
|
||||
var LIMIT = 20;
|
||||
for (var i = 0; i < LIMIT; i++) {
|
||||
// make sure global has no "foo"
|
||||
delete foo;
|
||||
Assert.assertFalse(checker(), "Expected false in interation " + i);
|
||||
|
||||
// now add 'foo' in global
|
||||
foo = 44;
|
||||
Assert.assertTrue(checker(), "Expected true in interation " + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
loop(checkFoo);
|
||||
loop(checkFooInWith);
|
Loading…
Reference in New Issue
Block a user