8007460: var assignment to a parameter in a varargs method causes compilation error
authorattila
Mon, 04 Feb 2013 15:59:44 +0100
changeset 16209 18e55b352d56
parent 16208 0d15274b2326
child 16210 8ad1381b69d0
8007460: var assignment to a parameter in a varargs method causes compilation error Reviewed-by: jlaskey, lagergren
nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
nashorn/test/script/basic/JDK-8007460.js
nashorn/test/script/basic/JDK-8007460.js.EXPECTED
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Mon Feb 04 08:13:05 2013 -0400
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Mon Feb 04 15:59:44 2013 +0100
@@ -201,10 +201,7 @@
         final Symbol symbol = identNode.getSymbol();
 
         if (!symbol.isScope()) {
-            if(symbol.isParam()) {
-                return method.loadParam(symbol);
-            }
-            assert symbol.hasSlot() && symbol.getSlot() != 0 || symbol.isThis();
+            assert symbol.hasSlot() || symbol.isParam();
             return method.load(symbol);
         }
 
@@ -3200,11 +3197,7 @@
                         }
                     } else {
                         assert symbol != null;
-                        if(symbol.isParam()) {
-                            method.storeParam(symbol);
-                        } else {
-                            method.store(symbol);
-                        }
+                        method.store(symbol);
                     }
                     return null;
 
--- a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Mon Feb 04 08:13:05 2013 -0400
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Mon Feb 04 15:59:44 2013 +0100
@@ -829,44 +829,26 @@
     public MethodEmitter load(final Symbol symbol) {
         assert symbol != null;
         if (symbol.hasSlot()) {
-            debug("load symbol", symbol.getName() + " slot=" + symbol.getSlot());
-            pushType(symbol.getSymbolType().load(method, symbol.getSlot()));
-        }
-        return this;
-    }
-
-    /**
-     * Push a non-scope function parameter to the stack. Function parameters always arrive into a function as either
-     * explicit parameters on the stack, or collected into a final variable-arity {@code Object[]} parameter. If they
-     * end up being scoped (i.e. referenced from a child function or eval), then they're loaded as scoped symbols and
-     * this function is not invoked for them. If they aren't scoped, then they will be loaded from one of three places.
-     * First, if the function has an Arguments object, they're loaded from it. Otherwise, if the parameters come in a
-     * {@code Object[]} array, they are loaded from the array. Finally, if neither is the case, they're simply loaded
-     * from their bytecode slot.
-     *
-     * @param symbol the symbol representing the parameter.
-     *
-     * @return the method emitter
-     */
-    public MethodEmitter loadParam(final Symbol symbol) {
-        assert symbol != null && symbol.isParam() && !symbol.isScope();
-        if(symbol.hasSlot()) {
-            // Check that we aren't vararg, except if we're loading "this"
-            assert symbol.isThis() || !functionNode.isVarArg() : "Symbol=" + symbol + " functionNode=" + functionNode.getName();
-            // Just load it from a local variable
-            return load(symbol);
-        }
-        assert functionNode.isVarArg();
-        if(functionNode.needsArguments()) {
-            // ScriptObject.getArgument(int) on arguments
-            loadArguments();
-            load(symbol.getFieldIndex());
-            ScriptObject.GET_ARGUMENT.invoke(this);
-        } else {
-            // array load from __varargs__
-            loadVarArgs();
-            load(symbol.getFieldIndex());
-            arrayload();
+            final int slot = symbol.getSlot();
+            debug("load symbol", symbol.getName(), " slot=", slot);
+            pushType(symbol.getSymbolType().load(method, slot));
+        } else if (symbol.isParam()) {
+            assert !symbol.isScope();
+            assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
+            final int index = symbol.getFieldIndex();
+            if(functionNode.needsArguments()) {
+                // ScriptObject.getArgument(int) on arguments
+                debug("load symbol", symbol.getName(), " arguments index=", index);
+                loadArguments();
+                load(index);
+                ScriptObject.GET_ARGUMENT.invoke(this);
+            } else {
+                // array load from __varargs__
+                debug("load symbol", symbol.getName(), " array index=", index);
+                loadVarArgs();
+                load(symbol.getFieldIndex());
+                arrayload();
+            }
         }
         return this;
     }
@@ -1033,46 +1015,29 @@
     public void store(final Symbol symbol) {
         assert symbol != null : "No symbol to store";
         if (symbol.hasSlot()) {
-            debug("store", symbol);
-            popType(symbol.getSymbolType()).store(method, symbol.getSlot());
+            final int slot = symbol.getSlot();
+            debug("store symbol", symbol.getName(), " slot=", slot);
+            popType(symbol.getSymbolType()).store(method, slot);
+        } else if (symbol.isParam()) {
+            assert !symbol.isScope();
+            assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
+            final int index = symbol.getFieldIndex();
+            if(functionNode.needsArguments()) {
+                debug("store symbol", symbol.getName(), " arguments index=", index);
+                loadArguments();
+                load(index);
+                ArgumentSetter.SET_ARGUMENT.invoke(this);
+            } else {
+                // varargs without arguments object - just do array store to __varargs__
+                debug("store symbol", symbol.getName(), " array index=", index);
+                loadVarArgs();
+                load(index);
+                ArgumentSetter.SET_ARRAY_ELEMENT.invoke(this);
+            }
         }
     }
 
     /**
-     * Pop a value from the stack and store it in a non-scope function parameter. Function parameters always arrive into
-     * a function as either explicit parameters on th stack, or collected into a final variable-arity {@code Object[]}
-     * parameter. If they end up being scoped (i.e. referenced from a child function or eval), then they're stored as
-     * scoped symbols are and this function is not invoked for them. If they aren't scoped, then they will be stored
-     * to one of three places. First, if the function has an Arguments object, they're stored to it. Otherwise, if the
-     * parameters come in a {@code Object[]} array, they are stored to the array. Finally, if neither is the case,
-     * they're simply stored to their bytecode slot.
-     *
-     * @param symbol the symbol representing the parameter.
-     *
-     */
-    public void storeParam(final Symbol symbol) {
-        assert symbol != null && symbol.isParam() && !symbol.isScope();
-        if(symbol.hasSlot()) {
-            assert !functionNode.isVarArg();
-            // Just store it to a local variable
-            store(symbol);
-            return;
-        }
-        assert functionNode.isVarArg();
-        if(functionNode.needsArguments()) {
-            loadArguments();
-            load(symbol.getFieldIndex());
-            ArgumentSetter.SET_ARGUMENT.invoke(this);
-        } else {
-            // varargs without arguments object - just do array store to __varargs__
-            loadVarArgs();
-            load(symbol.getFieldIndex());
-            ArgumentSetter.SET_ARRAY_ELEMENT.invoke(this);
-        }
-    }
-
-
-    /**
      * Pop a value from the stack and store it in a given local variable
      * slot.
      *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8007460.js	Mon Feb 04 15:59:44 2013 +0100
@@ -0,0 +1,40 @@
+/*
+ * 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-8007460: code generation error for variable-argument function that has a var-assignment to one of its parameters
+ *
+ * @test
+ * @run
+ */
+
+function f(y) {
+  print(y)
+  print(arguments[0])
+
+  var y = 1
+
+  print(y)
+  print(arguments[0])
+}
+f(2)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8007460.js.EXPECTED	Mon Feb 04 15:59:44 2013 +0100
@@ -0,0 +1,4 @@
+2
+2
+1
+1