8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook
authorsundar
Wed, 04 Jun 2014 13:55:21 +0530
changeset 24777 ed1974940ff4
parent 24776 966226aeee50
child 24778 2ff5d7041566
8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook Reviewed-by: attila, lagergren, hannesw
nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
nashorn/test/script/basic/JDK-8044750.js
nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Jun 03 12:05:59 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Jun 04 13:55:21 2014 +0530
@@ -156,7 +156,7 @@
     /** Method handle to retrieve prototype of this object */
     public static final MethodHandle GETPROTO      = findOwnMH_V("getProto", ScriptObject.class);
 
-    static final MethodHandle MEGAMORPHIC_GET    = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class, boolean.class);
+    static final MethodHandle MEGAMORPHIC_GET    = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class);
     static final MethodHandle GLOBALFILTER       = findOwnMH_S("globalFilter", Object.class, Object.class);
 
     private static final MethodHandle TRUNCATINGFILTER   = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class);
@@ -1924,7 +1924,7 @@
         }
 
         if (request.isCallSiteUnstable() || hasWithScope()) {
-            return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator), isScope() && NashornCallSiteDescriptor.isScope(desc));
+            return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator));
         }
 
         final FindProperty find = findProperty(name, true);
@@ -1983,22 +1983,19 @@
         return inv.addSwitchPoint(reservedNameSwitchPoint);
     }
 
-    private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod, final boolean isScope) {
+    private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
         Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
-        final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, isScope);
+        final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
         final MethodHandle guard   = getScriptObjectGuard(desc.getMethodType(), true);
         return new GuardedInvocation(invoker, guard);
     }
 
     @SuppressWarnings("unused")
-    private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
+    private Object megamorphicGet(final String key, final boolean isMethod) {
         final FindProperty find = findProperty(key, true);
         if (find != null) {
             return find.getObjectValue();
         }
-        if (isScope) {
-            throw referenceError("not.defined", key);
-        }
 
         return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8044750.js	Wed Jun 04 13:55:21 2014 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 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-8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook
+ *
+ * @test
+ * @run
+ */
+
+__noSuchProperty__ = function(name) {
+    return 1;
+}
+
+function func(obj) {
+    with(obj) {
+        // this "foo" getter site becomes megamorphic
+        // due to different 'with' scope objects.
+        foo;
+    }
+}
+
+for (var i = 0; i < 20; i++) {
+    var obj = {};
+    obj.foo = i;
+    obj[i] = i;
+    func(obj);
+}
+
+// pass a 'with' scope object that does not have 'foo'.
+// callsite inside func should see __noSuchProperty__
+// hook on global scope object.
+func({});
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java	Tue Jun 03 12:05:59 2014 +0200
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java	Wed Jun 04 13:55:21 2014 +0530
@@ -512,6 +512,23 @@
         assertEquals(e.eval("x", newCtxt), 2);
     }
 
+    // @bug 8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook
+    @Test
+    public static void testMegamorphicGetInGlobal() throws Exception {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine engine = m.getEngineByName("nashorn");
+        final String script = "foo";
+        // "foo" is megamorphic because of different global scopes.
+        // Make sure ScriptContext variable search works even after
+        // it becomes megamorphic.
+        for (int index = 0; index < 25; index++) {
+            final Bindings bindings = new SimpleBindings();
+            bindings.put("foo", index);
+            final Number value = (Number)engine.eval(script, bindings);
+            assertEquals(index, value.intValue());
+        }
+    }
+
     /**
      * Test "slow" scopes involving {@code with} and {@code eval} statements for shared script classes with multiple globals.
      */