8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts

Thu, 23 May 2013 15:51:08 +0200

author
lagergren
date
Thu, 23 May 2013 15:51:08 +0200
changeset 290
6fc7b51e83d6
parent 289
8af550dee961
child 291
fdfb4edd78d6

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

src/jdk/nashorn/internal/codegen/Attr.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CodeGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CompilationPhase.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/FinalizeTypes.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/FoldConstants.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/Lower.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/RangeAnalyzer.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/SharedScopeCall.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/Splitter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/WeighNodes.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/AccessNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/BinaryNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/Block.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/BreakNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/CallNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/CaseNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/CatchNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/ContinueNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/EmptyNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/ExecuteNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/ForNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/FunctionNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/IdentNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/IfNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/IndexNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/LabelNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/LexicalContextNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/LiteralNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/Node.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/ObjectNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/PropertyNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/ReturnNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/RuntimeNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/SplitNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/SwitchNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/TernaryNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/ThrowNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/TryNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/UnaryNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/VarNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/WhileNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/WithNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/debug/JSONWriter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/debug/PrintVisitor.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/ArrayBufferView.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/DebugLogger.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JavaAdapterGeneratorBase.java file | annotate | diff | comparison | revisions
     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);

mercurial