8136694: Megemorphic scope access does not throw ReferenceError when property is missing

Reviewed-by: attila, hannesw
This commit is contained in:
Athijegannathan Sundararajan 2015-09-17 18:23:53 +05:30
parent f74c628ffe
commit c2898271c9
3 changed files with 116 additions and 10 deletions

View File

@ -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;
}

View File

@ -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);
}

View 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);