Thu, 23 May 2013 15:51:08 +0200
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
Reviewed-by: attila, jlaskey
1.1 --- a/src/jdk/nashorn/internal/codegen/Attr.java Thu May 23 09:49:03 2013 -0300 1.2 +++ b/src/jdk/nashorn/internal/codegen/Attr.java Thu May 23 15:51:08 2013 +0200 1.3 @@ -84,8 +84,8 @@ 1.4 import jdk.nashorn.internal.ir.UnaryNode; 1.5 import jdk.nashorn.internal.ir.VarNode; 1.6 import jdk.nashorn.internal.ir.WithNode; 1.7 +import jdk.nashorn.internal.ir.visitor.NodeVisitor; 1.8 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; 1.9 -import jdk.nashorn.internal.ir.visitor.NodeVisitor; 1.10 import jdk.nashorn.internal.parser.TokenType; 1.11 import jdk.nashorn.internal.runtime.Context; 1.12 import jdk.nashorn.internal.runtime.Debug; 1.13 @@ -111,7 +111,7 @@ 1.14 * computed. 1.15 */ 1.16 1.17 -final class Attr extends NodeOperatorVisitor { 1.18 +final class Attr extends NodeOperatorVisitor<LexicalContext> { 1.19 1.20 /** 1.21 * Local definitions in current block (to discriminate from function 1.22 @@ -138,6 +138,7 @@ 1.23 * Constructor. 1.24 */ 1.25 Attr(final TemporarySymbols temporarySymbols) { 1.26 + super(new LexicalContext()); 1.27 this.temporarySymbols = temporarySymbols; 1.28 this.localDefs = new ArrayDeque<>(); 1.29 this.localUses = new ArrayDeque<>(); 1.30 @@ -202,7 +203,7 @@ 1.31 private void acceptDeclarations(final FunctionNode functionNode, final Block body) { 1.32 // This visitor will assign symbol to all declared variables, except function declarations (which are taken care 1.33 // in a separate step above) and "var" declarations in for loop initializers. 1.34 - body.accept(new NodeOperatorVisitor() { 1.35 + body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 1.36 @Override 1.37 public boolean enterFunctionNode(final FunctionNode nestedFn) { 1.38 return false; 1.39 @@ -218,7 +219,7 @@ 1.40 if (varNode.isFunctionDeclaration()) { 1.41 newType(symbol, FunctionNode.FUNCTION_TYPE); 1.42 } 1.43 - return varNode.setName((IdentNode)ident.setSymbol(getLexicalContext(), symbol)); 1.44 + return varNode.setName((IdentNode)ident.setSymbol(lc, symbol)); 1.45 } 1.46 return varNode; 1.47 } 1.48 @@ -227,8 +228,8 @@ 1.49 1.50 private void enterFunctionBody() { 1.51 1.52 - final FunctionNode functionNode = getLexicalContext().getCurrentFunction(); 1.53 - final Block body = getLexicalContext().getCurrentBlock(); 1.54 + final FunctionNode functionNode = lc.getCurrentFunction(); 1.55 + final Block body = lc.getCurrentBlock(); 1.56 1.57 initFunctionWideVariables(functionNode, body); 1.58 1.59 @@ -256,7 +257,7 @@ 1.60 //the symbols in the block should really be stateless 1.61 block.clearSymbols(); 1.62 1.63 - if (getLexicalContext().isFunctionBody()) { 1.64 + if (lc.isFunctionBody()) { 1.65 enterFunctionBody(); 1.66 } 1.67 pushLocalsBlock(); 1.68 @@ -283,7 +284,7 @@ 1.69 @Override 1.70 public boolean enterCatchNode(final CatchNode catchNode) { 1.71 final IdentNode exception = catchNode.getException(); 1.72 - final Block block = getLexicalContext().getCurrentBlock(); 1.73 + final Block block = lc.getCurrentBlock(); 1.74 1.75 start(catchNode); 1.76 1.77 @@ -298,10 +299,10 @@ 1.78 @Override 1.79 public Node leaveCatchNode(final CatchNode catchNode) { 1.80 final IdentNode exception = catchNode.getException(); 1.81 - final Block block = getLexicalContext().getCurrentBlock(); 1.82 + final Block block = lc.getCurrentBlock(); 1.83 final Symbol symbol = findSymbol(block, exception.getName()); 1.84 assert symbol != null; 1.85 - return end(catchNode.setException((IdentNode)exception.setSymbol(getLexicalContext(), symbol))); 1.86 + return end(catchNode.setException((IdentNode)exception.setSymbol(lc, symbol))); 1.87 } 1.88 1.89 /** 1.90 @@ -320,7 +321,7 @@ 1.91 flags |= IS_SCOPE; 1.92 } 1.93 1.94 - final FunctionNode function = getLexicalContext().getFunction(block); 1.95 + final FunctionNode function = lc.getFunction(block); 1.96 if (symbol != null) { 1.97 // Symbol was already defined. Check if it needs to be redefined. 1.98 if ((flags & KINDMASK) == IS_PARAM) { 1.99 @@ -353,12 +354,12 @@ 1.100 if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) { 1.101 symbolBlock = block; //internal vars are always defined in the block closest to them 1.102 } else { 1.103 - symbolBlock = getLexicalContext().getFunctionBody(function); 1.104 + symbolBlock = lc.getFunctionBody(function); 1.105 } 1.106 1.107 // Create and add to appropriate block. 1.108 symbol = new Symbol(name, flags); 1.109 - symbolBlock.putSymbol(getLexicalContext(), symbol); 1.110 + symbolBlock.putSymbol(lc, symbol); 1.111 1.112 if ((flags & Symbol.KINDMASK) != IS_GLOBAL) { 1.113 symbol.setNeedsSlot(true); 1.114 @@ -381,7 +382,7 @@ 1.115 //an outermost function in our lexical context that is not a program (runScript) 1.116 //is possible - it is a function being compiled lazily 1.117 if (functionNode.isDeclared()) { 1.118 - final Iterator<Block> blocks = getLexicalContext().getBlocks(); 1.119 + final Iterator<Block> blocks = lc.getBlocks(); 1.120 if (blocks.hasNext()) { 1.121 defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR); 1.122 } 1.123 @@ -397,13 +398,11 @@ 1.124 public Node leaveFunctionNode(final FunctionNode functionNode) { 1.125 FunctionNode newFunctionNode = functionNode; 1.126 1.127 - final LexicalContext lc = getLexicalContext(); 1.128 - 1.129 final Block body = newFunctionNode.getBody(); 1.130 1.131 //look for this function in the parent block 1.132 if (functionNode.isDeclared()) { 1.133 - final Iterator<Block> blocks = getLexicalContext().getBlocks(); 1.134 + final Iterator<Block> blocks = lc.getBlocks(); 1.135 if (blocks.hasNext()) { 1.136 newFunctionNode = (FunctionNode)newFunctionNode.setSymbol(lc, findSymbol(blocks.next(), functionNode.getIdent().getName())); 1.137 } 1.138 @@ -411,7 +410,7 @@ 1.139 final boolean anonymous = functionNode.isAnonymous(); 1.140 final String name = anonymous ? null : functionNode.getIdent().getName(); 1.141 if (anonymous || body.getExistingSymbol(name) != null) { 1.142 - newFunctionNode = (FunctionNode)ensureSymbol(lc, FunctionNode.FUNCTION_TYPE, newFunctionNode); 1.143 + newFunctionNode = (FunctionNode)ensureSymbol(FunctionNode.FUNCTION_TYPE, newFunctionNode); 1.144 } else { 1.145 assert name != null; 1.146 final Symbol self = body.getExistingSymbol(name); 1.147 @@ -490,8 +489,6 @@ 1.148 1.149 start(identNode); 1.150 1.151 - final LexicalContext lc = getLexicalContext(); 1.152 - 1.153 if (identNode.isPropertyName()) { 1.154 // assign a pseudo symbol to property name 1.155 final Symbol pseudoSymbol = pseudoSymbol(name); 1.156 @@ -549,7 +546,7 @@ 1.157 */ 1.158 private void maybeForceScope(final Symbol symbol) { 1.159 if (!symbol.isScope() && symbolNeedsToBeScope(symbol)) { 1.160 - Symbol.setSymbolIsScope(getLexicalContext(), symbol); 1.161 + Symbol.setSymbolIsScope(lc, symbol); 1.162 } 1.163 } 1.164 1.165 @@ -558,7 +555,7 @@ 1.166 return false; 1.167 } 1.168 boolean previousWasBlock = false; 1.169 - for(final Iterator<LexicalContextNode> it = getLexicalContext().getAllNodes(); it.hasNext();) { 1.170 + for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) { 1.171 final LexicalContextNode node = it.next(); 1.172 if(node instanceof FunctionNode) { 1.173 // We reached the function boundary without seeing a definition for the symbol - it needs to be in 1.174 @@ -594,10 +591,8 @@ 1.175 } 1.176 1.177 if (symbol.isScope()) { 1.178 - final LexicalContext lc = getLexicalContext(); 1.179 - 1.180 Block scopeBlock = null; 1.181 - for (final Iterator<LexicalContextNode> contextNodeIter = getLexicalContext().getAllNodes(); contextNodeIter.hasNext(); ) { 1.182 + for (final Iterator<LexicalContextNode> contextNodeIter = lc.getAllNodes(); contextNodeIter.hasNext(); ) { 1.183 final LexicalContextNode node = contextNodeIter.next(); 1.184 if (node instanceof Block) { 1.185 if (((Block)node).getExistingSymbol(name) != null) { 1.186 @@ -610,7 +605,7 @@ 1.187 } 1.188 1.189 if (scopeBlock != null) { 1.190 - assert getLexicalContext().contains(scopeBlock); 1.191 + assert lc.contains(scopeBlock); 1.192 lc.setFlag(scopeBlock, Block.NEEDS_SCOPE); 1.193 } 1.194 } 1.195 @@ -622,8 +617,8 @@ 1.196 * @see #needsParentScope() 1.197 */ 1.198 private void setUsesGlobalSymbol() { 1.199 - for (final Iterator<FunctionNode> fns = getLexicalContext().getFunctions(); fns.hasNext();) { 1.200 - getLexicalContext().setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE); 1.201 + for (final Iterator<FunctionNode> fns = lc.getFunctions(); fns.hasNext();) { 1.202 + lc.setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE); 1.203 } 1.204 } 1.205 1.206 @@ -635,7 +630,7 @@ 1.207 private Symbol findSymbol(final Block block, final String name) { 1.208 // Search up block chain to locate symbol. 1.209 1.210 - for (final Iterator<Block> blocks = getLexicalContext().getBlocks(block); blocks.hasNext();) { 1.211 + for (final Iterator<Block> blocks = lc.getBlocks(block); blocks.hasNext();) { 1.212 // Find name. 1.213 final Symbol symbol = blocks.next().getExistingSymbol(name); 1.214 // If found then we are good. 1.215 @@ -656,11 +651,11 @@ 1.216 public Node leaveLiteralNode(final LiteralNode literalNode) { 1.217 assert !literalNode.isTokenType(TokenType.THIS) : "tokentype for " + literalNode + " is this"; //guard against old dead code case. literal nodes should never inherit tokens 1.218 assert literalNode instanceof ArrayLiteralNode || !(literalNode.getValue() instanceof Node) : "literals with Node values not supported"; 1.219 - final Symbol symbol = new Symbol(getLexicalContext().getCurrentFunction().uniqueName(LITERAL_PREFIX.symbolName()), IS_CONSTANT, literalNode.getType()); 1.220 + final Symbol symbol = new Symbol(lc.getCurrentFunction().uniqueName(LITERAL_PREFIX.symbolName()), IS_CONSTANT, literalNode.getType()); 1.221 if (literalNode instanceof ArrayLiteralNode) { 1.222 ((ArrayLiteralNode)literalNode).analyze(); 1.223 } 1.224 - return end(literalNode.setSymbol(getLexicalContext(), symbol)); 1.225 + return end(literalNode.setSymbol(lc, symbol)); 1.226 } 1.227 1.228 @Override 1.229 @@ -676,7 +671,7 @@ 1.230 @Override 1.231 public Node leavePropertyNode(final PropertyNode propertyNode) { 1.232 // assign a pseudo symbol to property name, see NASHORN-710 1.233 - return propertyNode.setSymbol(getLexicalContext(), new Symbol(propertyNode.getKeyName(), 0, Type.OBJECT)); 1.234 + return propertyNode.setSymbol(lc, new Symbol(propertyNode.getKeyName(), 0, Type.OBJECT)); 1.235 } 1.236 1.237 @Override 1.238 @@ -734,11 +729,11 @@ 1.239 type = Type.OBJECT; 1.240 } 1.241 1.242 - switchNode.setTag(newInternal(getLexicalContext().getCurrentFunction().uniqueName(SWITCH_TAG_PREFIX.symbolName()), type)); 1.243 + switchNode.setTag(newInternal(lc.getCurrentFunction().uniqueName(SWITCH_TAG_PREFIX.symbolName()), type)); 1.244 1.245 end(switchNode); 1.246 1.247 - return switchNode.setCases(getLexicalContext(), newCases); 1.248 + return switchNode.setCases(lc, newCases); 1.249 } 1.250 1.251 @Override 1.252 @@ -761,7 +756,7 @@ 1.253 final IdentNode ident = varNode.getName(); 1.254 final String name = ident.getName(); 1.255 1.256 - final Symbol symbol = defineSymbol(getLexicalContext().getCurrentBlock(), name, IS_VAR); 1.257 + final Symbol symbol = defineSymbol(lc.getCurrentBlock(), name, IS_VAR); 1.258 assert symbol != null; 1.259 1.260 // NASHORN-467 - use before definition of vars - conservative 1.261 @@ -781,7 +776,6 @@ 1.262 final IdentNode ident = newVarNode.getName(); 1.263 final String name = ident.getName(); 1.264 1.265 - final LexicalContext lc = getLexicalContext(); 1.266 final Symbol symbol = findSymbol(lc.getCurrentBlock(), ident.getName()); 1.267 1.268 if (init == null) { 1.269 @@ -834,7 +828,7 @@ 1.270 1.271 @Override 1.272 public Node leaveDELETE(final UnaryNode unaryNode) { 1.273 - final FunctionNode currentFunctionNode = getLexicalContext().getCurrentFunction(); 1.274 + final FunctionNode currentFunctionNode = lc.getCurrentFunction(); 1.275 final boolean strictMode = currentFunctionNode.isStrict(); 1.276 final Node rhs = unaryNode.rhs(); 1.277 final Node strictFlagNode = LiteralNode.newInstance(unaryNode, strictMode).accept(this); 1.278 @@ -894,10 +888,10 @@ 1.279 * @return true if the symbol denoted by the specified name in the current lexical context defined in the program level. 1.280 */ 1.281 private boolean isProgramLevelSymbol(final String name) { 1.282 - for(final Iterator<Block> it = getLexicalContext().getBlocks(); it.hasNext();) { 1.283 + for(final Iterator<Block> it = lc.getBlocks(); it.hasNext();) { 1.284 final Block next = it.next(); 1.285 if(next.getExistingSymbol(name) != null) { 1.286 - return next == getLexicalContext().getFunctionBody(getLexicalContext().getOutermostFunction()); 1.287 + return next == lc.getFunctionBody(lc.getOutermostFunction()); 1.288 } 1.289 } 1.290 throw new AssertionError("Couldn't find symbol " + name + " in the context"); 1.291 @@ -914,14 +908,14 @@ 1.292 } 1.293 1.294 private IdentNode compilerConstant(CompilerConstants cc) { 1.295 - final FunctionNode functionNode = getLexicalContext().getCurrentFunction(); 1.296 + final FunctionNode functionNode = lc.getCurrentFunction(); 1.297 return (IdentNode) 1.298 new IdentNode( 1.299 functionNode.getToken(), 1.300 functionNode.getFinish(), 1.301 cc.symbolName()). 1.302 setSymbol( 1.303 - getLexicalContext(), 1.304 + lc, 1.305 functionNode.compilerConstant(cc)); 1.306 } 1.307 1.308 @@ -999,7 +993,7 @@ 1.309 final Node lhs = binaryNode.lhs(); 1.310 1.311 if (lhs instanceof IdentNode) { 1.312 - final Block block = getLexicalContext().getCurrentBlock(); 1.313 + final Block block = lc.getCurrentBlock(); 1.314 final IdentNode ident = (IdentNode)lhs; 1.315 final String name = ident.getName(); 1.316 1.317 @@ -1043,7 +1037,7 @@ 1.318 } 1.319 1.320 private boolean isLocal(FunctionNode function, Symbol symbol) { 1.321 - final FunctionNode definingFn = getLexicalContext().getDefiningFunction(symbol); 1.322 + final FunctionNode definingFn = lc.getDefiningFunction(symbol); 1.323 // Temp symbols are not assigned to a block, so their defining fn is null; those can be assumed local 1.324 return definingFn == null || definingFn == function; 1.325 } 1.326 @@ -1329,7 +1323,7 @@ 1.327 @Override 1.328 public Node leaveForNode(final ForNode forNode) { 1.329 if (forNode.isForIn()) { 1.330 - forNode.setIterator(newInternal(getLexicalContext().getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.OBJECT)); //NASHORN-73 1.331 + forNode.setIterator(newInternal(lc.getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.OBJECT)); //NASHORN-73 1.332 /* 1.333 * Iterators return objects, so we need to widen the scope of the 1.334 * init variable if it, for example, has been assigned double type 1.335 @@ -1407,7 +1401,7 @@ 1.336 final Symbol paramSymbol = functionNode.getBody().getExistingSymbol(param.getName()); 1.337 assert paramSymbol != null; 1.338 assert paramSymbol.isParam(); 1.339 - newParams.add((IdentNode)param.setSymbol(getLexicalContext(), paramSymbol)); 1.340 + newParams.add((IdentNode)param.setSymbol(lc, paramSymbol)); 1.341 1.342 assert paramSymbol != null; 1.343 Type type = functionNode.getHints().getParameterType(pos); 1.344 @@ -1439,10 +1433,10 @@ 1.345 FunctionNode newFunctionNode = functionNode; 1.346 1.347 if (nparams == 0 || (specialize * 2) < nparams) { 1.348 - newFunctionNode = newFunctionNode.clearSnapshot(getLexicalContext()); 1.349 + newFunctionNode = newFunctionNode.clearSnapshot(lc); 1.350 } 1.351 1.352 - return newFunctionNode.setParameters(getLexicalContext(), newParams); 1.353 + return newFunctionNode.setParameters(lc, newParams); 1.354 } 1.355 1.356 /** 1.357 @@ -1506,7 +1500,7 @@ 1.358 } 1.359 1.360 private Symbol exceptionSymbol() { 1.361 - return newInternal(getLexicalContext().getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(ECMAException.class)); 1.362 + return newInternal(lc.getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(ECMAException.class)); 1.363 } 1.364 1.365 /** 1.366 @@ -1520,8 +1514,8 @@ 1.367 * @param assignmentDest the destination node of the assignment, e.g. lhs for binary nodes 1.368 */ 1.369 private Node ensureAssignmentSlots(final Node assignmentDest) { 1.370 - final LexicalContext attrLexicalContext = getLexicalContext(); 1.371 - return assignmentDest.accept(new NodeVisitor() { 1.372 + final LexicalContext attrLexicalContext = lc; 1.373 + return assignmentDest.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 1.374 @Override 1.375 public Node leaveIndexNode(final IndexNode indexNode) { 1.376 assert indexNode.getSymbol().isTemp(); 1.377 @@ -1565,7 +1559,7 @@ 1.378 FunctionNode currentFunctionNode = functionNode; 1.379 do { 1.380 changed.clear(); 1.381 - final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor() { 1.382 + final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 1.383 1.384 private Node widen(final Node node, final Type to) { 1.385 if (node instanceof LiteralNode) { 1.386 @@ -1579,7 +1573,7 @@ 1.387 symbol = temporarySymbols.getTypedTemporarySymbol(to); 1.388 } 1.389 newType(symbol, to); 1.390 - final Node newNode = node.setSymbol(getLexicalContext(), symbol); 1.391 + final Node newNode = node.setSymbol(lc, symbol); 1.392 changed.add(newNode); 1.393 return newNode; 1.394 } 1.395 @@ -1622,7 +1616,7 @@ 1.396 return newBinaryNode; 1.397 } 1.398 }); 1.399 - getLexicalContext().replace(currentFunctionNode, newFunctionNode); 1.400 + lc.replace(currentFunctionNode, newFunctionNode); 1.401 currentFunctionNode = newFunctionNode; 1.402 } while (!changed.isEmpty()); 1.403 return currentFunctionNode; 1.404 @@ -1643,12 +1637,12 @@ 1.405 } 1.406 1.407 private Node ensureSymbol(final Type type, final Node node) { 1.408 - LOG.info("New TEMPORARY added to ", getLexicalContext().getCurrentFunction().getName(), " type=", type); 1.409 - return ensureSymbol(getLexicalContext(), type, node); 1.410 + LOG.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type); 1.411 + return temporarySymbols.ensureSymbol(lc, type, node); 1.412 } 1.413 1.414 private Symbol newInternal(final String name, final Type type) { 1.415 - final Symbol iter = defineSymbol(getLexicalContext().getCurrentBlock(), name, IS_VAR | IS_INTERNAL); 1.416 + final Symbol iter = defineSymbol(lc.getCurrentBlock(), name, IS_VAR | IS_INTERNAL); 1.417 iter.setType(type); // NASHORN-73 1.418 return iter; 1.419 } 1.420 @@ -1705,10 +1699,6 @@ 1.421 localUses.peek().add(name); 1.422 } 1.423 1.424 - private Node ensureSymbol(final LexicalContext lc, final Type type, final Node node) { 1.425 - return temporarySymbols.ensureSymbol(lc, type, node); 1.426 - } 1.427 - 1.428 /** 1.429 * Pessimistically promote all symbols in current function node to Object types 1.430 * This is done when the function contains unevaluated black boxes such as 1.431 @@ -1717,7 +1707,7 @@ 1.432 * @param body body for the function node we are leaving 1.433 */ 1.434 private static void objectifySymbols(final Block body) { 1.435 - body.accept(new NodeVisitor() { 1.436 + body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 1.437 private void toObject(final Block block) { 1.438 for (final Symbol symbol : block.getSymbols()) { 1.439 if (!symbol.isTemp()) { 1.440 @@ -1761,7 +1751,7 @@ 1.441 append("] "). 1.442 append(printNode ? node.toString() : ""). 1.443 append(" in '"). 1.444 - append(getLexicalContext().getCurrentFunction().getName()). 1.445 + append(lc.getCurrentFunction().getName()). 1.446 append("'"); 1.447 LOG.info(sb); 1.448 LOG.indent(); 1.449 @@ -1787,7 +1777,7 @@ 1.450 append("] "). 1.451 append(printNode ? node.toString() : ""). 1.452 append(" in '"). 1.453 - append(getLexicalContext().getCurrentFunction().getName()); 1.454 + append(lc.getCurrentFunction().getName()); 1.455 1.456 if (node.getSymbol() == null) { 1.457 sb.append(" <NO SYMBOL>");
2.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu May 23 09:49:03 2013 -0300 2.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu May 23 15:51:08 2013 +0200 2.3 @@ -52,16 +52,12 @@ 2.4 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT; 2.5 2.6 import java.io.PrintWriter; 2.7 -import java.util.ArrayDeque; 2.8 import java.util.ArrayList; 2.9 import java.util.Arrays; 2.10 -import java.util.Deque; 2.11 import java.util.EnumSet; 2.12 -import java.util.HashMap; 2.13 import java.util.Iterator; 2.14 import java.util.LinkedList; 2.15 import java.util.List; 2.16 -import java.util.Map; 2.17 import java.util.TreeMap; 2.18 2.19 import jdk.nashorn.internal.codegen.ClassEmitter.Flag; 2.20 @@ -83,11 +79,11 @@ 2.21 import jdk.nashorn.internal.ir.ExecuteNode; 2.22 import jdk.nashorn.internal.ir.ForNode; 2.23 import jdk.nashorn.internal.ir.FunctionNode; 2.24 +import jdk.nashorn.internal.ir.LexicalContext; 2.25 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 2.26 import jdk.nashorn.internal.ir.IdentNode; 2.27 import jdk.nashorn.internal.ir.IfNode; 2.28 import jdk.nashorn.internal.ir.IndexNode; 2.29 -import jdk.nashorn.internal.ir.LexicalContext; 2.30 import jdk.nashorn.internal.ir.LexicalContextNode; 2.31 import jdk.nashorn.internal.ir.LiteralNode; 2.32 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 2.33 @@ -150,7 +146,7 @@ 2.34 * The CodeGenerator visits nodes only once, tags them as resolved and emits 2.35 * bytecode for them. 2.36 */ 2.37 -final class CodeGenerator extends NodeOperatorVisitor { 2.38 +final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> { 2.39 2.40 /** Name of the Global object, cannot be referred to as .class, @see CodeGenerator */ 2.41 private static final String GLOBAL_OBJECT = Compiler.OBJECTS_PACKAGE + '/' + "Global"; 2.42 @@ -168,23 +164,12 @@ 2.43 /** How many regexp fields have been emitted */ 2.44 private int regexFieldCount; 2.45 2.46 - /** Map of shared scope call sites */ 2.47 - private final Map<SharedScopeCall, SharedScopeCall> scopeCalls = new HashMap<>(); 2.48 - 2.49 - /** Compile unit stack - every time we start a sub method (e.g. a split) we push one */ 2.50 - private final Deque<CompileUnit> compileUnits = new ArrayDeque<>(); 2.51 - 2.52 - /** Method emitter stack - every time we start a sub method (e.g. a split) we push one */ 2.53 - private final Deque<MethodEmitter> methodEmitters = new ArrayDeque<>(); 2.54 - 2.55 - /** The discard stack - whenever we enter a discard node we keep track of its return value status - 2.56 - * i.e. should we keep it or throw it away */ 2.57 - private final Deque<Node> discard = new ArrayDeque<>(); 2.58 - 2.59 - // A stack tracking the next free local variable slot in the blocks. There's one entry for every block 2.60 - // currently on the lexical context stack. 2.61 - private int[] nextFreeSlots = new int[16]; 2.62 - private int nextFreeSlotsSize = 0; 2.63 + /** Line number for last statement. If we encounter a new line number, line number bytecode information 2.64 + * needs to be generated */ 2.65 + private int lastLineNumber = -1; 2.66 + 2.67 + /** When should we stop caching regexp expressions in fields to limit bytecode size? */ 2.68 + private static final int MAX_REGEX_FIELDS = 2 * 1024; 2.69 2.70 /** Current method emitter */ 2.71 private MethodEmitter method; 2.72 @@ -192,20 +177,16 @@ 2.73 /** Current compile unit */ 2.74 private CompileUnit unit; 2.75 2.76 - private int lastLineNumber = -1; 2.77 - 2.78 - /** When should we stop caching regexp expressions in fields to limit bytecode size? */ 2.79 - private static final int MAX_REGEX_FIELDS = 2 * 1024; 2.80 - 2.81 private static final DebugLogger LOG = new DebugLogger("codegen", "nashorn.codegen.debug"); 2.82 2.83 + 2.84 /** 2.85 * Constructor. 2.86 * 2.87 * @param compiler 2.88 */ 2.89 CodeGenerator(final Compiler compiler) { 2.90 - super(new DynamicScopeTrackingLexicalContext()); 2.91 + super(new CodeGeneratorLexicalContext()); 2.92 this.compiler = compiler; 2.93 this.callSiteFlags = compiler.getEnv()._callsite_flags; 2.94 } 2.95 @@ -217,37 +198,7 @@ 2.96 * @return the correct flags for a call site in the current function 2.97 */ 2.98 int getCallSiteFlags() { 2.99 - return getLexicalContext().getCurrentFunction().isStrict() ? callSiteFlags | CALLSITE_STRICT : callSiteFlags; 2.100 - } 2.101 - 2.102 - private void pushMethodEmitter(final MethodEmitter newMethod) { 2.103 - methodEmitters.push(newMethod); 2.104 - this.method = newMethod; 2.105 - } 2.106 - 2.107 - private void popMethodEmitter(final MethodEmitter oldMethod) { 2.108 - assert methodEmitters.peek() == oldMethod; 2.109 - methodEmitters.pop(); 2.110 - if (!methodEmitters.isEmpty()) { 2.111 - this.method = methodEmitters.peek(); 2.112 - } else { 2.113 - this.method = null; 2.114 - } 2.115 - } 2.116 - 2.117 - private void push(final CompileUnit newUnit) { 2.118 - compileUnits.push(newUnit); 2.119 - this.unit = newUnit; 2.120 - } 2.121 - 2.122 - private void pop(final CompileUnit oldUnit) { 2.123 - assert compileUnits.peek() == oldUnit; 2.124 - compileUnits.pop(); 2.125 - if (!compileUnits.isEmpty()) { 2.126 - this.unit = compileUnits.peek(); 2.127 - } else { 2.128 - this.unit = null; 2.129 - } 2.130 + return lc.getCurrentFunction().isStrict() ? callSiteFlags | CALLSITE_STRICT : callSiteFlags; 2.131 } 2.132 2.133 /** 2.134 @@ -265,7 +216,7 @@ 2.135 } 2.136 2.137 final String name = symbol.getName(); 2.138 - final Source source = getLexicalContext().getCurrentFunction().getSource(); 2.139 + final Source source = lc.getCurrentFunction().getSource(); 2.140 2.141 if (CompilerConstants.__FILE__.name().equals(name)) { 2.142 return method.load(source.getName()); 2.143 @@ -291,88 +242,43 @@ 2.144 } 2.145 2.146 /** 2.147 - * A lexical context that also tracks if we have any dynamic scopes in the context. Such scopes can have new 2.148 - * variables introduced into them at run time - a with block or a function directly containing an eval call. 2.149 - */ 2.150 - private static class DynamicScopeTrackingLexicalContext extends LexicalContext { 2.151 - int dynamicScopeCount = 0; 2.152 - 2.153 - @Override 2.154 - public <T extends LexicalContextNode> T push(T node) { 2.155 - if(isDynamicScopeBoundary(node)) { 2.156 - ++dynamicScopeCount; 2.157 - } 2.158 - return super.push(node); 2.159 - } 2.160 - 2.161 - @Override 2.162 - public <T extends LexicalContextNode> T pop(T node) { 2.163 - final T popped = super.pop(node); 2.164 - if(isDynamicScopeBoundary(popped)) { 2.165 - --dynamicScopeCount; 2.166 - } 2.167 - return popped; 2.168 - } 2.169 - 2.170 - private boolean isDynamicScopeBoundary(LexicalContextNode node) { 2.171 - if(node instanceof Block) { 2.172 - // Block's immediate parent is a with node. Note we aren't testing for a WithNode, as that'd capture 2.173 - // processing of WithNode.expression too, but it should be unaffected. 2.174 - return !isEmpty() && peek() instanceof WithNode; 2.175 - } else if(node instanceof FunctionNode) { 2.176 - // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new 2.177 - // variable into the function's scope), and it isn't strict (as evals in strict functions get an 2.178 - // isolated scope). 2.179 - return isFunctionDynamicScope((FunctionNode)node); 2.180 - } 2.181 - return false; 2.182 - } 2.183 - } 2.184 - 2.185 - boolean inDynamicScope() { 2.186 - return ((DynamicScopeTrackingLexicalContext)getLexicalContext()).dynamicScopeCount > 0; 2.187 - } 2.188 - 2.189 - static boolean isFunctionDynamicScope(FunctionNode fn) { 2.190 - return fn.hasEval() && !fn.isStrict(); 2.191 - } 2.192 - 2.193 - /** 2.194 * Check if this symbol can be accessed directly with a putfield or getfield or dynamic load 2.195 * 2.196 * @param function function to check for fast scope 2.197 * @return true if fast scope 2.198 */ 2.199 private boolean isFastScope(final Symbol symbol) { 2.200 - if(!symbol.isScope()) { 2.201 + if (!symbol.isScope()) { 2.202 return false; 2.203 } 2.204 - final LexicalContext lc = getLexicalContext(); 2.205 - if(!inDynamicScope()) { 2.206 + 2.207 + if (!lc.inDynamicScope()) { 2.208 // If there's no with or eval in context, and the symbol is marked as scoped, it is fast scoped. Such a 2.209 // symbol must either be global, or its defining block must need scope. 2.210 assert symbol.isGlobal() || lc.getDefiningBlock(symbol).needsScope() : symbol.getName(); 2.211 return true; 2.212 } 2.213 - if(symbol.isGlobal()) { 2.214 + 2.215 + if (symbol.isGlobal()) { 2.216 // Shortcut: if there's a with or eval in context, globals can't be fast scoped 2.217 return false; 2.218 } 2.219 + 2.220 // Otherwise, check if there's a dynamic scope between use of the symbol and its definition 2.221 final String name = symbol.getName(); 2.222 boolean previousWasBlock = false; 2.223 for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) { 2.224 final LexicalContextNode node = it.next(); 2.225 - if(node instanceof Block) { 2.226 + if (node instanceof Block) { 2.227 // If this block defines the symbol, then we can fast scope the symbol. 2.228 final Block block = (Block)node; 2.229 - if(block.getExistingSymbol(name) == symbol) { 2.230 + if (block.getExistingSymbol(name) == symbol) { 2.231 assert block.needsScope(); 2.232 return true; 2.233 } 2.234 previousWasBlock = true; 2.235 } else { 2.236 - if((node instanceof WithNode && previousWasBlock) || (node instanceof FunctionNode && isFunctionDynamicScope((FunctionNode)node))) { 2.237 + if ((node instanceof WithNode && previousWasBlock) || (node instanceof FunctionNode && CodeGeneratorLexicalContext.isFunctionDynamicScope((FunctionNode)node))) { 2.238 // If we hit a scope that can have symbols introduced into it at run time before finding the defining 2.239 // block, the symbol can't be fast scoped. A WithNode only counts if we've immediately seen a block 2.240 // before - its block. Otherwise, we are currently processing the WithNode's expression, and that's 2.241 @@ -387,16 +293,14 @@ 2.242 } 2.243 2.244 private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) { 2.245 - method.load(isFastScope(symbol) ? getScopeProtoDepth(getLexicalContext().getCurrentBlock(), symbol) : -1); 2.246 - final SharedScopeCall scopeCall = getScopeGet(valueType, symbol, flags | CALLSITE_FAST_SCOPE); 2.247 - scopeCall.generateInvoke(method); 2.248 - return method; 2.249 + method.load(isFastScope(symbol) ? getScopeProtoDepth(lc.getCurrentBlock(), symbol) : -1); 2.250 + final SharedScopeCall scopeCall = lc.getScopeGet(unit, valueType, symbol, flags | CALLSITE_FAST_SCOPE); 2.251 + return scopeCall.generateInvoke(method); 2.252 } 2.253 2.254 private MethodEmitter loadFastScopeVar(final Type valueType, final Symbol symbol, final int flags, final boolean isMethod) { 2.255 loadFastScopeProto(symbol, false); 2.256 - method.dynamicGet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE, isMethod); 2.257 - return method; 2.258 + return method.dynamicGet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE, isMethod); 2.259 } 2.260 2.261 private MethodEmitter storeFastScopeVar(final Type valueType, final Symbol symbol, final int flags) { 2.262 @@ -408,7 +312,7 @@ 2.263 private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) { 2.264 int depth = 0; 2.265 final String name = symbol.getName(); 2.266 - for(final Iterator<Block> blocks = getLexicalContext().getBlocks(startingBlock); blocks.hasNext();) { 2.267 + for(final Iterator<Block> blocks = lc.getBlocks(startingBlock); blocks.hasNext();) { 2.268 final Block currentBlock = blocks.next(); 2.269 if (currentBlock.getExistingSymbol(name) == symbol) { 2.270 return depth; 2.271 @@ -421,7 +325,7 @@ 2.272 } 2.273 2.274 private void loadFastScopeProto(final Symbol symbol, final boolean swap) { 2.275 - final int depth = getScopeProtoDepth(getLexicalContext().getCurrentBlock(), symbol); 2.276 + final int depth = getScopeProtoDepth(lc.getCurrentBlock(), symbol); 2.277 assert depth != -1; 2.278 if (depth > 0) { 2.279 if (swap) { 2.280 @@ -464,7 +368,7 @@ 2.281 */ 2.282 final CodeGenerator codegen = this; 2.283 2.284 - node.accept(new NodeVisitor() { 2.285 + node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 2.286 @Override 2.287 public boolean enterIdentNode(final IdentNode identNode) { 2.288 loadIdent(identNode); 2.289 @@ -538,7 +442,7 @@ 2.290 final boolean isInternal = symbol.isParam() || symbol.isInternal() || symbol.isThis() || !symbol.canBeUndefined(); 2.291 2.292 if (symbol.hasSlot() && !isInternal) { 2.293 - assert symbol.getSymbolType().isNumber() || symbol.getSymbolType().isObject() : "no potentially undefined narrower local vars than doubles are allowed: " + symbol + " in " + getLexicalContext().getCurrentFunction(); 2.294 + assert symbol.getSymbolType().isNumber() || symbol.getSymbolType().isObject() : "no potentially undefined narrower local vars than doubles are allowed: " + symbol + " in " + lc.getCurrentFunction(); 2.295 if (symbol.getSymbolType().isNumber()) { 2.296 numbers.add(symbol); 2.297 } else if (symbol.getSymbolType().isObject()) { 2.298 @@ -595,7 +499,6 @@ 2.299 if (block.needsScope() && !block.isTerminal()) { 2.300 popBlockScope(block); 2.301 } 2.302 - --nextFreeSlotsSize; 2.303 return block; 2.304 } 2.305 2.306 @@ -624,11 +527,11 @@ 2.307 public boolean enterBreakNode(final BreakNode breakNode) { 2.308 lineNumber(breakNode); 2.309 2.310 - final BreakableNode breakFrom = getLexicalContext().getBreakable(breakNode.getLabel()); 2.311 - for (int i = 0; i < getLexicalContext().getScopeNestingLevelTo(breakFrom); i++) { 2.312 + final BreakableNode breakFrom = lc.getBreakable(breakNode.getLabel()); 2.313 + for (int i = 0; i < lc.getScopeNestingLevelTo(breakFrom); i++) { 2.314 closeWith(); 2.315 } 2.316 - method.splitAwareGoto(getLexicalContext(), breakFrom.getBreakLabel()); 2.317 + method.splitAwareGoto(lc, breakFrom.getBreakLabel()); 2.318 2.319 return false; 2.320 } 2.321 @@ -672,11 +575,12 @@ 2.322 2.323 final List<Node> args = callNode.getArgs(); 2.324 final Node function = callNode.getFunction(); 2.325 - final Block currentBlock = getLexicalContext().getCurrentBlock(); 2.326 - 2.327 - function.accept(new NodeVisitor() { 2.328 - 2.329 - private void sharedScopeCall(final IdentNode identNode, final int flags) { 2.330 + final Block currentBlock = lc.getCurrentBlock(); 2.331 + final CodeGeneratorLexicalContext codegenLexicalContext = lc; 2.332 + 2.333 + function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 2.334 + 2.335 + private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) { 2.336 final Symbol symbol = identNode.getSymbol(); 2.337 int scopeCallFlags = flags; 2.338 method.loadCompilerConstant(SCOPE); 2.339 @@ -688,8 +592,8 @@ 2.340 } 2.341 loadArgs(args); 2.342 final Type[] paramTypes = method.getTypesFromStack(args.size()); 2.343 - final SharedScopeCall scopeCall = getScopeCall(symbol, identNode.getType(), callNode.getType(), paramTypes, scopeCallFlags); 2.344 - scopeCall.generateInvoke(method); 2.345 + final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol, identNode.getType(), callNode.getType(), paramTypes, scopeCallFlags); 2.346 + return scopeCall.generateInvoke(method); 2.347 } 2.348 2.349 private void scopeCall(final IdentNode node, final int flags) { 2.350 @@ -756,7 +660,7 @@ 2.351 evalCall(node, flags); 2.352 } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD 2.353 || (!isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD) 2.354 - || CodeGenerator.this.inDynamicScope()) { 2.355 + || CodeGenerator.this.lc.inDynamicScope()) { 2.356 scopeCall(node, flags); 2.357 } else { 2.358 sharedScopeCall(node, flags); 2.359 @@ -845,11 +749,11 @@ 2.360 public boolean enterContinueNode(final ContinueNode continueNode) { 2.361 lineNumber(continueNode); 2.362 2.363 - final LoopNode continueTo = getLexicalContext().getContinueTo(continueNode.getLabel()); 2.364 - for (int i = 0; i < getLexicalContext().getScopeNestingLevelTo(continueTo); i++) { 2.365 + final LoopNode continueTo = lc.getContinueTo(continueNode.getLabel()); 2.366 + for (int i = 0; i < lc.getScopeNestingLevelTo(continueTo); i++) { 2.367 closeWith(); 2.368 } 2.369 - method.splitAwareGoto(getLexicalContext(), continueTo.getContinueLabel()); 2.370 + method.splitAwareGoto(lc, continueTo.getContinueLabel()); 2.371 2.372 return false; 2.373 } 2.374 @@ -875,90 +779,89 @@ 2.375 public boolean enterForNode(final ForNode forNode) { 2.376 lineNumber(forNode); 2.377 2.378 + if (forNode.isForIn()) { 2.379 + enterForIn(forNode); 2.380 + } else { 2.381 + enterFor(forNode); 2.382 + } 2.383 + 2.384 + return false; 2.385 + } 2.386 + 2.387 + private void enterFor(final ForNode forNode) { 2.388 + final Node init = forNode.getInit(); 2.389 final Node test = forNode.getTest(); 2.390 final Block body = forNode.getBody(); 2.391 final Node modify = forNode.getModify(); 2.392 2.393 - final Label breakLabel = forNode.getBreakLabel(); 2.394 - final Label continueLabel = forNode.getContinueLabel(); 2.395 - final Label loopLabel = new Label("loop"); 2.396 + if (init != null) { 2.397 + init.accept(this); 2.398 + } 2.399 + 2.400 + final Label loopLabel = new Label("loop"); 2.401 + final Label testLabel = new Label("test"); 2.402 + 2.403 + method._goto(testLabel); 2.404 + method.label(loopLabel); 2.405 + body.accept(this); 2.406 + method.label(forNode.getContinueLabel()); 2.407 + 2.408 + if (!body.isTerminal() && modify != null) { 2.409 + load(modify); 2.410 + } 2.411 + 2.412 + method.label(testLabel); 2.413 + if (test != null) { 2.414 + new BranchOptimizer(this, method).execute(test, loopLabel, true); 2.415 + } else { 2.416 + method._goto(loopLabel); 2.417 + } 2.418 + 2.419 + method.label(forNode.getBreakLabel()); 2.420 + } 2.421 + 2.422 + private void enterForIn(final ForNode forNode) { 2.423 + final Block body = forNode.getBody(); 2.424 + final Node modify = forNode.getModify(); 2.425 + 2.426 + final Symbol iter = forNode.getIterator(); 2.427 + final Label loopLabel = new Label("loop"); 2.428 2.429 Node init = forNode.getInit(); 2.430 2.431 - if (forNode.isForIn()) { 2.432 - final Symbol iter = forNode.getIterator(); 2.433 - 2.434 - // We have to evaluate the optional initializer expression 2.435 - // of the iterator variable of the for-in statement. 2.436 - if (init instanceof VarNode) { 2.437 - init.accept(this); 2.438 - init = ((VarNode)init).getName(); 2.439 + // We have to evaluate the optional initializer expression 2.440 + // of the iterator variable of the for-in statement. 2.441 + if (init instanceof VarNode) { 2.442 + init.accept(this); 2.443 + init = ((VarNode)init).getName(); 2.444 + } 2.445 + 2.446 + load(modify); 2.447 + assert modify.getType().isObject(); 2.448 + method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR); 2.449 + method.store(iter); 2.450 + method._goto(forNode.getContinueLabel()); 2.451 + method.label(loopLabel); 2.452 + 2.453 + new Store<Node>(init) { 2.454 + @Override 2.455 + protected void storeNonDiscard() { 2.456 + return; 2.457 } 2.458 - 2.459 - load(modify); 2.460 - assert modify.getType().isObject(); 2.461 - method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR); 2.462 - method.store(iter); 2.463 - method._goto(continueLabel); 2.464 - method.label(loopLabel); 2.465 - 2.466 - new Store<Node>(init) { 2.467 - @Override 2.468 - protected void storeNonDiscard() { 2.469 - return; 2.470 - } 2.471 - @Override 2.472 - protected void evaluate() { 2.473 - method.load(iter); 2.474 - method.invoke(interfaceCallNoLookup(Iterator.class, "next", Object.class)); 2.475 - } 2.476 - }.store(); 2.477 - 2.478 - body.accept(this); 2.479 - 2.480 - method.label(continueLabel); 2.481 - method.load(iter); 2.482 - method.invoke(interfaceCallNoLookup(Iterator.class, "hasNext", boolean.class)); 2.483 - method.ifne(loopLabel); 2.484 - method.label(breakLabel); 2.485 - } else { 2.486 - if (init != null) { 2.487 - init.accept(this); 2.488 + @Override 2.489 + protected void evaluate() { 2.490 + method.load(iter); 2.491 + method.invoke(interfaceCallNoLookup(Iterator.class, "next", Object.class)); 2.492 } 2.493 - 2.494 - final Label testLabel = new Label("test"); 2.495 - 2.496 - method._goto(testLabel); 2.497 - method.label(loopLabel); 2.498 - body.accept(this); 2.499 - method.label(continueLabel); 2.500 - 2.501 - if (!body.isTerminal() && modify != null) { 2.502 - load(modify); 2.503 - } 2.504 - 2.505 - method.label(testLabel); 2.506 - if (test != null) { 2.507 - new BranchOptimizer(this, method).execute(test, loopLabel, true); 2.508 - } else { 2.509 - method._goto(loopLabel); 2.510 - } 2.511 - 2.512 - method.label(breakLabel); 2.513 - } 2.514 - 2.515 - return false; 2.516 - } 2.517 - 2.518 - private static int assignSlots(final Block block, final int firstSlot) { 2.519 - int nextSlot = firstSlot; 2.520 - for (final Symbol symbol : block.getSymbols()) { 2.521 - if (symbol.hasSlot()) { 2.522 - symbol.setSlot(nextSlot); 2.523 - nextSlot += symbol.slotCount(); 2.524 - } 2.525 - } 2.526 - return nextSlot; 2.527 + }.store(); 2.528 + 2.529 + body.accept(this); 2.530 + 2.531 + method.label(forNode.getContinueLabel()); 2.532 + method.load(iter); 2.533 + method.invoke(interfaceCallNoLookup(Iterator.class, "hasNext", boolean.class)); 2.534 + method.ifne(loopLabel); 2.535 + method.label(forNode.getBreakLabel()); 2.536 } 2.537 2.538 /** 2.539 @@ -967,24 +870,11 @@ 2.540 * @param block block with local vars. 2.541 */ 2.542 private void initLocals(final Block block) { 2.543 - final boolean isFunctionBody = getLexicalContext().isFunctionBody(); 2.544 - 2.545 - final int nextFreeSlot; 2.546 - if (isFunctionBody) { 2.547 - // On entry to function, start with slot 0 2.548 - nextFreeSlot = 0; 2.549 - } else { 2.550 - // Otherwise, continue from previous block's first free slot 2.551 - nextFreeSlot = nextFreeSlots[nextFreeSlotsSize - 1]; 2.552 - } 2.553 - if(nextFreeSlotsSize == nextFreeSlots.length) { 2.554 - final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2]; 2.555 - System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize); 2.556 - nextFreeSlots = newNextFreeSlots; 2.557 - } 2.558 - nextFreeSlots[nextFreeSlotsSize++] = assignSlots(block, nextFreeSlot); 2.559 - 2.560 - final FunctionNode function = getLexicalContext().getCurrentFunction(); 2.561 + lc.nextFreeSlot(block); 2.562 + 2.563 + final boolean isFunctionBody = lc.isFunctionBody(); 2.564 + 2.565 + final FunctionNode function = lc.getCurrentFunction(); 2.566 if (isFunctionBody) { 2.567 /* Fix the predefined slots so they have numbers >= 0, like varargs. */ 2.568 if (function.needsParentScope()) { 2.569 @@ -1023,7 +913,7 @@ 2.570 } 2.571 2.572 if (symbol.isVar()) { 2.573 - if(varsInScope || symbol.isScope()) { 2.574 + if (varsInScope || symbol.isScope()) { 2.575 nameList.add(symbol.getName()); 2.576 newSymbols.add(symbol); 2.577 values.add(null); 2.578 @@ -1062,7 +952,7 @@ 2.579 2.580 @Override 2.581 protected void loadScope(MethodEmitter m) { 2.582 - if(function.needsParentScope()) { 2.583 + if (function.needsParentScope()) { 2.584 m.loadCompilerConstant(SCOPE); 2.585 } else { 2.586 m.loadNull(); 2.587 @@ -1096,7 +986,7 @@ 2.588 2.589 private void initArguments(final FunctionNode function) { 2.590 method.loadCompilerConstant(VARARGS); 2.591 - if(function.needsCallee()) { 2.592 + if (function.needsCallee()) { 2.593 method.loadCompilerConstant(CALLEE); 2.594 } else { 2.595 // If function is strict mode, "arguments.callee" is not populated, so we don't necessarily need the 2.596 @@ -1126,10 +1016,10 @@ 2.597 LOG.info("=== BEGIN ", functionNode.getName()); 2.598 2.599 assert functionNode.getCompileUnit() != null : "no compile unit for " + functionNode.getName() + " " + Debug.id(functionNode); 2.600 - push(functionNode.getCompileUnit()); 2.601 - assert !compileUnits.isEmpty(); 2.602 - 2.603 - pushMethodEmitter(unit.getClassEmitter().method(functionNode)); 2.604 + unit = lc.pushCompileUnit(functionNode.getCompileUnit()); 2.605 + assert lc.hasCompileUnits(); 2.606 + 2.607 + method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode)); 2.608 // Mark end for variable tables. 2.609 method.begin(); 2.610 2.611 @@ -1140,11 +1030,11 @@ 2.612 public Node leaveFunctionNode(final FunctionNode functionNode) { 2.613 try { 2.614 method.end(); // wrap up this method 2.615 - pop(functionNode.getCompileUnit()); 2.616 - popMethodEmitter(method); 2.617 + unit = lc.popCompileUnit(functionNode.getCompileUnit()); 2.618 + method = lc.popMethodEmitter(method); 2.619 LOG.info("=== END ", functionNode.getName()); 2.620 2.621 - final FunctionNode newFunctionNode = functionNode.setState(getLexicalContext(), CompilationState.EMITTED); 2.622 + final FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.EMITTED); 2.623 2.624 newFunctionObject(newFunctionNode, functionNode); 2.625 return newFunctionNode; 2.626 @@ -1238,16 +1128,16 @@ 2.627 final MethodEmitter savedMethod = method; 2.628 2.629 for (final ArrayUnit arrayUnit : units) { 2.630 - push(arrayUnit.getCompileUnit()); 2.631 + unit = lc.pushCompileUnit(arrayUnit.getCompileUnit()); 2.632 2.633 final String className = unit.getUnitClassName(); 2.634 - final String name = getLexicalContext().getCurrentFunction().uniqueName(SPLIT_PREFIX.symbolName()); 2.635 + final String name = lc.getCurrentFunction().uniqueName(SPLIT_PREFIX.symbolName()); 2.636 final String signature = methodDescriptor(type, Object.class, ScriptFunction.class, ScriptObject.class, type); 2.637 2.638 final MethodEmitter me = unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature); 2.639 - pushMethodEmitter(me); 2.640 - 2.641 - method.setFunctionNode(getLexicalContext().getCurrentFunction()); 2.642 + method = lc.pushMethodEmitter(me); 2.643 + 2.644 + method.setFunctionNode(lc.getCurrentFunction()); 2.645 method.begin(); 2.646 2.647 fixScopeSlot(); 2.648 @@ -1260,7 +1150,7 @@ 2.649 2.650 method._return(); 2.651 method.end(); 2.652 - popMethodEmitter(me); 2.653 + method = lc.popMethodEmitter(me); 2.654 2.655 assert method == savedMethod; 2.656 method.loadCompilerConstant(THIS); 2.657 @@ -1271,7 +1161,7 @@ 2.658 method.swap(); 2.659 method.invokestatic(className, name, signature); 2.660 2.661 - pop(unit); 2.662 + unit = lc.popCompileUnit(unit); 2.663 } 2.664 2.665 return method; 2.666 @@ -1407,7 +1297,7 @@ 2.667 return loadRegexToken(regexToken); 2.668 } 2.669 // emit field 2.670 - final String regexName = getLexicalContext().getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName()); 2.671 + final String regexName = lc.getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName()); 2.672 final ClassEmitter classEmitter = unit.getClassEmitter(); 2.673 2.674 classEmitter.field(EnumSet.of(PRIVATE, STATIC), regexName, Object.class); 2.675 @@ -1545,7 +1435,7 @@ 2.676 2.677 method.registerReturn(); 2.678 2.679 - final Type returnType = getLexicalContext().getCurrentFunction().getReturnType(); 2.680 + final Type returnType = lc.getCurrentFunction().getReturnType(); 2.681 2.682 final Node expression = returnNode.getExpression(); 2.683 if (expression != null) { 2.684 @@ -1756,7 +1646,7 @@ 2.685 2.686 final CompileUnit splitCompileUnit = splitNode.getCompileUnit(); 2.687 2.688 - final FunctionNode fn = getLexicalContext().getCurrentFunction(); 2.689 + final FunctionNode fn = lc.getCurrentFunction(); 2.690 final String className = splitCompileUnit.getUnitClassName(); 2.691 final String name = splitNode.getName(); 2.692 2.693 @@ -1767,7 +1657,7 @@ 2.694 new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class}; 2.695 2.696 final MethodEmitter caller = method; 2.697 - push(splitCompileUnit); 2.698 + unit = lc.pushCompileUnit(splitCompileUnit); 2.699 2.700 final Call splitCall = staticCallNoLookup( 2.701 className, 2.702 @@ -1781,8 +1671,7 @@ 2.703 rtype, 2.704 ptypes); 2.705 2.706 - pushMethodEmitter(splitEmitter); 2.707 - 2.708 + method = lc.pushMethodEmitter(splitEmitter); 2.709 method.setFunctionNode(fn); 2.710 2.711 if (fn.needsCallee()) { 2.712 @@ -1809,7 +1698,7 @@ 2.713 } 2.714 2.715 private void fixScopeSlot() { 2.716 - if (getLexicalContext().getCurrentFunction().compilerConstant(SCOPE).getSlot() != SCOPE.slot()) { 2.717 + if (lc.getCurrentFunction().compilerConstant(SCOPE).getSlot() != SCOPE.slot()) { 2.718 // TODO hack to move the scope to the expected slot (that's needed because split methods reuse the same slots as the root method) 2.719 method.load(Type.typeFor(ScriptObject.class), SCOPE.slot()); 2.720 method.storeCompilerConstant(SCOPE); 2.721 @@ -1826,15 +1715,15 @@ 2.722 // Wrap up this method. 2.723 2.724 method.loadCompilerConstant(RETURN); 2.725 - method._return(getLexicalContext().getCurrentFunction().getReturnType()); 2.726 + method._return(lc.getCurrentFunction().getReturnType()); 2.727 method.end(); 2.728 2.729 - pop(splitNode.getCompileUnit()); 2.730 - popMethodEmitter(method); 2.731 + unit = lc.popCompileUnit(splitNode.getCompileUnit()); 2.732 + method = lc.popMethodEmitter(method); 2.733 2.734 } catch (final Throwable t) { 2.735 Context.printStackTrace(t); 2.736 - final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + getLexicalContext().getCurrentFunction().getSource().getName()); 2.737 + final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + lc.getCurrentFunction().getSource().getName()); 2.738 e.initCause(t); 2.739 throw e; 2.740 } 2.741 @@ -1862,7 +1751,7 @@ 2.742 //has to be zero 2.743 caller.label(new Label("split_return")); 2.744 method.loadCompilerConstant(RETURN); 2.745 - caller._return(getLexicalContext().getCurrentFunction().getReturnType()); 2.746 + caller._return(lc.getCurrentFunction().getReturnType()); 2.747 caller.label(breakLabel); 2.748 } else { 2.749 assert !targets.isEmpty(); 2.750 @@ -1879,14 +1768,14 @@ 2.751 caller.label(labels[i - low]); 2.752 if (i == 0) { 2.753 caller.loadCompilerConstant(RETURN); 2.754 - caller._return(getLexicalContext().getCurrentFunction().getReturnType()); 2.755 + caller._return(lc.getCurrentFunction().getReturnType()); 2.756 } else { 2.757 // Clear split state. 2.758 caller.loadCompilerConstant(SCOPE); 2.759 caller.checkcast(Scope.class); 2.760 caller.load(-1); 2.761 caller.invoke(Scope.SET_SPLIT_STATE); 2.762 - caller.splitAwareGoto(getLexicalContext(), targets.get(i - 1)); 2.763 + caller.splitAwareGoto(lc, targets.get(i - 1)); 2.764 } 2.765 } 2.766 caller.label(breakLabel); 2.767 @@ -2037,7 +1926,7 @@ 2.768 2.769 method._new(ECMAException.class).dup(); 2.770 2.771 - final Source source = getLexicalContext().getCurrentFunction().getSource(); 2.772 + final Source source = lc.getCurrentFunction().getSource(); 2.773 2.774 final Node expression = throwNode.getExpression(); 2.775 final int position = throwNode.position(); 2.776 @@ -2088,7 +1977,7 @@ 2.777 //TODO this is very ugly - try not to call enter/leave methods directly 2.778 //better to use the implicit lexical context scoping given by the visitor's 2.779 //accept method. 2.780 - getLexicalContext().push(catchBlock); 2.781 + lc.push(catchBlock); 2.782 enterBlock(catchBlock); 2.783 2.784 final CatchNode catchNode = (CatchNode)catchBlocks.get(i).getStatements().get(0); 2.785 @@ -2101,6 +1990,7 @@ 2.786 protected void storeNonDiscard() { 2.787 return; 2.788 } 2.789 + 2.790 @Override 2.791 protected void evaluate() { 2.792 if (catchNode.isSyntheticRethrow()) { 2.793 @@ -2147,7 +2037,7 @@ 2.794 } 2.795 2.796 leaveBlock(catchBlock); 2.797 - getLexicalContext().pop(catchBlock); 2.798 + lc.pop(catchBlock); 2.799 } 2.800 2.801 method.label(skip); 2.802 @@ -2244,7 +2134,7 @@ 2.803 final boolean hasScope = method.hasScope(); 2.804 2.805 final Label tryLabel; 2.806 - if(hasScope) { 2.807 + if (hasScope) { 2.808 tryLabel = new Label("with_try"); 2.809 method.label(tryLabel); 2.810 method.loadCompilerConstant(SCOPE); 2.811 @@ -2255,7 +2145,7 @@ 2.812 load(expression); 2.813 assert expression.getType().isObject() : "with expression needs to be object: " + expression; 2.814 2.815 - if(hasScope) { 2.816 + if (hasScope) { 2.817 // Construct a WithObject if we have a scope 2.818 method.invoke(ScriptRuntime.OPEN_WITH); 2.819 method.storeCompilerConstant(SCOPE); 2.820 @@ -2397,13 +2287,13 @@ 2.821 public boolean enterDISCARD(final UnaryNode unaryNode) { 2.822 final Node rhs = unaryNode.rhs(); 2.823 2.824 - discard.push(rhs); 2.825 + lc.pushDiscard(rhs); 2.826 load(rhs); 2.827 2.828 - if (discard.peek() == rhs) { 2.829 + if (lc.getCurrentDiscard() == rhs) { 2.830 assert !rhs.isAssignment(); 2.831 method.pop(); 2.832 - discard.pop(); 2.833 + lc.popDiscard(); 2.834 } 2.835 2.836 return false; 2.837 @@ -2455,7 +2345,7 @@ 2.838 assert lhs.getType().equals(rhs.getType()) && lhs.getType().equals(type) : lhs.getType() + " != " + rhs.getType() + " != " + type + " " + new ASTWriter(lhs) + " " + new ASTWriter(rhs); 2.839 load(lhs); 2.840 load(rhs); 2.841 - method.add(); 2.842 + method.add(); //if the symbol is optimistic, it always needs to be written, not on the stack? 2.843 method.store(symbol); 2.844 return null; 2.845 } 2.846 @@ -2999,53 +2889,12 @@ 2.847 * Generate all shared scope calls generated during codegen. 2.848 */ 2.849 protected void generateScopeCalls() { 2.850 - for (final SharedScopeCall scopeAccess : scopeCalls.values()) { 2.851 + for (final SharedScopeCall scopeAccess : lc.getScopeCalls()) { 2.852 scopeAccess.generateScopeCall(); 2.853 } 2.854 } 2.855 2.856 /** 2.857 - * Get a shared static method representing a dynamic scope callsite. 2.858 - * 2.859 - * @param symbol the symbol 2.860 - * @param valueType the value type of the symbol 2.861 - * @param returnType the return type 2.862 - * @param paramTypes the parameter types 2.863 - * @param flags the callsite flags 2.864 - * @return an object representing a shared scope call 2.865 - */ 2.866 - private SharedScopeCall getScopeCall(final Symbol symbol, final Type valueType, final Type returnType, 2.867 - final Type[] paramTypes, final int flags) { 2.868 - 2.869 - final SharedScopeCall scopeCall = new SharedScopeCall(symbol, valueType, returnType, paramTypes, flags); 2.870 - if (scopeCalls.containsKey(scopeCall)) { 2.871 - return scopeCalls.get(scopeCall); 2.872 - } 2.873 - scopeCall.setClassAndName(unit, getLexicalContext().getCurrentFunction().uniqueName("scopeCall")); 2.874 - scopeCalls.put(scopeCall, scopeCall); 2.875 - return scopeCall; 2.876 - } 2.877 - 2.878 - /** 2.879 - * Get a shared static method representing a dynamic scope get access. 2.880 - * 2.881 - * @param type the type of the variable 2.882 - * @param symbol the symbol 2.883 - * @param flags the callsite flags 2.884 - * @return an object representing a shared scope call 2.885 - */ 2.886 - private SharedScopeCall getScopeGet(final Type type, final Symbol symbol, final int flags) { 2.887 - 2.888 - final SharedScopeCall scopeCall = new SharedScopeCall(symbol, type, type, null, flags); 2.889 - if (scopeCalls.containsKey(scopeCall)) { 2.890 - return scopeCalls.get(scopeCall); 2.891 - } 2.892 - scopeCall.setClassAndName(unit, getLexicalContext().getCurrentFunction().uniqueName("scopeCall")); 2.893 - scopeCalls.put(scopeCall, scopeCall); 2.894 - return scopeCall; 2.895 - } 2.896 - 2.897 - /** 2.898 * Debug code used to print symbols 2.899 * 2.900 * @param block the block we are in 2.901 @@ -3139,14 +2988,14 @@ 2.902 2.903 private void prologue() { 2.904 final Symbol targetSymbol = target.getSymbol(); 2.905 - final Symbol scopeSymbol = getLexicalContext().getCurrentFunction().compilerConstant(SCOPE); 2.906 + final Symbol scopeSymbol = lc.getCurrentFunction().compilerConstant(SCOPE); 2.907 2.908 /** 2.909 * This loads the parts of the target, e.g base and index. they are kept 2.910 * on the stack throughout the store and used at the end to execute it 2.911 */ 2.912 2.913 - target.accept(new NodeVisitor() { 2.914 + target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 2.915 @Override 2.916 public boolean enterIdentNode(final IdentNode node) { 2.917 if (targetSymbol.isScope()) { 2.918 @@ -3213,22 +3062,21 @@ 2.919 * @return the quick symbol 2.920 */ 2.921 private Symbol quickSymbol(final Type type, final String prefix) { 2.922 - final String name = getLexicalContext().getCurrentFunction().uniqueName(prefix); 2.923 + final String name = lc.getCurrentFunction().uniqueName(prefix); 2.924 final Symbol symbol = new Symbol(name, IS_TEMP | IS_INTERNAL); 2.925 2.926 symbol.setType(type); 2.927 - final int quickSlot = nextFreeSlots[nextFreeSlotsSize - 1]; 2.928 - nextFreeSlots[nextFreeSlotsSize - 1] = quickSlot + symbol.slotCount(); 2.929 - symbol.setSlot(quickSlot); 2.930 + 2.931 + symbol.setSlot(lc.quickSlot(symbol)); 2.932 2.933 return symbol; 2.934 } 2.935 2.936 // store the result that "lives on" after the op, e.g. "i" in i++ postfix. 2.937 protected void storeNonDiscard() { 2.938 - if (discard.peek() == assignNode) { 2.939 + if (lc.getCurrentDiscard() == assignNode) { 2.940 assert assignNode.isAssignment(); 2.941 - discard.pop(); 2.942 + lc.popDiscard(); 2.943 return; 2.944 } 2.945 2.946 @@ -3256,7 +3104,7 @@ 2.947 */ 2.948 method.convert(target.getType()); 2.949 2.950 - target.accept(new NodeVisitor() { 2.951 + target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 2.952 @Override 2.953 protected boolean enterDefault(Node node) { 2.954 throw new AssertionError("Unexpected node " + node + " in store epilogue"); 2.955 @@ -3318,7 +3166,6 @@ 2.956 } 2.957 2.958 private void newFunctionObject(final FunctionNode functionNode, final FunctionNode originalFunctionNode) { 2.959 - final LexicalContext lc = getLexicalContext(); 2.960 assert lc.peek() == functionNode; 2.961 // We don't emit a ScriptFunction on stack for: 2.962 // 1. the outermost compiled function (as there's no code being generated in its outer context that'd need it
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Thu May 23 15:51:08 2013 +0200 3.3 @@ -0,0 +1,235 @@ 3.4 +/* 3.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. Oracle designates this 3.11 + * particular file as subject to the "Classpath" exception as provided 3.12 + * by Oracle in the LICENSE file that accompanied this code. 3.13 + * 3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.17 + * version 2 for more details (a copy is included in the LICENSE file that 3.18 + * accompanied this code). 3.19 + * 3.20 + * You should have received a copy of the GNU General Public License version 3.21 + * 2 along with this work; if not, write to the Free Software Foundation, 3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.23 + * 3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.25 + * or visit www.oracle.com if you need additional information or have any 3.26 + * questions. 3.27 + */ 3.28 + 3.29 +package jdk.nashorn.internal.codegen; 3.30 + 3.31 +import java.util.ArrayDeque; 3.32 +import java.util.Collection; 3.33 +import java.util.Collections; 3.34 +import java.util.Deque; 3.35 +import java.util.HashMap; 3.36 +import java.util.Map; 3.37 + 3.38 +import jdk.nashorn.internal.codegen.types.Type; 3.39 +import jdk.nashorn.internal.ir.Block; 3.40 +import jdk.nashorn.internal.ir.FunctionNode; 3.41 +import jdk.nashorn.internal.ir.LexicalContext; 3.42 +import jdk.nashorn.internal.ir.LexicalContextNode; 3.43 +import jdk.nashorn.internal.ir.Node; 3.44 +import jdk.nashorn.internal.ir.Symbol; 3.45 +import jdk.nashorn.internal.ir.WithNode; 3.46 + 3.47 +/** 3.48 + * A lexical context that also tracks if we have any dynamic scopes in the context. Such scopes can have new 3.49 + * variables introduced into them at run time - a with block or a function directly containing an eval call. 3.50 + * Furthermore, this class keeps track of current discard state, which the current method emitter being used is, 3.51 + * the current compile unit, and local variable indexes 3.52 + */ 3.53 +final class CodeGeneratorLexicalContext extends LexicalContext { 3.54 + private int dynamicScopeCount; 3.55 + 3.56 + /** Map of shared scope call sites */ 3.57 + private final Map<SharedScopeCall, SharedScopeCall> scopeCalls = new HashMap<>(); 3.58 + 3.59 + /** Compile unit stack - every time we start a sub method (e.g. a split) we push one */ 3.60 + private final Deque<CompileUnit> compileUnits = new ArrayDeque<>(); 3.61 + 3.62 + /** Method emitter stack - every time we start a sub method (e.g. a split) we push one */ 3.63 + private final Deque<MethodEmitter> methodEmitters = new ArrayDeque<>(); 3.64 + 3.65 + /** The discard stack - whenever we enter a discard node we keep track of its return value status - 3.66 + * i.e. should we keep it or throw it away */ 3.67 + private final Deque<Node> discard = new ArrayDeque<>(); 3.68 + 3.69 + /** A stack tracking the next free local variable slot in the blocks. There's one entry for every block 3.70 + * currently on the lexical context stack. */ 3.71 + private int[] nextFreeSlots = new int[16]; 3.72 + 3.73 + /** size of next free slot vector */ 3.74 + private int nextFreeSlotsSize; 3.75 + 3.76 + @Override 3.77 + public <T extends LexicalContextNode> T push(final T node) { 3.78 + if (isDynamicScopeBoundary(node)) { 3.79 + ++dynamicScopeCount; 3.80 + } 3.81 + return super.push(node); 3.82 + } 3.83 + 3.84 + @Override 3.85 + public <T extends LexicalContextNode> T pop(final T node) { 3.86 + final T popped = super.pop(node); 3.87 + if (isDynamicScopeBoundary(popped)) { 3.88 + --dynamicScopeCount; 3.89 + } 3.90 + if (node instanceof Block) { 3.91 + --nextFreeSlotsSize; 3.92 + } 3.93 + return popped; 3.94 + } 3.95 + 3.96 + private boolean isDynamicScopeBoundary(final LexicalContextNode node) { 3.97 + if (node instanceof Block) { 3.98 + // Block's immediate parent is a with node. Note we aren't testing for a WithNode, as that'd capture 3.99 + // processing of WithNode.expression too, but it should be unaffected. 3.100 + return !isEmpty() && peek() instanceof WithNode; 3.101 + } else if (node instanceof FunctionNode) { 3.102 + // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new 3.103 + // variable into the function's scope), and it isn't strict (as evals in strict functions get an 3.104 + // isolated scope). 3.105 + return isFunctionDynamicScope((FunctionNode)node); 3.106 + } 3.107 + return false; 3.108 + } 3.109 + 3.110 + boolean inDynamicScope() { 3.111 + return dynamicScopeCount > 0; 3.112 + } 3.113 + 3.114 + static boolean isFunctionDynamicScope(FunctionNode fn) { 3.115 + return fn.hasEval() && !fn.isStrict(); 3.116 + } 3.117 + 3.118 + MethodEmitter pushMethodEmitter(final MethodEmitter newMethod) { 3.119 + methodEmitters.push(newMethod); 3.120 + return newMethod; 3.121 + } 3.122 + 3.123 + MethodEmitter popMethodEmitter(final MethodEmitter oldMethod) { 3.124 + assert methodEmitters.peek() == oldMethod; 3.125 + methodEmitters.pop(); 3.126 + return methodEmitters.isEmpty() ? null : methodEmitters.peek(); 3.127 + } 3.128 + 3.129 + CompileUnit pushCompileUnit(final CompileUnit newUnit) { 3.130 + compileUnits.push(newUnit); 3.131 + return newUnit; 3.132 + } 3.133 + 3.134 + CompileUnit popCompileUnit(final CompileUnit oldUnit) { 3.135 + assert compileUnits.peek() == oldUnit; 3.136 + compileUnits.pop(); 3.137 + return compileUnits.isEmpty() ? null : compileUnits.peek(); 3.138 + } 3.139 + 3.140 + boolean hasCompileUnits() { 3.141 + return !compileUnits.isEmpty(); 3.142 + } 3.143 + 3.144 + Collection<SharedScopeCall> getScopeCalls() { 3.145 + return Collections.unmodifiableCollection(scopeCalls.values()); 3.146 + } 3.147 + 3.148 + /** 3.149 + * Get a shared static method representing a dynamic scope callsite. 3.150 + * 3.151 + * @param unit current compile unit 3.152 + * @param symbol the symbol 3.153 + * @param valueType the value type of the symbol 3.154 + * @param returnType the return type 3.155 + * @param paramTypes the parameter types 3.156 + * @param flags the callsite flags 3.157 + * @return an object representing a shared scope call 3.158 + */ 3.159 + SharedScopeCall getScopeCall(final CompileUnit unit, final Symbol symbol, final Type valueType, final Type returnType, final Type[] paramTypes, final int flags) { 3.160 + final SharedScopeCall scopeCall = new SharedScopeCall(symbol, valueType, returnType, paramTypes, flags); 3.161 + if (scopeCalls.containsKey(scopeCall)) { 3.162 + return scopeCalls.get(scopeCall); 3.163 + } 3.164 + scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall")); 3.165 + scopeCalls.put(scopeCall, scopeCall); 3.166 + return scopeCall; 3.167 + } 3.168 + 3.169 + /** 3.170 + * Get a shared static method representing a dynamic scope get access. 3.171 + * 3.172 + * @param unit current compile unit 3.173 + * @param type the type of the variable 3.174 + * @param symbol the symbol 3.175 + * @param flags the callsite flags 3.176 + * @return an object representing a shared scope call 3.177 + */ 3.178 + SharedScopeCall getScopeGet(final CompileUnit unit, final Type type, final Symbol symbol, final int flags) { 3.179 + final SharedScopeCall scopeCall = new SharedScopeCall(symbol, type, type, null, flags); 3.180 + if (scopeCalls.containsKey(scopeCall)) { 3.181 + return scopeCalls.get(scopeCall); 3.182 + } 3.183 + scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall")); 3.184 + scopeCalls.put(scopeCall, scopeCall); 3.185 + return scopeCall; 3.186 + } 3.187 + 3.188 + 3.189 + void nextFreeSlot(final Block block) { 3.190 + final boolean isFunctionBody = isFunctionBody(); 3.191 + 3.192 + final int nextFreeSlot; 3.193 + if (isFunctionBody) { 3.194 + // On entry to function, start with slot 0 3.195 + nextFreeSlot = 0; 3.196 + } else { 3.197 + // Otherwise, continue from previous block's first free slot 3.198 + nextFreeSlot = nextFreeSlots[nextFreeSlotsSize - 1]; 3.199 + } 3.200 + if (nextFreeSlotsSize == nextFreeSlots.length) { 3.201 + final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2]; 3.202 + System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize); 3.203 + nextFreeSlots = newNextFreeSlots; 3.204 + } 3.205 + nextFreeSlots[nextFreeSlotsSize++] = assignSlots(block, nextFreeSlot); 3.206 + } 3.207 + 3.208 + private static int assignSlots(final Block block, final int firstSlot) { 3.209 + int nextSlot = firstSlot; 3.210 + for (final Symbol symbol : block.getSymbols()) { 3.211 + if (symbol.hasSlot()) { 3.212 + symbol.setSlot(nextSlot); 3.213 + nextSlot += symbol.slotCount(); 3.214 + } 3.215 + } 3.216 + return nextSlot; 3.217 + } 3.218 + 3.219 + void pushDiscard(final Node node) { 3.220 + discard.push(node); 3.221 + } 3.222 + 3.223 + Node popDiscard() { 3.224 + return discard.pop(); 3.225 + } 3.226 + 3.227 + Node getCurrentDiscard() { 3.228 + return discard.peek(); 3.229 + } 3.230 + 3.231 + int quickSlot(final Symbol symbol) { 3.232 + final int quickSlot = nextFreeSlots[nextFreeSlotsSize - 1]; 3.233 + nextFreeSlots[nextFreeSlotsSize - 1] = quickSlot + symbol.slotCount(); 3.234 + return quickSlot; 3.235 + } 3.236 + 3.237 +} 3.238 +
4.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu May 23 09:49:03 2013 -0300 4.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu May 23 15:51:08 2013 +0200 4.3 @@ -24,15 +24,14 @@ 4.4 import jdk.nashorn.internal.ir.Block; 4.5 import jdk.nashorn.internal.ir.CallNode; 4.6 import jdk.nashorn.internal.ir.FunctionNode; 4.7 +import jdk.nashorn.internal.ir.LexicalContext; 4.8 import jdk.nashorn.internal.ir.ReturnNode; 4.9 import jdk.nashorn.internal.ir.Symbol; 4.10 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 4.11 -import jdk.nashorn.internal.ir.LexicalContext; 4.12 import jdk.nashorn.internal.ir.Node; 4.13 import jdk.nashorn.internal.ir.TemporarySymbols; 4.14 import jdk.nashorn.internal.ir.debug.ASTWriter; 4.15 import jdk.nashorn.internal.ir.debug.PrintVisitor; 4.16 -import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; 4.17 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 4.18 import jdk.nashorn.internal.runtime.ECMAErrors; 4.19 import jdk.nashorn.internal.runtime.ScriptEnvironment; 4.20 @@ -74,7 +73,7 @@ 4.21 4.22 FunctionNode newFunctionNode = outermostFunctionNode; 4.23 4.24 - newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor() { 4.25 + newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 4.26 // self references are done with invokestatic and thus cannot 4.27 // have trampolines - never lazy 4.28 @Override 4.29 @@ -107,10 +106,9 @@ 4.30 lazy.remove(node); 4.31 } 4.32 4.33 - newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeOperatorVisitor() { 4.34 + newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 4.35 @Override 4.36 public Node leaveFunctionNode(final FunctionNode functionNode) { 4.37 - final LexicalContext lc = getLexicalContext(); 4.38 if (lazy.contains(functionNode)) { 4.39 Compiler.LOG.fine( 4.40 "Marking ", 4.41 @@ -194,12 +192,11 @@ 4.42 * @param functionNode node where to start iterating 4.43 */ 4.44 private FunctionNode enterAttr(final FunctionNode functionNode, final TemporarySymbols ts) { 4.45 - return (FunctionNode)functionNode.accept(new NodeVisitor() { 4.46 + return (FunctionNode)functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 4.47 @Override 4.48 public Node leaveFunctionNode(final FunctionNode node) { 4.49 - final LexicalContext lc = getLexicalContext(); 4.50 if (node.isLazy()) { 4.51 - FunctionNode newNode = node.setReturnType(getLexicalContext(), Type.OBJECT); 4.52 + FunctionNode newNode = node.setReturnType(lc, Type.OBJECT); 4.53 return ts.ensureSymbol(lc, Type.OBJECT, newNode); 4.54 } 4.55 //node may have a reference here that needs to be nulled if it was referred to by 4.56 @@ -230,7 +227,7 @@ 4.57 FunctionNode newFunctionNode = (FunctionNode)fn.accept(new RangeAnalyzer()); 4.58 final List<ReturnNode> returns = new ArrayList<>(); 4.59 4.60 - newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor() { 4.61 + newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 4.62 private final Deque<ArrayList<ReturnNode>> returnStack = new ArrayDeque<>(); 4.63 4.64 @Override 4.65 @@ -249,7 +246,7 @@ 4.66 } 4.67 returnType = Type.widest(returnType, ret.getExpression().getType()); 4.68 } 4.69 - return functionNode.setReturnType(getLexicalContext(), returnType); 4.70 + return functionNode.setReturnType(lc, returnType); 4.71 } 4.72 4.73 @Override 4.74 @@ -270,8 +267,8 @@ 4.75 } 4.76 final Type rangeType = range.getType(); 4.77 if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range 4.78 - RangeAnalyzer.LOG.info("[", getLexicalContext().getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange()); 4.79 - return node.setSymbol(getLexicalContext(), symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols())); 4.80 + RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange()); 4.81 + return node.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols())); 4.82 } 4.83 } 4.84 return node;
5.1 --- a/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Thu May 23 09:49:03 2013 -0300 5.2 +++ b/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Thu May 23 15:51:08 2013 +0200 5.3 @@ -31,6 +31,7 @@ 5.4 import java.util.ArrayList; 5.5 import java.util.HashSet; 5.6 import java.util.List; 5.7 + 5.8 import jdk.nashorn.internal.codegen.types.Type; 5.9 import jdk.nashorn.internal.ir.AccessNode; 5.10 import jdk.nashorn.internal.ir.Assignment; 5.11 @@ -84,13 +85,14 @@ 5.12 * and frame optimizations 5.13 */ 5.14 5.15 -final class FinalizeTypes extends NodeOperatorVisitor { 5.16 +final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> { 5.17 5.18 private static final DebugLogger LOG = new DebugLogger("finalize"); 5.19 5.20 private final TemporarySymbols temporarySymbols; 5.21 5.22 FinalizeTypes(final TemporarySymbols temporarySymbols) { 5.23 + super(new LexicalContext()); 5.24 this.temporarySymbols = temporarySymbols; 5.25 } 5.26 5.27 @@ -233,7 +235,7 @@ 5.28 5.29 private boolean symbolIsInteger(Node node) { 5.30 final Symbol symbol = node.getSymbol(); 5.31 - assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + getLexicalContext().getCurrentFunction().getSource(); 5.32 + assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + lc.getCurrentFunction().getSource(); 5.33 return true; 5.34 } 5.35 5.36 @@ -382,12 +384,10 @@ 5.37 final Node test = forNode.getTest(); 5.38 final Node modify = forNode.getModify(); 5.39 5.40 - final LexicalContext lc = getLexicalContext(); 5.41 - 5.42 if (forNode.isForIn()) { 5.43 return forNode.setModify(lc, convert(forNode.getModify(), Type.OBJECT)); // NASHORN-400 5.44 } 5.45 - assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + getLexicalContext().getCurrentFunction(); 5.46 + assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + lc.getCurrentFunction(); 5.47 5.48 return forNode. 5.49 setInit(lc, init == null ? null : discard(init)). 5.50 @@ -419,7 +419,7 @@ 5.51 5.52 @Override 5.53 public Node leaveFunctionNode(final FunctionNode functionNode) { 5.54 - return functionNode.setState(getLexicalContext(), CompilationState.FINALIZED); 5.55 + return functionNode.setState(lc, CompilationState.FINALIZED); 5.56 } 5.57 5.58 @Override 5.59 @@ -450,7 +450,7 @@ 5.60 public Node leaveReturnNode(final ReturnNode returnNode) { 5.61 final Node expr = returnNode.getExpression(); 5.62 if (expr != null) { 5.63 - return returnNode.setExpression(convert(expr, getLexicalContext().getCurrentFunction().getReturnType())); 5.64 + return returnNode.setExpression(convert(expr, lc.getCurrentFunction().getReturnType())); 5.65 } 5.66 return returnNode; 5.67 } 5.68 @@ -482,8 +482,8 @@ 5.69 } 5.70 5.71 return switchNode. 5.72 - setExpression(getLexicalContext(), convert(expression, Type.OBJECT)). 5.73 - setCases(getLexicalContext(), newCases); 5.74 + setExpression(lc, convert(expression, Type.OBJECT)). 5.75 + setCases(lc, newCases); 5.76 } 5.77 5.78 @Override 5.79 @@ -519,14 +519,14 @@ 5.80 public Node leaveWhileNode(final WhileNode whileNode) { 5.81 final Node test = whileNode.getTest(); 5.82 if (test != null) { 5.83 - return whileNode.setTest(getLexicalContext(), convert(test, Type.BOOLEAN)); 5.84 + return whileNode.setTest(lc, convert(test, Type.BOOLEAN)); 5.85 } 5.86 return whileNode; 5.87 } 5.88 5.89 @Override 5.90 public Node leaveWithNode(final WithNode withNode) { 5.91 - return withNode.setExpression(getLexicalContext(), convert(withNode.getExpression(), Type.OBJECT)); 5.92 + return withNode.setExpression(lc, convert(withNode.getExpression(), Type.OBJECT)); 5.93 } 5.94 5.95 private static void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) { 5.96 @@ -550,7 +550,6 @@ 5.97 return; // nothing to do 5.98 } 5.99 5.100 - final LexicalContext lc = getLexicalContext(); 5.101 final FunctionNode functionNode = lc.getFunction(block); 5.102 final boolean allVarsInScope = functionNode.allVarsInScope(); 5.103 final boolean isVarArg = functionNode.isVarArg(); 5.104 @@ -652,7 +651,7 @@ 5.105 private static void setCanBePrimitive(final Node node, final Type to) { 5.106 final HashSet<Node> exclude = new HashSet<>(); 5.107 5.108 - node.accept(new NodeVisitor() { 5.109 + node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 5.110 private void setCanBePrimitive(final Symbol symbol) { 5.111 LOG.info("*** can be primitive symbol ", symbol, " ", Debug.id(symbol)); 5.112 symbol.setCanBePrimitive(to); 5.113 @@ -762,7 +761,7 @@ 5.114 } 5.115 } 5.116 LOG.info("Type override for lhs in '", node, "' => ", to); 5.117 - return ((TypeOverride<T>)node).setType(temporarySymbols, getLexicalContext(), to); 5.118 + return ((TypeOverride<T>)node).setType(temporarySymbols, lc, to); 5.119 } 5.120 5.121 /** 5.122 @@ -785,8 +784,8 @@ 5.123 private Node convert(final Node node, final Type to) { 5.124 assert !to.isUnknown() : "unknown type for " + node + " class=" + node.getClass(); 5.125 assert node != null : "node is null"; 5.126 - assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + getLexicalContext().getCurrentFunction(); 5.127 - assert node.tokenType() != TokenType.CONVERT : "assert convert in convert " + node + " in " + getLexicalContext().getCurrentFunction(); 5.128 + assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + lc.getCurrentFunction(); 5.129 + assert node.tokenType() != TokenType.CONVERT : "assert convert in convert " + node + " in " + lc.getCurrentFunction(); 5.130 5.131 final Type from = node.getType(); 5.132 5.133 @@ -817,7 +816,6 @@ 5.134 5.135 assert !node.isTerminal(); 5.136 5.137 - final LexicalContext lc = getLexicalContext(); 5.138 //This is the only place in this file that can create new temporaries 5.139 //FinalizeTypes may not introduce ANY node that is not a conversion. 5.140 return temporarySymbols.ensureSymbol(lc, to, resultNode); 5.141 @@ -854,7 +852,7 @@ 5.142 symbol = symbol.setTypeOverrideShared(to, temporarySymbols); 5.143 LOG.info("Type override for temporary in '", node, "' => ", to); 5.144 } 5.145 - return node.setSymbol(getLexicalContext(), symbol); 5.146 + return node.setSymbol(lc, symbol); 5.147 } 5.148 5.149 /** 5.150 @@ -907,7 +905,7 @@ 5.151 5.152 if (literalNode != null) { 5.153 //inherit literal symbol for attr. 5.154 - literalNode = (LiteralNode<?>)literalNode.setSymbol(getLexicalContext(), parent.getSymbol()); 5.155 + literalNode = (LiteralNode<?>)literalNode.setSymbol(lc, parent.getSymbol()); 5.156 } 5.157 5.158 return literalNode;
6.1 --- a/src/jdk/nashorn/internal/codegen/FoldConstants.java Thu May 23 09:49:03 2013 -0300 6.2 +++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java Thu May 23 15:51:08 2013 +0200 6.3 @@ -33,6 +33,7 @@ 6.4 import jdk.nashorn.internal.ir.FunctionNode; 6.5 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 6.6 import jdk.nashorn.internal.ir.IfNode; 6.7 +import jdk.nashorn.internal.ir.LexicalContext; 6.8 import jdk.nashorn.internal.ir.LiteralNode; 6.9 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 6.10 import jdk.nashorn.internal.ir.Node; 6.11 @@ -46,11 +47,12 @@ 6.12 /** 6.13 * Simple constant folding pass, executed before IR is starting to be lowered. 6.14 */ 6.15 -final class FoldConstants extends NodeVisitor { 6.16 +final class FoldConstants extends NodeVisitor<LexicalContext> { 6.17 6.18 private static final DebugLogger LOG = new DebugLogger("fold"); 6.19 6.20 FoldConstants() { 6.21 + super(new LexicalContext()); 6.22 } 6.23 6.24 @Override 6.25 @@ -80,7 +82,7 @@ 6.26 6.27 @Override 6.28 public Node leaveFunctionNode(final FunctionNode functionNode) { 6.29 - return functionNode.setState(getLexicalContext(), CompilationState.CONSTANT_FOLDED); 6.30 + return functionNode.setState(lc, CompilationState.CONSTANT_FOLDED); 6.31 } 6.32 6.33 @Override
7.1 --- a/src/jdk/nashorn/internal/codegen/Lower.java Thu May 23 09:49:03 2013 -0300 7.2 +++ b/src/jdk/nashorn/internal/codegen/Lower.java Thu May 23 15:51:08 2013 +0200 7.3 @@ -80,7 +80,7 @@ 7.4 * finalized. 7.5 */ 7.6 7.7 -final class Lower extends NodeOperatorVisitor { 7.8 +final class Lower extends NodeOperatorVisitor<BlockLexicalContext> { 7.9 7.10 private static final DebugLogger LOG = new DebugLogger("lower"); 7.11 7.12 @@ -105,7 +105,7 @@ 7.13 terminated = true; 7.14 } 7.15 } else { 7.16 - statement.accept(new NodeVisitor() { 7.17 + statement.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 7.18 @Override 7.19 public boolean enterVarNode(final VarNode varNode) { 7.20 newStatements.add(varNode.setInit(null)); 7.21 @@ -121,7 +121,6 @@ 7.22 7.23 @Override 7.24 public boolean enterBlock(final Block block) { 7.25 - final LexicalContext lc = getLexicalContext(); 7.26 final FunctionNode function = lc.getCurrentFunction(); 7.27 if (lc.isFunctionBody() && function.isProgram() && !function.hasDeclaredFunctions()) { 7.28 new ExecuteNode(block.getLineNumber(), block.getToken(), block.getFinish(), LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)).accept(this); 7.29 @@ -134,12 +133,10 @@ 7.30 //now we have committed the entire statement list to the block, but we need to truncate 7.31 //whatever is after the last terminal. block append won't append past it 7.32 7.33 - final BlockLexicalContext lc = (BlockLexicalContext)getLexicalContext(); 7.34 - 7.35 Statement last = lc.getLastStatement(); 7.36 7.37 if (lc.isFunctionBody()) { 7.38 - final FunctionNode currentFunction = getLexicalContext().getCurrentFunction(); 7.39 + final FunctionNode currentFunction = lc.getCurrentFunction(); 7.40 final boolean isProgram = currentFunction.isProgram(); 7.41 final ReturnNode returnNode = new ReturnNode( 7.42 last == null ? block.getLineNumber() : last.getLineNumber(), //TODO? 7.43 @@ -191,7 +188,7 @@ 7.44 final Node expr = executeNode.getExpression(); 7.45 ExecuteNode node = executeNode; 7.46 7.47 - final FunctionNode currentFunction = getLexicalContext().getCurrentFunction(); 7.48 + final FunctionNode currentFunction = lc.getCurrentFunction(); 7.49 7.50 if (currentFunction.isProgram()) { 7.51 if (!(expr instanceof Block) || expr instanceof FunctionNode) { // it's not a block, but can be a function 7.52 @@ -216,7 +213,7 @@ 7.53 7.54 final Node test = forNode.getTest(); 7.55 if (!forNode.isForIn() && conservativeAlwaysTrue(test)) { 7.56 - newForNode = forNode.setTest(getLexicalContext(), null); 7.57 + newForNode = forNode.setTest(lc, null); 7.58 } 7.59 7.60 return addStatement(checkEscape(newForNode)); 7.61 @@ -230,7 +227,7 @@ 7.62 @Override 7.63 public Node leaveFunctionNode(final FunctionNode functionNode) { 7.64 LOG.info("END FunctionNode: ", functionNode.getName()); 7.65 - return functionNode.setState(getLexicalContext(), CompilationState.LOWERED); 7.66 + return functionNode.setState(lc, CompilationState.LOWERED); 7.67 } 7.68 7.69 @Override 7.70 @@ -262,16 +259,16 @@ 7.71 } 7.72 7.73 private static Node ensureUniqueNamesIn(final LexicalContext lc, final Node node) { 7.74 - return node.accept(new NodeVisitor() { 7.75 + return node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 7.76 @Override 7.77 public Node leaveFunctionNode(final FunctionNode functionNode) { 7.78 final String name = functionNode.getName(); 7.79 - return functionNode.setName(getLexicalContext(), lc.getCurrentFunction().uniqueName(name)); 7.80 + return functionNode.setName(lc, lc.getCurrentFunction().uniqueName(name)); 7.81 } 7.82 7.83 @Override 7.84 public Node leaveDefault(final Node labelledNode) { 7.85 - return labelledNode.ensureUniqueLabels(getLexicalContext()); 7.86 + return labelledNode.ensureUniqueLabels(lc); 7.87 } 7.88 }); 7.89 } 7.90 @@ -292,10 +289,10 @@ 7.91 final long token = tryNode.getToken(); 7.92 final int finish = tryNode.getFinish(); 7.93 7.94 - final IdentNode exception = new IdentNode(token, finish, getLexicalContext().getCurrentFunction().uniqueName("catch_all")); 7.95 + final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName("catch_all")); 7.96 7.97 final Block catchBody = new Block(lineNumber, token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), ThrowNode.IS_SYNTHETIC_RETHROW)). 7.98 - setIsTerminal(getLexicalContext(), true); //ends with throw, so terminal 7.99 + setIsTerminal(lc, true); //ends with throw, so terminal 7.100 7.101 final CatchNode catchAllNode = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, CatchNode.IS_SYNTHETIC_RETHROW); 7.102 final Block catchAllBlock = new Block(lineNumber, token, finish, catchAllNode); 7.103 @@ -306,7 +303,7 @@ 7.104 } 7.105 7.106 private IdentNode compilerConstant(final CompilerConstants cc) { 7.107 - final FunctionNode functionNode = getLexicalContext().getCurrentFunction(); 7.108 + final FunctionNode functionNode = lc.getCurrentFunction(); 7.109 return new IdentNode(functionNode.getToken(), functionNode.getFinish(), cc.symbolName()); 7.110 } 7.111 7.112 @@ -324,9 +321,8 @@ 7.113 private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) { 7.114 assert tryNode.getFinallyBody() == null; 7.115 final int finish = tryNode.getFinish(); 7.116 - final LexicalContext lc = getLexicalContext(); 7.117 7.118 - final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor() { 7.119 + final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 7.120 final List<Node> insideTry = new ArrayList<>(); 7.121 7.122 @Override 7.123 @@ -355,12 +351,12 @@ 7.124 7.125 @Override 7.126 public Node leaveBreakNode(final BreakNode breakNode) { 7.127 - return copy(breakNode, Lower.this.getLexicalContext().getBreakable(breakNode.getLabel())); 7.128 + return copy(breakNode, Lower.this.lc.getBreakable(breakNode.getLabel())); 7.129 } 7.130 7.131 @Override 7.132 public Node leaveContinueNode(final ContinueNode continueNode) { 7.133 - return copy(continueNode, Lower.this.getLexicalContext().getContinueTo(continueNode.getLabel())); 7.134 + return copy(continueNode, Lower.this.lc.getContinueTo(continueNode.getLabel())); 7.135 } 7.136 7.137 @Override 7.138 @@ -383,7 +379,7 @@ 7.139 newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode)); 7.140 } 7.141 7.142 - return new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new Block(returnNode.getLineNumber(), returnNode.getToken(), getLexicalContext().getCurrentBlock().getFinish(), newStatements)); 7.143 + return new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new Block(returnNode.getLineNumber(), returnNode.getToken(), lc.getCurrentBlock().getFinish(), newStatements)); 7.144 } 7.145 7.146 private Node copy(final Statement endpoint, final Node targetNode) { 7.147 @@ -442,7 +438,7 @@ 7.148 final Block catchAll = catchAllBlock(tryNode); 7.149 7.150 final List<ThrowNode> rethrows = new ArrayList<>(); 7.151 - catchAll.accept(new NodeVisitor() { 7.152 + catchAll.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 7.153 @Override 7.154 public boolean enterThrowNode(final ThrowNode throwNode) { 7.155 rethrows.add(throwNode); 7.156 @@ -470,7 +466,7 @@ 7.157 @Override 7.158 public Node leaveVarNode(final VarNode varNode) { 7.159 addStatement(varNode); 7.160 - if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && getLexicalContext().getCurrentFunction().isProgram()) { 7.161 + if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && lc.getCurrentFunction().isProgram()) { 7.162 new ExecuteNode(varNode.getLineNumber(), varNode.getToken(), varNode.getFinish(), new IdentNode(varNode.getName())).accept(this); 7.163 } 7.164 return varNode; 7.165 @@ -484,7 +480,7 @@ 7.166 if (conservativeAlwaysTrue(test)) { 7.167 //turn it into a for node without a test. 7.168 final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), null, null, body, null, ForNode.IS_FOR).accept(this); 7.169 - getLexicalContext().replace(whileNode, forNode); 7.170 + lc.replace(whileNode, forNode); 7.171 return forNode; 7.172 } 7.173 7.174 @@ -519,7 +515,7 @@ 7.175 * @return eval location 7.176 */ 7.177 private String evalLocation(final IdentNode node) { 7.178 - final Source source = getLexicalContext().getCurrentFunction().getSource(); 7.179 + final Source source = lc.getCurrentFunction().getSource(); 7.180 return new StringBuilder(). 7.181 append(source.getName()). 7.182 append('#'). 7.183 @@ -551,10 +547,10 @@ 7.184 7.185 // 'eval' call with at least one argument 7.186 if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) { 7.187 - final FunctionNode currentFunction = getLexicalContext().getCurrentFunction(); 7.188 + final FunctionNode currentFunction = lc.getCurrentFunction(); 7.189 return callNode.setEvalArgs( 7.190 new CallNode.EvalArgs( 7.191 - ensureUniqueNamesIn(getLexicalContext(), args.get(0)).accept(this), 7.192 + ensureUniqueNamesIn(lc, args.get(0)).accept(this), 7.193 compilerConstant(THIS), 7.194 evalLocation(callee), 7.195 currentFunction.isStrict())); 7.196 @@ -580,7 +576,7 @@ 7.197 private static boolean controlFlowEscapes(final LexicalContext lex, final Block loopBody) { 7.198 final List<Node> escapes = new ArrayList<>(); 7.199 7.200 - loopBody.accept(new NodeVisitor() { 7.201 + loopBody.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 7.202 @Override 7.203 public Node leaveBreakNode(final BreakNode node) { 7.204 escapes.add(node); 7.205 @@ -601,7 +597,6 @@ 7.206 } 7.207 7.208 private LoopNode checkEscape(final LoopNode loopNode) { 7.209 - final LexicalContext lc = getLexicalContext(); 7.210 final boolean escapes = controlFlowEscapes(lc, loopNode.getBody()); 7.211 if (escapes) { 7.212 return loopNode. 7.213 @@ -613,7 +608,7 @@ 7.214 7.215 7.216 private Node addStatement(final Statement statement) { 7.217 - ((BlockLexicalContext)getLexicalContext()).appendStatement(statement); 7.218 + lc.appendStatement(statement); 7.219 return statement; 7.220 } 7.221
8.1 --- a/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java Thu May 23 09:49:03 2013 -0300 8.2 +++ b/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java Thu May 23 15:51:08 2013 +0200 8.3 @@ -35,6 +35,7 @@ 8.4 import jdk.nashorn.internal.ir.BinaryNode; 8.5 import jdk.nashorn.internal.ir.ForNode; 8.6 import jdk.nashorn.internal.ir.IdentNode; 8.7 +import jdk.nashorn.internal.ir.LexicalContext; 8.8 import jdk.nashorn.internal.ir.LiteralNode; 8.9 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 8.10 import jdk.nashorn.internal.ir.LoopNode; 8.11 @@ -61,7 +62,7 @@ 8.12 * 8.13 * Proves that the multiplication never exceeds 24 bits and can thus be an int 8.14 */ 8.15 -final class RangeAnalyzer extends NodeOperatorVisitor { 8.16 +final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> { 8.17 static final DebugLogger LOG = new DebugLogger("ranges"); 8.18 8.19 private static final Range.Functionality RANGE = new Range.Functionality(LOG); 8.20 @@ -69,6 +70,7 @@ 8.21 private final Map<LoopNode, Symbol> loopCounters = new HashMap<>(); 8.22 8.23 RangeAnalyzer() { 8.24 + super(new LexicalContext()); 8.25 } 8.26 8.27 @Override 8.28 @@ -96,7 +98,7 @@ 8.29 final Range symRange = RANGE.join(symbol.getRange(), range); 8.30 8.31 //anything assigned in the loop, not being the safe loop counter(s) invalidates its entire range 8.32 - if (getLexicalContext().inLoop() && !isLoopCounter(getLexicalContext().getCurrentLoop(), symbol)) { 8.33 + if (lc.inLoop() && !isLoopCounter(lc.getCurrentLoop(), symbol)) { 8.34 symbol.setRange(Range.createGenericRange()); 8.35 return symbol; 8.36 } 8.37 @@ -399,7 +401,7 @@ 8.38 final HashSet<Node> skip = new HashSet<>(); 8.39 final HashSet<Node> assignmentsInLoop = new HashSet<>(); 8.40 8.41 - loopNode.accept(new NodeVisitor() { 8.42 + loopNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 8.43 private boolean assigns(final Node node, final Symbol s) { 8.44 return node.isAssignment() && ((Assignment<?>)node).getAssignmentDest().getSymbol() == s; 8.45 }
9.1 --- a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java Thu May 23 09:49:03 2013 -0300 9.2 +++ b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java Thu May 23 15:51:08 2013 +0200 9.3 @@ -116,9 +116,10 @@ 9.4 /** 9.5 * Generate the invoke instruction for this shared scope call. 9.6 * @param method the method emitter 9.7 + * @return the method emitter 9.8 */ 9.9 - public void generateInvoke(final MethodEmitter method) { 9.10 - method.invokestatic(compileUnit.getUnitClassName(), methodName, getStaticSignature()); 9.11 + public MethodEmitter generateInvoke(final MethodEmitter method) { 9.12 + return method.invokestatic(compileUnit.getUnitClassName(), methodName, getStaticSignature()); 9.13 } 9.14 9.15 /**
10.1 --- a/src/jdk/nashorn/internal/codegen/Splitter.java Thu May 23 09:49:03 2013 -0300 10.2 +++ b/src/jdk/nashorn/internal/codegen/Splitter.java Thu May 23 15:51:08 2013 +0200 10.3 @@ -49,12 +49,12 @@ 10.4 /** 10.5 * Split the IR into smaller compile units. 10.6 */ 10.7 -final class Splitter extends NodeVisitor { 10.8 +final class Splitter extends NodeVisitor<LexicalContext> { 10.9 /** Current compiler. */ 10.10 private final Compiler compiler; 10.11 10.12 /** IR to be broken down. */ 10.13 - private FunctionNode outermost; 10.14 + private final FunctionNode outermost; 10.15 10.16 /** Compile unit for the main script. */ 10.17 private final CompileUnit outermostCompileUnit; 10.18 @@ -75,6 +75,7 @@ 10.19 * @param outermostCompileUnit compile unit for outermost function, if non-lazy this is the script's compile unit 10.20 */ 10.21 public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) { 10.22 + super(new LexicalContext()); 10.23 this.compiler = compiler; 10.24 this.outermost = functionNode; 10.25 this.outermostCompileUnit = outermostCompileUnit; 10.26 @@ -93,8 +94,6 @@ 10.27 10.28 LOG.finest("Initiating split of '", functionNode.getName(), "'"); 10.29 10.30 - final LexicalContext lc = getLexicalContext(); 10.31 - 10.32 long weight = WeighNodes.weigh(functionNode); 10.33 final boolean top = fn.isProgram(); //compiler.getFunctionNode() == outermost; 10.34 10.35 @@ -127,7 +126,7 @@ 10.36 final Block body = functionNode.getBody(); 10.37 final List<FunctionNode> dc = directChildren(functionNode); 10.38 10.39 - final Block newBody = (Block)body.accept(new NodeVisitor() { 10.40 + final Block newBody = (Block)body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 10.41 @Override 10.42 public boolean enterFunctionNode(final FunctionNode nestedFunction) { 10.43 return dc.contains(nestedFunction); 10.44 @@ -136,7 +135,7 @@ 10.45 @Override 10.46 public Node leaveFunctionNode(final FunctionNode nestedFunction) { 10.47 FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction); 10.48 - getLexicalContext().replace(nestedFunction, split); 10.49 + lc.replace(nestedFunction, split); 10.50 return split; 10.51 } 10.52 }); 10.53 @@ -149,13 +148,13 @@ 10.54 10.55 private static List<FunctionNode> directChildren(final FunctionNode functionNode) { 10.56 final List<FunctionNode> dc = new ArrayList<>(); 10.57 - functionNode.accept(new NodeVisitor() { 10.58 + functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 10.59 @Override 10.60 public boolean enterFunctionNode(final FunctionNode child) { 10.61 if (child == functionNode) { 10.62 return true; 10.63 } 10.64 - if (getLexicalContext().getParentFunction(child) == functionNode) { 10.65 + if (lc.getParentFunction(child) == functionNode) { 10.66 dc.add(child); 10.67 } 10.68 return false; 10.69 @@ -181,7 +180,7 @@ 10.70 * @return new weight for the resulting block. 10.71 */ 10.72 private Block splitBlock(final Block block, final FunctionNode function) { 10.73 - getLexicalContext().setFlag(getLexicalContext().getCurrentFunction(), FunctionNode.IS_SPLIT); 10.74 + lc.setFlag(lc.getCurrentFunction(), FunctionNode.IS_SPLIT); 10.75 10.76 final List<Statement> splits = new ArrayList<>(); 10.77 List<Statement> statements = new ArrayList<>(); 10.78 @@ -210,7 +209,7 @@ 10.79 splits.add(createBlockSplitNode(block, function, statements, statementsWeight)); 10.80 } 10.81 10.82 - return block.setStatements(getLexicalContext(), splits); 10.83 + return block.setStatements(lc, splits); 10.84 } 10.85 10.86 /** 10.87 @@ -258,7 +257,7 @@ 10.88 // been split already, so weigh again before splitting. 10.89 long weight = WeighNodes.weigh(block, weightCache); 10.90 if (weight >= SPLIT_THRESHOLD) { 10.91 - newBlock = splitBlock(block, getLexicalContext().getFunction(block)); 10.92 + newBlock = splitBlock(block, lc.getFunction(block)); 10.93 weight = WeighNodes.weigh(newBlock, weightCache); 10.94 } 10.95 weightCache.put(newBlock, weight); 10.96 @@ -274,9 +273,9 @@ 10.97 return literal; 10.98 } 10.99 10.100 - final FunctionNode functionNode = getLexicalContext().getCurrentFunction(); 10.101 + final FunctionNode functionNode = lc.getCurrentFunction(); 10.102 10.103 - getLexicalContext().setFlag(functionNode, FunctionNode.IS_SPLIT); 10.104 + lc.setFlag(functionNode, FunctionNode.IS_SPLIT); 10.105 10.106 if (literal instanceof ArrayLiteralNode) { 10.107 final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal;
11.1 --- a/src/jdk/nashorn/internal/codegen/WeighNodes.java Thu May 23 09:49:03 2013 -0300 11.2 +++ b/src/jdk/nashorn/internal/codegen/WeighNodes.java Thu May 23 15:51:08 2013 +0200 11.3 @@ -27,6 +27,7 @@ 11.4 11.5 import java.util.List; 11.6 import java.util.Map; 11.7 + 11.8 import jdk.nashorn.internal.codegen.types.Type; 11.9 import jdk.nashorn.internal.ir.AccessNode; 11.10 import jdk.nashorn.internal.ir.BinaryNode; 11.11 @@ -41,6 +42,7 @@ 11.12 import jdk.nashorn.internal.ir.IdentNode; 11.13 import jdk.nashorn.internal.ir.IfNode; 11.14 import jdk.nashorn.internal.ir.IndexNode; 11.15 +import jdk.nashorn.internal.ir.LexicalContext; 11.16 import jdk.nashorn.internal.ir.LiteralNode; 11.17 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 11.18 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; 11.19 @@ -63,7 +65,7 @@ 11.20 * Computes the "byte code" weight of an AST segment. This is used 11.21 * for Splitting too large class files 11.22 */ 11.23 -final class WeighNodes extends NodeOperatorVisitor { 11.24 +final class WeighNodes extends NodeOperatorVisitor<LexicalContext> { 11.25 /* 11.26 * Weight constants. 11.27 */ 11.28 @@ -100,7 +102,7 @@ 11.29 * @param weightCache cache of already calculated block weights 11.30 */ 11.31 private WeighNodes(FunctionNode topFunction, final Map<Node, Long> weightCache) { 11.32 - super(); 11.33 + super(new LexicalContext()); 11.34 this.topFunction = topFunction; 11.35 this.weightCache = weightCache; 11.36 }
12.1 --- a/src/jdk/nashorn/internal/ir/AccessNode.java Thu May 23 09:49:03 2013 -0300 12.2 +++ b/src/jdk/nashorn/internal/ir/AccessNode.java Thu May 23 15:51:08 2013 +0200 12.3 @@ -60,7 +60,7 @@ 12.4 * @param visitor IR navigating visitor. 12.5 */ 12.6 @Override 12.7 - public Node accept(final NodeVisitor visitor) { 12.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 12.9 if (visitor.enterAccessNode(this)) { 12.10 return visitor.leaveAccessNode( 12.11 setBase(base.accept(visitor)). 12.12 @@ -110,7 +110,6 @@ 12.13 return new AccessNode(this, base, property, isFunction(), hasCallSiteType()); 12.14 } 12.15 12.16 - 12.17 private AccessNode setProperty(final IdentNode property) { 12.18 if (this.property == property) { 12.19 return this;
13.1 --- a/src/jdk/nashorn/internal/ir/BinaryNode.java Thu May 23 09:49:03 2013 -0300 13.2 +++ b/src/jdk/nashorn/internal/ir/BinaryNode.java Thu May 23 15:51:08 2013 +0200 13.3 @@ -160,7 +160,7 @@ 13.4 * @param visitor IR navigating visitor. 13.5 */ 13.6 @Override 13.7 - public Node accept(final NodeVisitor visitor) { 13.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 13.9 if (visitor.enterBinaryNode(this)) { 13.10 return visitor.leaveBinaryNode(setLHS(lhs.accept(visitor)).setRHS(rhs.accept(visitor))); 13.11 }
14.1 --- a/src/jdk/nashorn/internal/ir/Block.java Thu May 23 09:49:03 2013 -0300 14.2 +++ b/src/jdk/nashorn/internal/ir/Block.java Thu May 23 15:51:08 2013 +0200 14.3 @@ -131,7 +131,7 @@ 14.4 * @return new or same node 14.5 */ 14.6 @Override 14.7 - public Node accept(final LexicalContext lc, final NodeVisitor visitor) { 14.8 + public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 14.9 if (visitor.enterBlock(this)) { 14.10 return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, Statement.class, statements))); 14.11 }
15.1 --- a/src/jdk/nashorn/internal/ir/BreakNode.java Thu May 23 09:49:03 2013 -0300 15.2 +++ b/src/jdk/nashorn/internal/ir/BreakNode.java Thu May 23 15:51:08 2013 +0200 15.3 @@ -59,7 +59,7 @@ 15.4 * @param visitor IR navigating visitor. 15.5 */ 15.6 @Override 15.7 - public Node accept(final NodeVisitor visitor) { 15.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 15.9 if (visitor.enterBreakNode(this)) { 15.10 return visitor.leaveBreakNode(this); 15.11 }
16.1 --- a/src/jdk/nashorn/internal/ir/CallNode.java Thu May 23 09:49:03 2013 -0300 16.2 +++ b/src/jdk/nashorn/internal/ir/CallNode.java Thu May 23 15:51:08 2013 +0200 16.3 @@ -27,6 +27,7 @@ 16.4 16.5 import java.util.Collections; 16.6 import java.util.List; 16.7 + 16.8 import jdk.nashorn.internal.codegen.types.Type; 16.9 import jdk.nashorn.internal.ir.annotations.Ignore; 16.10 import jdk.nashorn.internal.ir.annotations.Immutable; 16.11 @@ -194,7 +195,7 @@ 16.12 * @return node or replacement 16.13 */ 16.14 @Override 16.15 - public Node accept(final LexicalContext lc, final NodeVisitor visitor) { 16.16 + public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 16.17 if (visitor.enterCallNode(this)) { 16.18 final CallNode newCallNode = (CallNode)visitor.leaveCallNode( 16.19 setFunction(function.accept(visitor)).
17.1 --- a/src/jdk/nashorn/internal/ir/CaseNode.java Thu May 23 09:49:03 2013 -0300 17.2 +++ b/src/jdk/nashorn/internal/ir/CaseNode.java Thu May 23 15:51:08 2013 +0200 17.3 @@ -78,7 +78,7 @@ 17.4 * @param visitor IR navigating visitor. 17.5 */ 17.6 @Override 17.7 - public Node accept(final NodeVisitor visitor) { 17.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 17.9 if (visitor.enterCaseNode(this)) { 17.10 final Node newTest = test == null ? null : test.accept(visitor); 17.11 final Block newBody = body == null ? null : (Block)body.accept(visitor);
18.1 --- a/src/jdk/nashorn/internal/ir/CatchNode.java Thu May 23 09:49:03 2013 -0300 18.2 +++ b/src/jdk/nashorn/internal/ir/CatchNode.java Thu May 23 15:51:08 2013 +0200 18.3 @@ -79,7 +79,7 @@ 18.4 * @param visitor IR navigating visitor. 18.5 */ 18.6 @Override 18.7 - public Node accept(final NodeVisitor visitor) { 18.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 18.9 if (visitor.enterCatchNode(this)) { 18.10 return visitor.leaveCatchNode( 18.11 setException((IdentNode)exception.accept(visitor)).
19.1 --- a/src/jdk/nashorn/internal/ir/ContinueNode.java Thu May 23 09:49:03 2013 -0300 19.2 +++ b/src/jdk/nashorn/internal/ir/ContinueNode.java Thu May 23 15:51:08 2013 +0200 19.3 @@ -55,7 +55,7 @@ 19.4 } 19.5 19.6 @Override 19.7 - public Node accept(final NodeVisitor visitor) { 19.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 19.9 if (visitor.enterContinueNode(this)) { 19.10 return visitor.leaveContinueNode(this); 19.11 }
20.1 --- a/src/jdk/nashorn/internal/ir/EmptyNode.java Thu May 23 09:49:03 2013 -0300 20.2 +++ b/src/jdk/nashorn/internal/ir/EmptyNode.java Thu May 23 15:51:08 2013 +0200 20.3 @@ -56,7 +56,7 @@ 20.4 20.5 20.6 @Override 20.7 - public Node accept(final NodeVisitor visitor) { 20.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 20.9 if (visitor.enterEmptyNode(this)) { 20.10 return visitor.leaveEmptyNode(this); 20.11 }
21.1 --- a/src/jdk/nashorn/internal/ir/ExecuteNode.java Thu May 23 09:49:03 2013 -0300 21.2 +++ b/src/jdk/nashorn/internal/ir/ExecuteNode.java Thu May 23 15:51:08 2013 +0200 21.3 @@ -62,7 +62,7 @@ 21.4 } 21.5 21.6 @Override 21.7 - public Node accept(final NodeVisitor visitor) { 21.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 21.9 if (visitor.enterExecuteNode(this)) { 21.10 return visitor.leaveExecuteNode(setExpression(expression.accept(visitor))); 21.11 }
22.1 --- a/src/jdk/nashorn/internal/ir/ForNode.java Thu May 23 09:49:03 2013 -0300 22.2 +++ b/src/jdk/nashorn/internal/ir/ForNode.java Thu May 23 15:51:08 2013 +0200 22.3 @@ -86,7 +86,7 @@ 22.4 } 22.5 22.6 @Override 22.7 - protected Node accept(final LexicalContext lc, final NodeVisitor visitor) { 22.8 + protected Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 22.9 if (visitor.enterForNode(this)) { 22.10 return visitor.leaveForNode( 22.11 setInit(lc, init == null ? null : init.accept(visitor)).
23.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Thu May 23 09:49:03 2013 -0300 23.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Thu May 23 15:51:08 2013 +0200 23.3 @@ -281,7 +281,7 @@ 23.4 } 23.5 23.6 @Override 23.7 - public Node accept(final LexicalContext lc, final NodeVisitor visitor) { 23.8 + public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 23.9 if (visitor.enterFunctionNode(this)) { 23.10 return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor))); 23.11 }
24.1 --- a/src/jdk/nashorn/internal/ir/IdentNode.java Thu May 23 09:49:03 2013 -0300 24.2 +++ b/src/jdk/nashorn/internal/ir/IdentNode.java Thu May 23 15:51:08 2013 +0200 24.3 @@ -29,7 +29,6 @@ 24.4 import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__; 24.5 import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__; 24.6 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS; 24.7 - 24.8 import jdk.nashorn.internal.codegen.ObjectClassGenerator; 24.9 import jdk.nashorn.internal.codegen.types.Type; 24.10 import jdk.nashorn.internal.ir.annotations.Immutable; 24.11 @@ -119,7 +118,7 @@ 24.12 * @param visitor IR navigating visitor. 24.13 */ 24.14 @Override 24.15 - public Node accept(final NodeVisitor visitor) { 24.16 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 24.17 if (visitor.enterIdentNode(this)) { 24.18 return visitor.leaveIdentNode(this); 24.19 }
25.1 --- a/src/jdk/nashorn/internal/ir/IfNode.java Thu May 23 09:49:03 2013 -0300 25.2 +++ b/src/jdk/nashorn/internal/ir/IfNode.java Thu May 23 15:51:08 2013 +0200 25.3 @@ -72,7 +72,7 @@ 25.4 } 25.5 25.6 @Override 25.7 - public Node accept(final NodeVisitor visitor) { 25.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 25.9 if (visitor.enterIfNode(this)) { 25.10 return visitor.leaveIfNode( 25.11 setTest(test.accept(visitor)).
26.1 --- a/src/jdk/nashorn/internal/ir/IndexNode.java Thu May 23 09:49:03 2013 -0300 26.2 +++ b/src/jdk/nashorn/internal/ir/IndexNode.java Thu May 23 15:51:08 2013 +0200 26.3 @@ -56,19 +56,12 @@ 26.4 } 26.5 26.6 @Override 26.7 - public Node accept(final NodeVisitor visitor) { 26.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 26.9 if (visitor.enterIndexNode(this)) { 26.10 - final Node newBase = base.accept(visitor); 26.11 - final Node newIndex = index.accept(visitor); 26.12 - final IndexNode newNode; 26.13 - if (newBase != base || newIndex != index) { 26.14 - newNode = new IndexNode(this, newBase, newIndex, isFunction(), hasCallSiteType()); 26.15 - } else { 26.16 - newNode = this; 26.17 - } 26.18 - return visitor.leaveIndexNode(newNode); 26.19 + return visitor.leaveIndexNode( 26.20 + setBase(base.accept(visitor)). 26.21 + setIndex(index.accept(visitor))); 26.22 } 26.23 - 26.24 return this; 26.25 } 26.26 26.27 @@ -106,6 +99,13 @@ 26.28 return index; 26.29 } 26.30 26.31 + private IndexNode setBase(final Node base) { 26.32 + if (this.base == base) { 26.33 + return this; 26.34 + } 26.35 + return new IndexNode(this, base, index, isFunction(), hasCallSiteType()); 26.36 + } 26.37 + 26.38 /** 26.39 * Set the index expression for this node 26.40 * @param index new index expression
27.1 --- a/src/jdk/nashorn/internal/ir/LabelNode.java Thu May 23 09:49:03 2013 -0300 27.2 +++ b/src/jdk/nashorn/internal/ir/LabelNode.java Thu May 23 15:51:08 2013 +0200 27.3 @@ -67,11 +67,11 @@ 27.4 } 27.5 27.6 @Override 27.7 - public Node accept(final LexicalContext lc, final NodeVisitor visitor) { 27.8 + public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 27.9 if (visitor.enterLabelNode(this)) { 27.10 return visitor.leaveLabelNode( 27.11 - setLabel(visitor.getLexicalContext(), (IdentNode)label.accept(visitor)). 27.12 - setBody(visitor.getLexicalContext(), (Block)body.accept(visitor))); 27.13 + setLabel(lc, (IdentNode)label.accept(visitor)). 27.14 + setBody(lc, (Block)body.accept(visitor))); 27.15 } 27.16 27.17 return this;
28.1 --- a/src/jdk/nashorn/internal/ir/LexicalContextNode.java Thu May 23 09:49:03 2013 -0300 28.2 +++ b/src/jdk/nashorn/internal/ir/LexicalContextNode.java Thu May 23 15:51:08 2013 +0200 28.3 @@ -60,10 +60,10 @@ 28.4 * 28.5 * @return new node or same node depending on state change 28.6 */ 28.7 - protected abstract Node accept(final LexicalContext lc, final NodeVisitor visitor); 28.8 + protected abstract Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor); 28.9 28.10 @Override 28.11 - public Node accept(final NodeVisitor visitor) { 28.12 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 28.13 final LexicalContext lc = visitor.getLexicalContext(); 28.14 lc.push(this); 28.15 final LexicalContextNode newNode = (LexicalContextNode)accept(lc, visitor);
29.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java Thu May 23 09:49:03 2013 -0300 29.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java Thu May 23 15:51:08 2013 +0200 29.3 @@ -28,6 +28,7 @@ 29.4 import java.util.Arrays; 29.5 import java.util.Collections; 29.6 import java.util.List; 29.7 + 29.8 import jdk.nashorn.internal.codegen.CompileUnit; 29.9 import jdk.nashorn.internal.codegen.types.Type; 29.10 import jdk.nashorn.internal.ir.annotations.Immutable; 29.11 @@ -208,7 +209,7 @@ 29.12 * @param visitor IR navigating visitor. 29.13 */ 29.14 @Override 29.15 - public Node accept(final NodeVisitor visitor) { 29.16 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 29.17 if (visitor.enterLiteralNode(this)) { 29.18 return visitor.leaveLiteralNode(this); 29.19 } 29.20 @@ -514,7 +515,7 @@ 29.21 } 29.22 29.23 @Override 29.24 - public Node accept(final NodeVisitor visitor) { 29.25 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 29.26 if (visitor.enterLiteralNode(this)) { 29.27 if (value != null) { 29.28 final Node newValue = value.accept(visitor); 29.29 @@ -840,7 +841,7 @@ 29.30 } 29.31 29.32 @Override 29.33 - public Node accept(final NodeVisitor visitor) { 29.34 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 29.35 if (visitor.enterLiteralNode(this)) { 29.36 final List<Node> oldValue = Arrays.asList(value); 29.37 final List<Node> newValue = Node.accept(visitor, Node.class, oldValue);
30.1 --- a/src/jdk/nashorn/internal/ir/Node.java Thu May 23 09:49:03 2013 -0300 30.2 +++ b/src/jdk/nashorn/internal/ir/Node.java Thu May 23 15:51:08 2013 +0200 30.3 @@ -27,6 +27,7 @@ 30.4 30.5 import java.util.ArrayList; 30.6 import java.util.List; 30.7 + 30.8 import jdk.nashorn.internal.codegen.types.Type; 30.9 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 30.10 import jdk.nashorn.internal.parser.Token; 30.11 @@ -175,7 +176,7 @@ 30.12 * @param visitor Node visitor. 30.13 * @return node the node or its replacement after visitation, null if no further visitations are required 30.14 */ 30.15 - public abstract Node accept(NodeVisitor visitor); 30.16 + public abstract Node accept(NodeVisitor<? extends LexicalContext> visitor); 30.17 30.18 @Override 30.19 public String toString() { 30.20 @@ -337,7 +338,7 @@ 30.21 } 30.22 30.23 //on change, we have to replace the entire list, that's we can't simple do ListIterator.set 30.24 - static <T extends Node> List<T> accept(final NodeVisitor visitor, final Class<T> clazz, final List<T> list) { 30.25 + static <T extends Node> List<T> accept(final NodeVisitor<? extends LexicalContext> visitor, final Class<T> clazz, final List<T> list) { 30.26 boolean changed = false; 30.27 final List<T> newList = new ArrayList<>(); 30.28
31.1 --- a/src/jdk/nashorn/internal/ir/ObjectNode.java Thu May 23 09:49:03 2013 -0300 31.2 +++ b/src/jdk/nashorn/internal/ir/ObjectNode.java Thu May 23 15:51:08 2013 +0200 31.3 @@ -58,7 +58,7 @@ 31.4 } 31.5 31.6 @Override 31.7 - public Node accept(final NodeVisitor visitor) { 31.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 31.9 if (visitor.enterObjectNode(this)) { 31.10 return visitor.leaveObjectNode(setElements(Node.accept(visitor, Node.class, elements))); 31.11 }
32.1 --- a/src/jdk/nashorn/internal/ir/PropertyNode.java Thu May 23 09:49:03 2013 -0300 32.2 +++ b/src/jdk/nashorn/internal/ir/PropertyNode.java Thu May 23 15:51:08 2013 +0200 32.3 @@ -81,7 +81,7 @@ 32.4 } 32.5 32.6 @Override 32.7 - public Node accept(final NodeVisitor visitor) { 32.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 32.9 if (visitor.enterPropertyNode(this)) { 32.10 return visitor.leavePropertyNode( 32.11 setKey((PropertyKey)((Node)key).accept(visitor)).
33.1 --- a/src/jdk/nashorn/internal/ir/ReturnNode.java Thu May 23 09:49:03 2013 -0300 33.2 +++ b/src/jdk/nashorn/internal/ir/ReturnNode.java Thu May 23 15:51:08 2013 +0200 33.3 @@ -86,7 +86,7 @@ 33.4 } 33.5 33.6 @Override 33.7 - public Node accept(final NodeVisitor visitor) { 33.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 33.9 if (visitor.enterReturnNode(this)) { 33.10 if (expression != null) { 33.11 return visitor.leaveReturnNode(setExpression(expression.accept(visitor)));
34.1 --- a/src/jdk/nashorn/internal/ir/RuntimeNode.java Thu May 23 09:49:03 2013 -0300 34.2 +++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java Thu May 23 15:51:08 2013 +0200 34.3 @@ -29,6 +29,7 @@ 34.4 import java.util.Arrays; 34.5 import java.util.Collections; 34.6 import java.util.List; 34.7 + 34.8 import jdk.nashorn.internal.codegen.types.Type; 34.9 import jdk.nashorn.internal.ir.annotations.Immutable; 34.10 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 34.11 @@ -407,7 +408,7 @@ 34.12 } 34.13 34.14 @Override 34.15 - public Node accept(final NodeVisitor visitor) { 34.16 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 34.17 if (visitor.enterRuntimeNode(this)) { 34.18 final List<Node> newArgs = new ArrayList<>(); 34.19 for (final Node arg : args) {
35.1 --- a/src/jdk/nashorn/internal/ir/SplitNode.java Thu May 23 09:49:03 2013 -0300 35.2 +++ b/src/jdk/nashorn/internal/ir/SplitNode.java Thu May 23 15:51:08 2013 +0200 35.3 @@ -81,7 +81,7 @@ 35.4 } 35.5 35.6 @Override 35.7 - public Node accept(final LexicalContext lc, final NodeVisitor visitor) { 35.8 + public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 35.9 if (visitor.enterSplitNode(this)) { 35.10 return visitor.leaveSplitNode(setBody(lc, body.accept(visitor))); 35.11 }
36.1 --- a/src/jdk/nashorn/internal/ir/SwitchNode.java Thu May 23 09:49:03 2013 -0300 36.2 +++ b/src/jdk/nashorn/internal/ir/SwitchNode.java Thu May 23 15:51:08 2013 +0200 36.3 @@ -100,11 +100,11 @@ 36.4 } 36.5 36.6 @Override 36.7 - public Node accept(final LexicalContext lc, final NodeVisitor visitor) { 36.8 + public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 36.9 if (visitor.enterSwitchNode(this)) { 36.10 return visitor.leaveSwitchNode( 36.11 - setExpression(visitor.getLexicalContext(), expression.accept(visitor)). 36.12 - setCases(visitor.getLexicalContext(), Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex)); 36.13 + setExpression(lc, expression.accept(visitor)). 36.14 + setCases(lc, Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex)); 36.15 } 36.16 36.17 return this;
37.1 --- a/src/jdk/nashorn/internal/ir/TernaryNode.java Thu May 23 09:49:03 2013 -0300 37.2 +++ b/src/jdk/nashorn/internal/ir/TernaryNode.java Thu May 23 15:51:08 2013 +0200 37.3 @@ -63,7 +63,7 @@ 37.4 } 37.5 37.6 @Override 37.7 - public Node accept(final NodeVisitor visitor) { 37.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 37.9 if (visitor.enterTernaryNode(this)) { 37.10 final Node newLhs = lhs().accept(visitor); 37.11 final Node newRhs = rhs().accept(visitor);
38.1 --- a/src/jdk/nashorn/internal/ir/ThrowNode.java Thu May 23 09:49:03 2013 -0300 38.2 +++ b/src/jdk/nashorn/internal/ir/ThrowNode.java Thu May 23 15:51:08 2013 +0200 38.3 @@ -72,7 +72,7 @@ 38.4 * @param visitor IR navigating visitor. 38.5 */ 38.6 @Override 38.7 - public Node accept(final NodeVisitor visitor) { 38.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 38.9 if (visitor.enterThrowNode(this)) { 38.10 return visitor.leaveThrowNode(setExpression(expression.accept(visitor))); 38.11 }
39.1 --- a/src/jdk/nashorn/internal/ir/TryNode.java Thu May 23 09:49:03 2013 -0300 39.2 +++ b/src/jdk/nashorn/internal/ir/TryNode.java Thu May 23 15:51:08 2013 +0200 39.3 @@ -106,7 +106,7 @@ 39.4 * @param visitor IR navigating visitor. 39.5 */ 39.6 @Override 39.7 - public Node accept(final NodeVisitor visitor) { 39.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 39.9 if (visitor.enterTryNode(this)) { 39.10 // Need to do finallybody first for termination analysis. TODO still necessary? 39.11 final Block newFinallyBody = finallyBody == null ? null : (Block)finallyBody.accept(visitor);
40.1 --- a/src/jdk/nashorn/internal/ir/UnaryNode.java Thu May 23 09:49:03 2013 -0300 40.2 +++ b/src/jdk/nashorn/internal/ir/UnaryNode.java Thu May 23 15:51:08 2013 +0200 40.3 @@ -29,7 +29,6 @@ 40.4 import static jdk.nashorn.internal.parser.TokenType.CONVERT; 40.5 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX; 40.6 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX; 40.7 - 40.8 import jdk.nashorn.internal.codegen.types.Type; 40.9 import jdk.nashorn.internal.ir.annotations.Immutable; 40.10 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 40.11 @@ -121,7 +120,7 @@ 40.12 * @param visitor IR navigating visitor. 40.13 */ 40.14 @Override 40.15 - public Node accept(final NodeVisitor visitor) { 40.16 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 40.17 if (visitor.enterUnaryNode(this)) { 40.18 return visitor.leaveUnaryNode(setRHS(rhs.accept(visitor))); 40.19 }
41.1 --- a/src/jdk/nashorn/internal/ir/VarNode.java Thu May 23 09:49:03 2013 -0300 41.2 +++ b/src/jdk/nashorn/internal/ir/VarNode.java Thu May 23 15:51:08 2013 +0200 41.3 @@ -121,7 +121,7 @@ 41.4 * @param visitor IR navigating visitor. 41.5 */ 41.6 @Override 41.7 - public Node accept(final NodeVisitor visitor) { 41.8 + public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 41.9 if (visitor.enterVarNode(this)) { 41.10 final IdentNode newName = (IdentNode)name.accept(visitor); 41.11 final Node newInit = init == null ? null : init.accept(visitor);
42.1 --- a/src/jdk/nashorn/internal/ir/WhileNode.java Thu May 23 09:49:03 2013 -0300 42.2 +++ b/src/jdk/nashorn/internal/ir/WhileNode.java Thu May 23 15:51:08 2013 +0200 42.3 @@ -75,7 +75,7 @@ 42.4 } 42.5 42.6 @Override 42.7 - protected Node accept(final LexicalContext lc, final NodeVisitor visitor) { 42.8 + protected Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 42.9 if (visitor.enterWhileNode(this)) { 42.10 if (isDoWhile()) { 42.11 return visitor.leaveWhileNode(
43.1 --- a/src/jdk/nashorn/internal/ir/WithNode.java Thu May 23 09:49:03 2013 -0300 43.2 +++ b/src/jdk/nashorn/internal/ir/WithNode.java Thu May 23 15:51:08 2013 +0200 43.3 @@ -64,7 +64,7 @@ 43.4 * @param visitor IR navigating visitor. 43.5 */ 43.6 @Override 43.7 - public Node accept(final LexicalContext lc, final NodeVisitor visitor) { 43.8 + public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 43.9 if (visitor.enterWithNode(this)) { 43.10 return visitor.leaveWithNode( 43.11 setExpression(lc, expression.accept(visitor)).
44.1 --- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Thu May 23 09:49:03 2013 -0300 44.2 +++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java Thu May 23 15:51:08 2013 +0200 44.3 @@ -45,6 +45,7 @@ 44.4 import jdk.nashorn.internal.ir.IfNode; 44.5 import jdk.nashorn.internal.ir.IndexNode; 44.6 import jdk.nashorn.internal.ir.LabelNode; 44.7 +import jdk.nashorn.internal.ir.LexicalContext; 44.8 import jdk.nashorn.internal.ir.LiteralNode; 44.9 import jdk.nashorn.internal.ir.Node; 44.10 import jdk.nashorn.internal.ir.ObjectNode; 44.11 @@ -74,7 +75,8 @@ 44.12 /** 44.13 * This IR writer produces a JSON string that represents AST as a JSON string. 44.14 */ 44.15 -public final class JSONWriter extends NodeVisitor { 44.16 +public final class JSONWriter extends NodeVisitor<LexicalContext> { 44.17 + 44.18 /** 44.19 * Returns AST as JSON compatible string. 44.20 * 44.21 @@ -867,7 +869,8 @@ 44.22 // Internals below 44.23 44.24 private JSONWriter(final boolean includeLocation) { 44.25 - this.buf = new StringBuilder(); 44.26 + super(new LexicalContext()); 44.27 + this.buf = new StringBuilder(); 44.28 this.includeLocation = includeLocation; 44.29 } 44.30 44.31 @@ -963,7 +966,7 @@ 44.32 objectStart("loc"); 44.33 44.34 // source name 44.35 - final Source src = getLexicalContext().getCurrentFunction().getSource(); 44.36 + final Source src = lc.getCurrentFunction().getSource(); 44.37 property("source", src.getName()); 44.38 comma(); 44.39
45.1 --- a/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java Thu May 23 09:49:03 2013 -0300 45.2 +++ b/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java Thu May 23 15:51:08 2013 +0200 45.3 @@ -36,6 +36,7 @@ 45.4 import jdk.nashorn.internal.ir.FunctionNode; 45.5 import jdk.nashorn.internal.ir.IfNode; 45.6 import jdk.nashorn.internal.ir.LabelNode; 45.7 +import jdk.nashorn.internal.ir.LexicalContext; 45.8 import jdk.nashorn.internal.ir.Node; 45.9 import jdk.nashorn.internal.ir.SplitNode; 45.10 import jdk.nashorn.internal.ir.Statement; 45.11 @@ -53,7 +54,7 @@ 45.12 * 45.13 * see the flags --print-parse and --print-lower-parse 45.14 */ 45.15 -public final class PrintVisitor extends NodeVisitor { 45.16 +public final class PrintVisitor extends NodeVisitor<LexicalContext> { 45.17 /** Tab width */ 45.18 private static final int TABWIDTH = 4; 45.19 45.20 @@ -84,6 +85,7 @@ 45.21 * @param printLineNumbers should line number nodes be included in the output? 45.22 */ 45.23 public PrintVisitor(final boolean printLineNumbers) { 45.24 + super(new LexicalContext()); 45.25 this.EOLN = System.lineSeparator(); 45.26 this.sb = new StringBuilder(); 45.27 this.printLineNumbers = printLineNumbers;
46.1 --- a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Thu May 23 09:49:03 2013 -0300 46.2 +++ b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java Thu May 23 15:51:08 2013 +0200 46.3 @@ -32,21 +32,15 @@ 46.4 46.5 /** 46.6 * Like NodeVisitor but navigating further into operators. 46.7 + * @param <T> Lexical context class for this NodeOperatorVisitor 46.8 */ 46.9 -public class NodeOperatorVisitor extends NodeVisitor { 46.10 - /** 46.11 - * Constructor 46.12 - */ 46.13 - public NodeOperatorVisitor() { 46.14 - super(); 46.15 - } 46.16 - 46.17 +public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> { 46.18 /** 46.19 * Constructor 46.20 * 46.21 * @param lc a custom lexical context 46.22 */ 46.23 - public NodeOperatorVisitor(final LexicalContext lc) { 46.24 + public NodeOperatorVisitor(final T lc) { 46.25 super(lc); 46.26 } 46.27
47.1 --- a/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Thu May 23 09:49:03 2013 -0300 47.2 +++ b/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Thu May 23 15:51:08 2013 +0200 47.3 @@ -60,23 +60,18 @@ 47.4 47.5 /** 47.6 * Visitor used to navigate the IR. 47.7 + * @param <T> lexical context class used by this visitor 47.8 */ 47.9 -public abstract class NodeVisitor { 47.10 - private final LexicalContext lc; 47.11 - 47.12 - /** 47.13 - * Constructor 47.14 - */ 47.15 - public NodeVisitor() { 47.16 - this(new LexicalContext()); 47.17 - } 47.18 +public abstract class NodeVisitor<T extends LexicalContext> { 47.19 + /** lexical context in use */ 47.20 + protected final T lc; 47.21 47.22 /** 47.23 * Constructor 47.24 * 47.25 * @param lc a custom lexical context 47.26 */ 47.27 - public NodeVisitor(final LexicalContext lc) { 47.28 + public NodeVisitor(final T lc) { 47.29 this.lc = lc; 47.30 } 47.31 47.32 @@ -84,7 +79,7 @@ 47.33 * Get the lexical context of this node visitor 47.34 * @return lexical context 47.35 */ 47.36 - public LexicalContext getLexicalContext() { 47.37 + public T getLexicalContext() { 47.38 return lc; 47.39 } 47.40
48.1 --- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java Thu May 23 09:49:03 2013 -0300 48.2 +++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java Thu May 23 15:51:08 2013 +0200 48.3 @@ -28,7 +28,6 @@ 48.4 import jdk.nashorn.internal.objects.annotations.Attribute; 48.5 import jdk.nashorn.internal.objects.annotations.Getter; 48.6 import jdk.nashorn.internal.objects.annotations.ScriptClass; 48.7 -import jdk.nashorn.internal.objects.annotations.Where; 48.8 import jdk.nashorn.internal.runtime.JSType; 48.9 import jdk.nashorn.internal.runtime.ScriptObject; 48.10 import jdk.nashorn.internal.runtime.ScriptRuntime;
49.1 --- a/src/jdk/nashorn/internal/runtime/DebugLogger.java Thu May 23 09:49:03 2013 -0300 49.2 +++ b/src/jdk/nashorn/internal/runtime/DebugLogger.java Thu May 23 15:51:08 2013 +0200 49.3 @@ -35,7 +35,6 @@ 49.4 */ 49.5 49.6 public final class DebugLogger { 49.7 - @SuppressWarnings("NonConstantLogger") 49.8 private final Logger logger; 49.9 private final boolean isEnabled; 49.10
50.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Thu May 23 09:49:03 2013 -0300 50.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Thu May 23 15:51:08 2013 +0200 50.3 @@ -43,6 +43,7 @@ 50.4 import java.security.PrivilegedAction; 50.5 import java.security.ProtectionDomain; 50.6 import java.security.SecureClassLoader; 50.7 + 50.8 import jdk.internal.dynalink.beans.StaticClass; 50.9 import jdk.internal.org.objectweb.asm.ClassWriter; 50.10 import jdk.internal.org.objectweb.asm.Opcodes; 50.11 @@ -58,6 +59,7 @@ 50.12 * "class loader", it does not, in fact, extend {@code ClassLoader}, but rather uses them internally. Instances of this 50.13 * class are normally created by {@link JavaAdapterBytecodeGenerator}. 50.14 */ 50.15 +@SuppressWarnings("javadoc") 50.16 class JavaAdapterClassLoader extends JavaAdapterGeneratorBase { 50.17 private static final Type PRIVILEGED_ACTION_TYPE = Type.getType(PrivilegedAction.class); 50.18
51.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu May 23 09:49:03 2013 -0300 51.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu May 23 15:51:08 2013 +0200 51.3 @@ -39,6 +39,7 @@ 51.4 import java.util.HashMap; 51.5 import java.util.List; 51.6 import java.util.Map; 51.7 + 51.8 import jdk.internal.dynalink.beans.StaticClass; 51.9 import jdk.internal.dynalink.support.LinkRequestImpl; 51.10 import jdk.nashorn.internal.objects.NativeJava; 51.11 @@ -66,6 +67,7 @@ 51.12 * </p> 51.13 */ 51.14 51.15 +@SuppressWarnings("javadoc") 51.16 public final class JavaAdapterFactory { 51.17 /** 51.18 * A mapping from an original Class object to AdapterInfo representing the adapter for the class it represents.
52.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterGeneratorBase.java Thu May 23 09:49:03 2013 -0300 52.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterGeneratorBase.java Thu May 23 15:51:08 2013 +0200 52.3 @@ -33,6 +33,7 @@ 52.4 * Base class for both {@link JavaAdapterBytecodeGenerator} and {@link JavaAdapterClassLoader}, containing those 52.5 * bytecode types, type names and method descriptor that are used by both. 52.6 */ 52.7 +@SuppressWarnings("javadoc") 52.8 abstract class JavaAdapterGeneratorBase { 52.9 static final Type CONTEXT_TYPE = Type.getType(Context.class); 52.10 static final Type OBJECT_TYPE = Type.getType(Object.class);