< prev index next >

src/jdk/nashorn/internal/codegen/AssignSymbols.java

Print this page
rev 1338 : 8066222: too strong assertion on function expression names
Reviewed-by: hannesw, lagergren

@@ -133,20 +133,16 @@
         }
         if (!(functionNode.hasScopeBlock() || functionNode.needsParentScope())) {
             functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
         }
         // Named function expressions that end up not referencing themselves won't need a local slot for the self symbol.
-        if(!functionNode.isDeclared() && !functionNode.usesSelfSymbol() && !functionNode.isAnonymous()) {
+        if(functionNode.isNamedFunctionExpression() && !functionNode.usesSelfSymbol()) {
             final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName());
-            if(selfSymbol != null) {
-                if(selfSymbol.isFunctionSelf()) {
+            if(selfSymbol != null && selfSymbol.isFunctionSelf()) {
                     selfSymbol.setNeedsSlot(false);
                     selfSymbol.clearFlag(Symbol.IS_VAR);
                 }
-            } else {
-                assert functionNode.isProgram();
-            }
         }
         return functionNode;
     }
 
     private final Deque<Set<String>> thisProperties = new ArrayDeque<>();

@@ -488,26 +484,37 @@
     private void enterFunctionBody() {
         final FunctionNode functionNode = lc.getCurrentFunction();
         final Block body = lc.getCurrentBlock();
 
         initFunctionWideVariables(functionNode, body);
+        acceptDeclarations(functionNode, body);
+        defineFunctionSelfSymbol(functionNode, body);
+    }
+
+    private void defineFunctionSelfSymbol(final FunctionNode functionNode, final Block body) {
+        // Function self-symbol is only declared as a local variable for named function expressions. Declared functions
+        // don't need it as they are local variables in their declaring scope.
+        if (!functionNode.isNamedFunctionExpression()) {
+            return;
+        }
 
-        if (!functionNode.isProgram() && !functionNode.isDeclared() && !functionNode.isAnonymous()) {
-            // It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's
-            // anonymous.
             final String name = functionNode.getIdent().getName();
-            assert name != null;
-            assert body.getExistingSymbol(name) == null;
+        assert name != null; // As it's a named function expression.
+
+        if (body.getExistingSymbol(name) != null) {
+            // Body already has a declaration for the name. It's either a parameter "function x(x)" or a
+            // top-level variable "function x() { ... var x; ... }".
+            return;
+        }
+
             defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
             if(functionNode.allVarsInScope()) { // basically, has deep eval
+            // We must conservatively presume that eval'd code can dynamically use the function symbol.
                 lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
             }
         }
 
-        acceptDeclarations(functionNode, body);
-    }
-
     @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
         start(functionNode, false);
 
         thisProperties.push(new HashSet<String>());
< prev index next >