< 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


 118         if (lastDot == -1) {
 119             return cn;
 120         }
 121         return cn.substring(lastDot + 1);
 122     }
 123 
 124     /**
 125      * Checks if various symbols that were provisionally marked as needing a slot ended up unused, and marks them as not
 126      * needing a slot after all.
 127      * @param functionNode the function node
 128      * @return the passed in node, for easy chaining
 129      */
 130     private static FunctionNode removeUnusedSlots(final FunctionNode functionNode) {
 131         if (!functionNode.needsCallee()) {
 132             functionNode.compilerConstant(CALLEE).setNeedsSlot(false);
 133         }
 134         if (!(functionNode.hasScopeBlock() || functionNode.needsParentScope())) {
 135             functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
 136         }
 137         // Named function expressions that end up not referencing themselves won't need a local slot for the self symbol.
 138         if(!functionNode.isDeclared() && !functionNode.usesSelfSymbol() && !functionNode.isAnonymous()) {
 139             final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName());
 140             if(selfSymbol != null) {
 141                 if(selfSymbol.isFunctionSelf()) {
 142                     selfSymbol.setNeedsSlot(false);
 143                     selfSymbol.clearFlag(Symbol.IS_VAR);
 144                 }
 145             } else {
 146                 assert functionNode.isProgram();
 147             }
 148         }
 149         return functionNode;
 150     }
 151 
 152     private final Deque<Set<String>> thisProperties = new ArrayDeque<>();
 153     private final Map<String, Symbol> globalSymbols = new HashMap<>(); //reuse the same global symbol
 154     private final Compiler compiler;
 155 
 156     public AssignSymbols(final Compiler compiler) {
 157         super(new LexicalContext());
 158         this.compiler = compiler;
 159         this.log   = initLogger(compiler.getContext());
 160         this.debug = log.isEnabled();
 161     }
 162 
 163     @Override
 164     public DebugLogger getLogger() {
 165         return log;
 166     }
 167 


 473         start(catchNode);
 474 
 475         // define block-local exception variable
 476         final String exname = exception.getName();
 477         // If the name of the exception starts with ":e", this is a synthetic catch block, likely a catch-all. Its
 478         // symbol is naturally internal, and should be treated as such.
 479         final boolean isInternal = exname.startsWith(EXCEPTION_PREFIX.symbolName());
 480         // IS_LET flag is required to make sure symbol is not visible outside catch block. However, we need to
 481         // clear the IS_LET flag after creation to allow redefinition of symbol inside the catch block.
 482         final Symbol symbol = defineSymbol(block, exname, catchNode, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE);
 483         symbol.clearFlag(IS_LET);
 484 
 485         return true;
 486     }
 487 
 488     private void enterFunctionBody() {
 489         final FunctionNode functionNode = lc.getCurrentFunction();
 490         final Block body = lc.getCurrentBlock();
 491 
 492         initFunctionWideVariables(functionNode, body);










 493 
 494         if (!functionNode.isProgram() && !functionNode.isDeclared() && !functionNode.isAnonymous()) {
 495             // It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's
 496             // anonymous.
 497             final String name = functionNode.getIdent().getName();
 498             assert name != null;
 499             assert body.getExistingSymbol(name) == null;






 500             defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
 501             if(functionNode.allVarsInScope()) { // basically, has deep eval

 502                 lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
 503             }
 504         }
 505 
 506         acceptDeclarations(functionNode, body);
 507     }
 508 
 509     @Override
 510     public boolean enterFunctionNode(final FunctionNode functionNode) {
 511         start(functionNode, false);
 512 
 513         thisProperties.push(new HashSet<String>());
 514 
 515         // Every function has a body, even the ones skipped on reparse (they have an empty one). We're
 516         // asserting this as even for those, enterBlock() must be invoked to correctly process symbols that
 517         // are used in them.
 518         assert functionNode.getBody() != null;
 519 
 520         return true;
 521     }
 522 
 523     @Override
 524     public boolean enterVarNode(final VarNode varNode) {
 525         start(varNode);
 526         // Normally, a symbol assigned in a var statement is not live for its RHS. Since we also represent function




 118         if (lastDot == -1) {
 119             return cn;
 120         }
 121         return cn.substring(lastDot + 1);
 122     }
 123 
 124     /**
 125      * Checks if various symbols that were provisionally marked as needing a slot ended up unused, and marks them as not
 126      * needing a slot after all.
 127      * @param functionNode the function node
 128      * @return the passed in node, for easy chaining
 129      */
 130     private static FunctionNode removeUnusedSlots(final FunctionNode functionNode) {
 131         if (!functionNode.needsCallee()) {
 132             functionNode.compilerConstant(CALLEE).setNeedsSlot(false);
 133         }
 134         if (!(functionNode.hasScopeBlock() || functionNode.needsParentScope())) {
 135             functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
 136         }
 137         // Named function expressions that end up not referencing themselves won't need a local slot for the self symbol.
 138         if(functionNode.isNamedFunctionExpression() && !functionNode.usesSelfSymbol()) {
 139             final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName());
 140             if(selfSymbol != null && selfSymbol.isFunctionSelf()) {

 141                 selfSymbol.setNeedsSlot(false);
 142                 selfSymbol.clearFlag(Symbol.IS_VAR);
 143             }



 144         }
 145         return functionNode;
 146     }
 147 
 148     private final Deque<Set<String>> thisProperties = new ArrayDeque<>();
 149     private final Map<String, Symbol> globalSymbols = new HashMap<>(); //reuse the same global symbol
 150     private final Compiler compiler;
 151 
 152     public AssignSymbols(final Compiler compiler) {
 153         super(new LexicalContext());
 154         this.compiler = compiler;
 155         this.log   = initLogger(compiler.getContext());
 156         this.debug = log.isEnabled();
 157     }
 158 
 159     @Override
 160     public DebugLogger getLogger() {
 161         return log;
 162     }
 163 


 469         start(catchNode);
 470 
 471         // define block-local exception variable
 472         final String exname = exception.getName();
 473         // If the name of the exception starts with ":e", this is a synthetic catch block, likely a catch-all. Its
 474         // symbol is naturally internal, and should be treated as such.
 475         final boolean isInternal = exname.startsWith(EXCEPTION_PREFIX.symbolName());
 476         // IS_LET flag is required to make sure symbol is not visible outside catch block. However, we need to
 477         // clear the IS_LET flag after creation to allow redefinition of symbol inside the catch block.
 478         final Symbol symbol = defineSymbol(block, exname, catchNode, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE);
 479         symbol.clearFlag(IS_LET);
 480 
 481         return true;
 482     }
 483 
 484     private void enterFunctionBody() {
 485         final FunctionNode functionNode = lc.getCurrentFunction();
 486         final Block body = lc.getCurrentBlock();
 487 
 488         initFunctionWideVariables(functionNode, body);
 489         acceptDeclarations(functionNode, body);
 490         defineFunctionSelfSymbol(functionNode, body);
 491     }
 492 
 493     private void defineFunctionSelfSymbol(final FunctionNode functionNode, final Block body) {
 494         // Function self-symbol is only declared as a local variable for named function expressions. Declared functions
 495         // don't need it as they are local variables in their declaring scope.
 496         if (!functionNode.isNamedFunctionExpression()) {
 497             return;
 498         }
 499 



 500         final String name = functionNode.getIdent().getName();
 501         assert name != null; // As it's a named function expression.
 502 
 503         if (body.getExistingSymbol(name) != null) {
 504             // Body already has a declaration for the name. It's either a parameter "function x(x)" or a
 505             // top-level variable "function x() { ... var x; ... }".
 506             return;
 507         }
 508 
 509         defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
 510         if(functionNode.allVarsInScope()) { // basically, has deep eval
 511             // We must conservatively presume that eval'd code can dynamically use the function symbol.
 512             lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
 513         }



 514     }
 515 
 516     @Override
 517     public boolean enterFunctionNode(final FunctionNode functionNode) {
 518         start(functionNode, false);
 519 
 520         thisProperties.push(new HashSet<String>());
 521 
 522         // Every function has a body, even the ones skipped on reparse (they have an empty one). We're
 523         // asserting this as even for those, enterBlock() must be invoked to correctly process symbols that
 524         // are used in them.
 525         assert functionNode.getBody() != null;
 526 
 527         return true;
 528     }
 529 
 530     @Override
 531     public boolean enterVarNode(final VarNode varNode) {
 532         start(varNode);
 533         // Normally, a symbol assigned in a var statement is not live for its RHS. Since we also represent function


< prev index next >