8013925: Remove symbol fields from nodes that don't need them
authorattila
Thu, 11 Jul 2013 18:33:33 +0200
changeset 18867 bc91e3fcc5ba
parent 18866 a36334547d4f
child 18868 f5359cad148c
8013925: Remove symbol fields from nodes that don't need them Reviewed-by: jlaskey, lagergren
nashorn/src/jdk/nashorn/internal/codegen/Attr.java
nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java
nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java
nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java
nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java
nashorn/src/jdk/nashorn/internal/codegen/Lower.java
nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java
nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
nashorn/src/jdk/nashorn/internal/codegen/Splitter.java
nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java
nashorn/src/jdk/nashorn/internal/ir/AccessNode.java
nashorn/src/jdk/nashorn/internal/ir/Assignment.java
nashorn/src/jdk/nashorn/internal/ir/BaseNode.java
nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java
nashorn/src/jdk/nashorn/internal/ir/Block.java
nashorn/src/jdk/nashorn/internal/ir/BlockStatement.java
nashorn/src/jdk/nashorn/internal/ir/BreakableNode.java
nashorn/src/jdk/nashorn/internal/ir/BreakableStatement.java
nashorn/src/jdk/nashorn/internal/ir/CallNode.java
nashorn/src/jdk/nashorn/internal/ir/CaseNode.java
nashorn/src/jdk/nashorn/internal/ir/CatchNode.java
nashorn/src/jdk/nashorn/internal/ir/ExecuteNode.java
nashorn/src/jdk/nashorn/internal/ir/Expression.java
nashorn/src/jdk/nashorn/internal/ir/ExpressionStatement.java
nashorn/src/jdk/nashorn/internal/ir/ForNode.java
nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
nashorn/src/jdk/nashorn/internal/ir/IdentNode.java
nashorn/src/jdk/nashorn/internal/ir/IfNode.java
nashorn/src/jdk/nashorn/internal/ir/IndexNode.java
nashorn/src/jdk/nashorn/internal/ir/LabelNode.java
nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java
nashorn/src/jdk/nashorn/internal/ir/LexicalContextExpression.java
nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java
nashorn/src/jdk/nashorn/internal/ir/LexicalContextStatement.java
nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java
nashorn/src/jdk/nashorn/internal/ir/LoopNode.java
nashorn/src/jdk/nashorn/internal/ir/Node.java
nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java
nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java
nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java
nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java
nashorn/src/jdk/nashorn/internal/ir/SplitNode.java
nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java
nashorn/src/jdk/nashorn/internal/ir/TemporarySymbols.java
nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java
nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java
nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java
nashorn/src/jdk/nashorn/internal/ir/VarNode.java
nashorn/src/jdk/nashorn/internal/ir/WhileNode.java
nashorn/src/jdk/nashorn/internal/ir/WithNode.java
nashorn/src/jdk/nashorn/internal/ir/debug/ASTWriter.java
nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
nashorn/src/jdk/nashorn/internal/parser/JSONParser.java
nashorn/src/jdk/nashorn/internal/parser/Parser.java
nashorn/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
nashorn/test/script/trusted/JDK-8006529.js
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Thu Jul 11 18:33:33 2013 +0200
@@ -61,6 +61,7 @@
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
@@ -72,7 +73,6 @@
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ObjectNode;
-import jdk.nashorn.internal.ir.PropertyNode;
 import jdk.nashorn.internal.ir.ReturnNode;
 import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.RuntimeNode.Request;
@@ -512,7 +512,6 @@
             assert nameSymbol != null;
 
             selfInit = selfInit.setName((IdentNode)name.setSymbol(lc, nameSymbol));
-            selfInit = (VarNode)selfInit.setSymbol(lc, nameSymbol);
 
             newStatements.add(selfInit);
             newStatements.addAll(body.getStatements());
@@ -740,14 +739,8 @@
     }
 
     @Override
-    public Node leavePropertyNode(final PropertyNode propertyNode) {
-        // assign a pseudo symbol to property name, see NASHORN-710
-        return propertyNode.setSymbol(lc, new Symbol(propertyNode.getKeyName(), 0, Type.OBJECT));
-    }
-
-    @Override
     public Node leaveReturnNode(final ReturnNode returnNode) {
-        final Node expr = returnNode.getExpression();
+        final Expression expr = returnNode.getExpression();
         final Type returnType;
 
         if (expr != null) {
@@ -784,7 +777,7 @@
                     final LiteralNode<?> lit = (LiteralNode<?>)test;
                     if (lit.isNumeric() && !(lit.getValue() instanceof Integer)) {
                         if (JSType.isRepresentableAsInt(lit.getNumber())) {
-                            newCaseNode = caseNode.setTest(LiteralNode.newInstance(lit, lit.getInt32()).accept(this));
+                            newCaseNode = caseNode.setTest((Expression)LiteralNode.newInstance(lit, lit.getInt32()).accept(this));
                         }
                     }
                 } else {
@@ -847,19 +840,18 @@
 
     @Override
     public Node leaveVarNode(final VarNode varNode) {
-        VarNode newVarNode = varNode;
+        final Expression init  = varNode.getInit();
+        final IdentNode  ident = varNode.getName();
+        final String     name  = ident.getName();
 
-        final Node      init  = newVarNode.getInit();
-        final IdentNode ident = newVarNode.getName();
-        final String    name  = ident.getName();
-
-        final Symbol  symbol = findSymbol(lc.getCurrentBlock(), ident.getName());
+        final Symbol  symbol = findSymbol(lc.getCurrentBlock(), name);
+        assert ident.getSymbol() == symbol;
 
         if (init == null) {
             // var x; with no init will be treated like a use of x by
             // leaveIdentNode unless we remove the name from the localdef list.
             removeLocalDef(name);
-            return end(newVarNode.setSymbol(lc, symbol));
+            return end(varNode);
         }
 
         addLocalDef(name);
@@ -868,8 +860,7 @@
 
         final IdentNode newIdent = (IdentNode)ident.setSymbol(lc, symbol);
 
-        newVarNode = newVarNode.setName(newIdent);
-        newVarNode = (VarNode)newVarNode.setSymbol(lc, symbol);
+        final VarNode newVarNode = varNode.setName(newIdent);
 
         final boolean isScript = lc.getDefiningFunction(symbol).isProgram(); //see NASHORN-56
         if ((init.getType().isNumeric() || init.getType().isBoolean()) && !isScript) {
@@ -879,7 +870,7 @@
             newType(symbol, Type.OBJECT);
         }
 
-        assert newVarNode.hasType() : newVarNode + " has no type";
+        assert newVarNode.getName().hasType() : newVarNode + " has no type";
 
         return end(newVarNode);
     }
@@ -907,11 +898,11 @@
     public Node leaveDELETE(final UnaryNode unaryNode) {
         final FunctionNode   currentFunctionNode = lc.getCurrentFunction();
         final boolean        strictMode          = currentFunctionNode.isStrict();
-        final Node           rhs                 = unaryNode.rhs();
-        final Node           strictFlagNode      = LiteralNode.newInstance(unaryNode, strictMode).accept(this);
+        final Expression     rhs                 = unaryNode.rhs();
+        final Expression     strictFlagNode      = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this);
 
         Request request = Request.DELETE;
-        final List<Node> args = new ArrayList<>();
+        final List<Expression> args = new ArrayList<>();
 
         if (rhs instanceof IdentNode) {
             // If this is a declared variable or a function parameter, delete always fails (except for globals).
@@ -922,7 +913,7 @@
             if (failDelete && rhs.getSymbol().isThis()) {
                 return LiteralNode.newInstance(unaryNode, true).accept(this);
             }
-            final Node literalNode = LiteralNode.newInstance(unaryNode, name).accept(this);
+            final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this);
 
             if (!failDelete) {
                 args.add(compilerConstant(SCOPE));
@@ -934,16 +925,17 @@
                 request = Request.FAIL_DELETE;
             }
         } else if (rhs instanceof AccessNode) {
-            final Node      base     = ((AccessNode)rhs).getBase();
-            final IdentNode property = ((AccessNode)rhs).getProperty();
+            final Expression base     = ((AccessNode)rhs).getBase();
+            final IdentNode  property = ((AccessNode)rhs).getProperty();
 
             args.add(base);
-            args.add(LiteralNode.newInstance(unaryNode, property.getName()).accept(this));
+            args.add((Expression)LiteralNode.newInstance(unaryNode, property.getName()).accept(this));
             args.add(strictFlagNode);
 
         } else if (rhs instanceof IndexNode) {
-            final Node base  = ((IndexNode)rhs).getBase();
-            final Node index = ((IndexNode)rhs).getIndex();
+            final IndexNode indexNode = (IndexNode)rhs;
+            final Expression base  = indexNode.getBase();
+            final Expression index = indexNode.getIndex();
 
             args.add(base);
             args.add(index);
@@ -998,15 +990,15 @@
 
     @Override
     public Node leaveTYPEOF(final UnaryNode unaryNode) {
-        final Node rhs = unaryNode.rhs();
+        final Expression rhs = unaryNode.rhs();
 
-        List<Node> args = new ArrayList<>();
+        List<Expression> args = new ArrayList<>();
         if (rhs instanceof IdentNode && !rhs.getSymbol().isParam() && !rhs.getSymbol().isVar()) {
             args.add(compilerConstant(SCOPE));
-            args.add(LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null
+            args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null
         } else {
             args.add(rhs);
-            args.add(LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
+            args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
         }
 
         RuntimeNode runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args);
@@ -1040,8 +1032,8 @@
      */
     @Override
     public Node leaveADD(final BinaryNode binaryNode) {
-        final Node lhs = binaryNode.lhs();
-        final Node rhs = binaryNode.rhs();
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
 
         ensureTypeNotUnknown(lhs);
         ensureTypeNotUnknown(rhs);
@@ -1096,8 +1088,8 @@
     private Node leaveAssignmentNode(final BinaryNode binaryNode) {
         BinaryNode newBinaryNode = binaryNode;
 
-        final Node lhs = binaryNode.lhs();
-        final Node rhs = binaryNode.rhs();
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
         final Type type;
 
         if (rhs.getType().isNumeric()) {
@@ -1133,8 +1125,8 @@
 
     @Override
     public Node leaveASSIGN_ADD(final BinaryNode binaryNode) {
-        final Node lhs = binaryNode.lhs();
-        final Node rhs = binaryNode.rhs();
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
 
         final Type widest = Type.widest(lhs.getType(), rhs.getType());
         //Type.NUMBER if we can't prove that the add doesn't overflow. todo
@@ -1413,13 +1405,13 @@
 
     @Override
     public Node leaveTernaryNode(final TernaryNode ternaryNode) {
-        final Node lhs  = ternaryNode.rhs();
-        final Node rhs  = ternaryNode.third();
+        final Expression trueExpr  = ternaryNode.getTrueExpression();
+        final Expression falseExpr = ternaryNode.getFalseExpression();
 
-        ensureTypeNotUnknown(lhs);
-        ensureTypeNotUnknown(rhs);
+        ensureTypeNotUnknown(trueExpr);
+        ensureTypeNotUnknown(falseExpr);
 
-        final Type type = Type.widest(lhs.getType(), rhs.getType());
+        final Type type = Type.widest(trueExpr.getType(), falseExpr.getType());
         return end(ensureSymbol(type, ternaryNode));
     }
 
@@ -1537,7 +1529,7 @@
         }
     }
 
-    private static void ensureTypeNotUnknown(final Node node) {
+    private static void ensureTypeNotUnknown(final Expression node) {
 
         final Symbol symbol = node.getSymbol();
 
@@ -1594,13 +1586,13 @@
      *
      * @param assignmentDest the destination node of the assignment, e.g. lhs for binary nodes
      */
-    private Node ensureAssignmentSlots(final Node assignmentDest) {
+    private Expression ensureAssignmentSlots(final Expression assignmentDest) {
         final LexicalContext attrLexicalContext = lc;
-        return assignmentDest.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        return (Expression)assignmentDest.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public Node leaveIndexNode(final IndexNode indexNode) {
                 assert indexNode.getSymbol().isTemp();
-                final Node index = indexNode.getIndex();
+                final Expression index = indexNode.getIndex();
                 //only temps can be set as needing slots. the others will self resolve
                 //it is illegal to take a scope var and force it to be a slot, that breaks
                 Symbol indexSymbol = index.getSymbol();
@@ -1642,7 +1634,7 @@
             changed.clear();
             final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
 
-                private Node widen(final Node node, final Type to) {
+                private Expression widen(final Expression node, final Type to) {
                     if (node instanceof LiteralNode) {
                         return node;
                     }
@@ -1654,7 +1646,7 @@
                             symbol = temporarySymbols.getTypedTemporarySymbol(to);
                         }
                         newType(symbol, to);
-                        final Node newNode = node.setSymbol(lc, symbol);
+                        final Expression newNode = node.setSymbol(lc, symbol);
                         changed.add(newNode);
                         return newNode;
                     }
@@ -1709,7 +1701,7 @@
 
     private Node leaveSelfModifyingAssignmentNode(final BinaryNode binaryNode, final Type destType) {
         //e.g. for -=, Number, no wider, destType (binaryNode.getWidestOperationType())  is the coerce type
-        final Node lhs = binaryNode.lhs();
+        final Expression lhs = binaryNode.lhs();
 
         newType(lhs.getSymbol(), destType); //may not narrow if dest is already wider than destType
 //        ensureSymbol(destType, binaryNode); //for OP= nodes, the node can carry a narrower types than its lhs rhs. This is perfectly fine
@@ -1717,9 +1709,9 @@
         return end(ensureSymbol(destType, ensureAssignmentSlots(binaryNode)));
     }
 
-    private Node ensureSymbol(final Type type, final Node node) {
+    private Expression ensureSymbol(final Type type, final Expression expr) {
         LOG.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type);
-        return temporarySymbols.ensureSymbol(lc, type, node);
+        return temporarySymbols.ensureSymbol(lc, type, expr);
     }
 
     private Symbol newInternal(final String name, final Type type) {
@@ -1841,11 +1833,11 @@
         return true;
     }
 
-    private Node end(final Node node) {
+    private <T extends Node> T end(final T node) {
         return end(node, true);
     }
 
-    private Node end(final Node node, final boolean printNode) {
+    private <T extends Node> T end(final T node, final boolean printNode) {
         if(node instanceof Statement) {
             // If we're done with a statement, all temporaries can be reused.
             temporarySymbols.reuse();
@@ -1860,10 +1852,13 @@
                 append(" in '").
                 append(lc.getCurrentFunction().getName());
 
-            if (node.getSymbol() == null) {
-                sb.append(" <NO SYMBOL>");
-            } else {
-                sb.append(" <symbol=").append(node.getSymbol()).append('>');
+            if(node instanceof Expression) {
+                final Symbol symbol = ((Expression)node).getSymbol();
+                if (symbol == null) {
+                    sb.append(" <NO SYMBOL>");
+                } else {
+                    sb.append(" <symbol=").append(symbol).append('>');
+                }
             }
 
             LOG.unindent();
--- a/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java	Thu Jul 11 18:33:33 2013 +0200
@@ -34,7 +34,7 @@
 
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.BinaryNode;
-import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.UnaryNode;
 
@@ -52,16 +52,16 @@
         this.method  = method;
     }
 
-    void execute(final Node node, final Label label, final boolean state) {
+    void execute(final Expression node, final Label label, final boolean state) {
         branchOptimizer(node, label, state);
     }
 
-    private void load(final Node node) {
+    private void load(final Expression node) {
         codegen.load(node);
     }
 
     private void branchOptimizer(final UnaryNode unaryNode, final Label label, final boolean state) {
-        final Node rhs = unaryNode.rhs();
+        final Expression rhs = unaryNode.rhs();
 
         switch (unaryNode.tokenType()) {
         case NOT:
@@ -88,8 +88,8 @@
     }
 
     private void branchOptimizer(final BinaryNode binaryNode, final Label label, final boolean state) {
-        final Node lhs = binaryNode.lhs();
-        final Node rhs = binaryNode.rhs();
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
 
         switch (binaryNode.tokenType()) {
         case AND:
@@ -173,7 +173,7 @@
         }
     }
 
-    private void branchOptimizer(final Node node, final Label label, final boolean state) {
+    private void branchOptimizer(final Expression node, final Label label, final boolean state) {
         if (!(node instanceof TernaryNode)) {
 
             if (node instanceof BinaryNode) {
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Jul 11 18:33:33 2013 +0200
@@ -69,6 +69,7 @@
 import jdk.nashorn.internal.ir.BaseNode;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.BlockStatement;
 import jdk.nashorn.internal.ir.BreakNode;
 import jdk.nashorn.internal.ir.BreakableNode;
 import jdk.nashorn.internal.ir.CallNode;
@@ -76,7 +77,8 @@
 import jdk.nashorn.internal.ir.CatchNode;
 import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.EmptyNode;
-import jdk.nashorn.internal.ir.ExecuteNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
@@ -350,11 +352,11 @@
      *
      * @return the method emitter used
      */
-    MethodEmitter load(final Node node) {
+    MethodEmitter load(final Expression node) {
         return load(node, false);
     }
 
-    private MethodEmitter load(final Node node, final boolean baseAlreadyOnStack) {
+    private MethodEmitter load(final Expression node, final boolean baseAlreadyOnStack) {
         final Symbol symbol = node.getSymbol();
 
         // If we lack symbols, we just generate what we see.
@@ -539,11 +541,11 @@
         return false;
     }
 
-    private int loadArgs(final List<Node> args) {
+    private int loadArgs(final List<Expression> args) {
         return loadArgs(args, null, false, args.size());
     }
 
-    private int loadArgs(final List<Node> args, final String signature, final boolean isVarArg, final int argCount) {
+    private int loadArgs(final List<Expression> args, final String signature, final boolean isVarArg, final int argCount) {
         // arg have already been converted to objects here.
         if (isVarArg || argCount > LinkerCallSite.ARGLIMIT) {
             loadArgsArray(args);
@@ -553,7 +555,7 @@
         // pad with undefined if size is too short. argCount is the real number of args
         int n = 0;
         final Type[] params = signature == null ? null : Type.getMethodArguments(signature);
-        for (final Node arg : args) {
+        for (final Expression arg : args) {
             assert arg != null;
             load(arg);
             if (n >= argCount) {
@@ -574,13 +576,13 @@
 
     @Override
     public boolean enterCallNode(final CallNode callNode) {
-        lineNumber(callNode);
-
-        final List<Node>   args            = callNode.getArgs();
-        final Node         function        = callNode.getFunction();
-        final Block        currentBlock    = lc.getCurrentBlock();
+        lineNumber(callNode.getLineNumber());
+
+        final List<Expression> args = callNode.getArgs();
+        final Expression function = callNode.getFunction();
+        final Block currentBlock = lc.getCurrentBlock();
         final CodeGeneratorLexicalContext codegenLexicalContext = lc;
-        final Type         callNodeType    = callNode.getType();
+        final Type callNodeType = callNode.getType();
 
         function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
 
@@ -771,11 +773,19 @@
     }
 
     @Override
-    public boolean enterExecuteNode(final ExecuteNode executeNode) {
-        lineNumber(executeNode);
-
-        final Node expression = executeNode.getExpression();
-        expression.accept(this);
+    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
+        lineNumber(expressionStatement);
+
+        expressionStatement.getExpression().accept(this);
+
+        return false;
+    }
+
+    @Override
+    public boolean enterBlockStatement(final BlockStatement blockStatement) {
+        lineNumber(blockStatement);
+
+        blockStatement.getBlock().accept(this);
 
         return false;
     }
@@ -794,10 +804,10 @@
     }
 
     private void enterFor(final ForNode forNode) {
-        final Node  init   = forNode.getInit();
-        final Node  test   = forNode.getTest();
-        final Block body   = forNode.getBody();
-        final Node  modify = forNode.getModify();
+        final Expression init   = forNode.getInit();
+        final Expression test   = forNode.getTest();
+        final Block      body   = forNode.getBody();
+        final Expression modify = forNode.getModify();
 
         if (init != null) {
             init.accept(this);
@@ -827,19 +837,13 @@
 
     private void enterForIn(final ForNode forNode) {
         final Block body   = forNode.getBody();
-        final Node  modify = forNode.getModify();
+        final Expression  modify = forNode.getModify();
 
         final Symbol iter      = forNode.getIterator();
         final Label  loopLabel = new Label("loop");
 
-        Node init = forNode.getInit();
-
-        // We have to evaluate the optional initializer expression
-        // of the iterator variable of the for-in statement.
-        if (init instanceof VarNode) {
-            init.accept(this);
-            init = ((VarNode)init).getName();
-        }
+        final Expression init = forNode.getInit();
+        assert init instanceof IdentNode;
 
         load(modify);
         assert modify.getType().isObject();
@@ -848,7 +852,7 @@
         method._goto(forNode.getContinueLabel());
         method.label(loopLabel);
 
-        new Store<Node>(init) {
+        new Store<Expression>(init) {
             @Override
             protected void storeNonDiscard() {
                 return;
@@ -1047,7 +1051,7 @@
     public boolean enterIfNode(final IfNode ifNode) {
         lineNumber(ifNode);
 
-        final Node  test = ifNode.getTest();
+        final Expression test = ifNode.getTest();
         final Block pass = ifNode.getPass();
         final Block fail = ifNode.getFail();
 
@@ -1087,7 +1091,10 @@
     }
 
     private void lineNumber(final Statement statement) {
-        final int lineNumber = statement.getLineNumber();
+        lineNumber(statement.getLineNumber());
+    }
+
+    private void lineNumber(int lineNumber) {
         if (lineNumber != lastLineNumber) {
             method.lineNumber(lineNumber);
         }
@@ -1106,7 +1113,7 @@
     private MethodEmitter loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
         assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
 
-        final Node[]          nodes    = arrayLiteralNode.getValue();
+        final Expression[]    nodes    = arrayLiteralNode.getValue();
         final Object          presets  = arrayLiteralNode.getPresets();
         final int[]           postsets = arrayLiteralNode.getPostsets();
         final Class<?>        type     = arrayType.getTypeClass();
@@ -1166,11 +1173,11 @@
         return method;
     }
 
-    private void storeElement(final Node[] nodes, final Type elementType, final int index) {
+    private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
         method.dup();
         method.load(index);
 
-        final Node element = nodes[index];
+        final Expression element = nodes[index];
 
         if (element == null) {
             method.loadEmpty(elementType);
@@ -1182,7 +1189,7 @@
         method.arraystore();
     }
 
-    private MethodEmitter loadArgsArray(final List<Node> args) {
+    private MethodEmitter loadArgsArray(final List<Expression> args) {
         final Object[] array = new Object[args.size()];
         loadConstant(array);
 
@@ -1323,16 +1330,16 @@
     public boolean enterObjectNode(final ObjectNode objectNode) {
         final List<PropertyNode> elements = objectNode.getElements();
 
-        final List<String> keys    = new ArrayList<>();
-        final List<Symbol> symbols = new ArrayList<>();
-        final List<Node>   values  = new ArrayList<>();
+        final List<String>     keys    = new ArrayList<>();
+        final List<Symbol>     symbols = new ArrayList<>();
+        final List<Expression> values  = new ArrayList<>();
 
         boolean hasGettersSetters = false;
 
         for (PropertyNode propertyNode: elements) {
-            final Node         value        = propertyNode.getValue();
+            final Expression   value        = propertyNode.getValue();
             final String       key          = propertyNode.getKeyName();
-            final Symbol       symbol       = value == null ? null : propertyNode.getSymbol();
+            final Symbol       symbol       = value == null ? null : propertyNode.getKey().getSymbol();
 
             if (value == null) {
                 hasGettersSetters = true;
@@ -1346,9 +1353,9 @@
         if (elements.size() > OBJECT_SPILL_THRESHOLD) {
             new SpillObjectCreator(this, keys, symbols, values).makeObject(method);
         } else {
-            new FieldObjectCreator<Node>(this, keys, symbols, values) {
+            new FieldObjectCreator<Expression>(this, keys, symbols, values) {
                 @Override
-                protected void loadValue(final Node node) {
+                protected void loadValue(final Expression node) {
                     load(node);
                 }
 
@@ -1419,7 +1426,7 @@
 
         final Type returnType = lc.getCurrentFunction().getReturnType();
 
-        final Node expression = returnNode.getExpression();
+        final Expression expression = returnNode.getExpression();
         if (expression != null) {
             load(expression);
         } else {
@@ -1435,7 +1442,7 @@
         return node instanceof LiteralNode<?> && ((LiteralNode<?>) node).isNull();
     }
 
-    private boolean nullCheck(final RuntimeNode runtimeNode, final List<Node> args, final String signature) {
+    private boolean nullCheck(final RuntimeNode runtimeNode, final List<Expression> args, final String signature) {
         final Request request = runtimeNode.getRequest();
 
         if (!Request.isEQ(request) && !Request.isNE(request)) {
@@ -1444,11 +1451,11 @@
 
         assert args.size() == 2 : "EQ or NE or TYPEOF need two args";
 
-        Node lhs = args.get(0);
-        Node rhs = args.get(1);
+        Expression lhs = args.get(0);
+        Expression rhs = args.get(1);
 
         if (isNullLiteral(lhs)) {
-            final Node tmp = lhs;
+            final Expression tmp = lhs;
             lhs = rhs;
             rhs = tmp;
         }
@@ -1502,7 +1509,7 @@
         return false;
     }
 
-    private boolean specializationCheck(final RuntimeNode.Request request, final Node node, final List<Node> args) {
+    private boolean specializationCheck(final RuntimeNode.Request request, final Expression node, final List<Expression> args) {
         if (!request.canSpecialize()) {
             return false;
         }
@@ -1555,10 +1562,11 @@
          *
          * TODO - remove this - Access Specializer will always know after Attr/Lower
          */
+        final List<Expression> args = runtimeNode.getArgs();
         if (runtimeNode.isPrimitive() && !runtimeNode.isFinal() && isReducible(runtimeNode.getRequest())) {
-            final Node lhs = runtimeNode.getArgs().get(0);
-            assert runtimeNode.getArgs().size() > 1 : runtimeNode + " must have two args";
-            final Node rhs = runtimeNode.getArgs().get(1);
+            final Expression lhs = args.get(0);
+            assert args.size() > 1 : runtimeNode + " must have two args";
+            final Expression rhs = args.get(1);
 
             final Type   type   = runtimeNode.getType();
             final Symbol symbol = runtimeNode.getSymbol();
@@ -1595,9 +1603,6 @@
             }
         }
 
-        // Get the request arguments.
-        final List<Node> args = runtimeNode.getArgs();
-
         if (nullCheck(runtimeNode, args, new FunctionSignature(false, false, runtimeNode.getType(), args).toString())) {
             return false;
         }
@@ -1606,7 +1611,7 @@
             return false;
         }
 
-        for (final Node arg : runtimeNode.getArgs()) {
+        for (final Expression arg : args) {
             load(arg).convert(Type.OBJECT); //TODO this should not be necessary below Lower
         }
 
@@ -1617,7 +1622,7 @@
                 false,
                 false,
                 runtimeNode.getType(),
-                runtimeNode.getArgs().size()).toString());
+                args.size()).toString());
         method.convert(runtimeNode.getType());
         method.store(runtimeNode.getSymbol());
 
@@ -1626,8 +1631,6 @@
 
     @Override
     public boolean enterSplitNode(final SplitNode splitNode) {
-        lineNumber(splitNode);
-
         final CompileUnit splitCompileUnit = splitNode.getCompileUnit();
 
         final FunctionNode fn   = lc.getCurrentFunction();
@@ -1772,7 +1775,7 @@
     public boolean enterSwitchNode(final SwitchNode switchNode) {
         lineNumber(switchNode);
 
-        final Node           expression  = switchNode.getExpression();
+        final Expression     expression  = switchNode.getExpression();
         final Symbol         tag         = switchNode.getTag();
         final boolean        allInteger  = tag.getSymbolType().isInteger();
         final List<CaseNode> cases       = switchNode.getCases();
@@ -1875,7 +1878,7 @@
             }
 
             for (final CaseNode caseNode : cases) {
-                final Node test = caseNode.getTest();
+                final Expression test = caseNode.getTest();
 
                 if (test != null) {
                     method.load(tag);
@@ -1915,10 +1918,10 @@
 
         final Source source     = lc.getCurrentFunction().getSource();
 
-        final Node   expression = throwNode.getExpression();
-        final int    position   = throwNode.position();
-        final int    line       = source.getLine(position);
-        final int    column     = source.getColumn(position);
+        final Expression expression = throwNode.getExpression();
+        final int        position   = throwNode.position();
+        final int        line       = source.getLine(position);
+        final int        column     = source.getColumn(position);
 
         load(expression);
         assert expression.getType().isObject();
@@ -1967,10 +1970,10 @@
             lc.push(catchBlock);
             enterBlock(catchBlock);
 
-            final CatchNode catchNode          = (CatchNode)catchBlocks.get(i).getStatements().get(0);
-            final IdentNode exception          = catchNode.getException();
-            final Node      exceptionCondition = catchNode.getExceptionCondition();
-            final Block     catchBody          = catchNode.getBody();
+            final CatchNode  catchNode          = (CatchNode)catchBlocks.get(i).getStatements().get(0);
+            final IdentNode  exception          = catchNode.getException();
+            final Expression exceptionCondition = catchNode.getExceptionCondition();
+            final Block      catchBody          = catchNode.getBody();
 
             new Store<IdentNode>(exception) {
                 @Override
@@ -2038,7 +2041,7 @@
     @Override
     public boolean enterVarNode(final VarNode varNode) {
 
-        final Node init = varNode.getInit();
+        final Expression init = varNode.getInit();
 
         if (init == null) {
             return false;
@@ -2046,8 +2049,8 @@
 
         lineNumber(varNode);
 
-        final Symbol varSymbol = varNode.getSymbol();
-        assert varSymbol != null : "variable node " + varNode + " requires a symbol";
+        final Symbol varSymbol = varNode.getName().getSymbol();
+        assert varSymbol != null : "variable node " + varNode + " requires a name with a symbol";
 
         assert method != null;
 
@@ -2067,9 +2070,7 @@
                 method.dynamicSet(type, identNode.getName(), flags);
             }
         } else {
-            assert varNode.getType() == varNode.getName().getType() : "varNode type=" + varNode.getType() + " nametype=" + varNode.getName().getType() + " inittype=" + init.getType();
-
-            method.convert(varNode.getType()); // aw: convert moved here
+            method.convert(varNode.getName().getType()); // aw: convert moved here
             method.store(varSymbol);
         }
 
@@ -2080,11 +2081,11 @@
     public boolean enterWhileNode(final WhileNode whileNode) {
         lineNumber(whileNode);
 
-        final Node  test          = whileNode.getTest();
-        final Block body          = whileNode.getBody();
-        final Label breakLabel    = whileNode.getBreakLabel();
-        final Label continueLabel = whileNode.getContinueLabel();
-        final Label loopLabel     = new Label("loop");
+        final Expression test          = whileNode.getTest();
+        final Block      body          = whileNode.getBody();
+        final Label      breakLabel    = whileNode.getBreakLabel();
+        final Label      continueLabel = whileNode.getContinueLabel();
+        final Label      loopLabel     = new Label("loop");
 
         if (!whileNode.isDoWhile()) {
             method._goto(continueLabel);
@@ -2111,8 +2112,8 @@
 
     @Override
     public boolean enterWithNode(final WithNode withNode) {
-        final Node expression = withNode.getExpression();
-        final Node body       = withNode.getBody();
+        final Expression expression = withNode.getExpression();
+        final Node       body       = withNode.getBody();
 
         // It is possible to have a "pathological" case where the with block does not reference *any* identifiers. It's
         // pointless, but legal. In that case, if nothing else in the method forced the assignment of a slot to the
@@ -2187,7 +2188,7 @@
     // do this better with convert calls to method. TODO
     @Override
     public boolean enterCONVERT(final UnaryNode unaryNode) {
-        final Node rhs = unaryNode.rhs();
+        final Expression rhs = unaryNode.rhs();
         final Type to  = unaryNode.getType();
 
         if (to.isObject() && rhs instanceof LiteralNode) {
@@ -2224,11 +2225,11 @@
 
     @Override
     public boolean enterDECINC(final UnaryNode unaryNode) {
-        final Node      rhs         = unaryNode.rhs();
-        final Type      type        = unaryNode.getType();
-        final TokenType tokenType   = unaryNode.tokenType();
-        final boolean   isPostfix   = tokenType == TokenType.DECPOSTFIX || tokenType == TokenType.INCPOSTFIX;
-        final boolean   isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX;
+        final Expression rhs         = unaryNode.rhs();
+        final Type       type        = unaryNode.getType();
+        final TokenType  tokenType   = unaryNode.tokenType();
+        final boolean    isPostfix   = tokenType == TokenType.DECPOSTFIX || tokenType == TokenType.INCPOSTFIX;
+        final boolean    isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX;
 
         assert !type.isObject();
 
@@ -2272,7 +2273,7 @@
 
     @Override
     public boolean enterDISCARD(final UnaryNode unaryNode) {
-        final Node rhs = unaryNode.rhs();
+        final Expression rhs = unaryNode.rhs();
 
         lc.pushDiscard(rhs);
         load(rhs);
@@ -2289,7 +2290,7 @@
     @Override
     public boolean enterNEW(final UnaryNode unaryNode) {
         final CallNode callNode = (CallNode)unaryNode.rhs();
-        final List<Node> args   = callNode.getArgs();
+        final List<Expression> args   = callNode.getArgs();
 
         // Load function reference.
         load(callNode.getFunction()).convert(Type.OBJECT); // must detect type error
@@ -2302,7 +2303,7 @@
 
     @Override
     public boolean enterNOT(final UnaryNode unaryNode) {
-        final Node rhs = unaryNode.rhs();
+        final Expression rhs = unaryNode.rhs();
 
         load(rhs);
 
@@ -2336,19 +2337,18 @@
         return false;
     }
 
-    private Node enterNumericAdd(final Node lhs, final Node rhs, final Type type, final Symbol symbol) {
+    private void enterNumericAdd(final Expression lhs, final Expression rhs, final Type type, final Symbol symbol) {
         assert lhs.getType().equals(rhs.getType()) && lhs.getType().equals(type) : lhs.getType() + " != " + rhs.getType() + " != " + type + " " + new ASTWriter(lhs) + " " + new ASTWriter(rhs);
         load(lhs);
         load(rhs);
         method.add(); //if the symbol is optimistic, it always needs to be written, not on the stack?
         method.store(symbol);
-        return null;
     }
 
     @Override
     public boolean enterADD(final BinaryNode binaryNode) {
-        final Node lhs = binaryNode.lhs();
-        final Node rhs = binaryNode.rhs();
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
 
         final Type type = binaryNode.getType();
         if (type.isNumeric()) {
@@ -2364,8 +2364,8 @@
     }
 
     private boolean enterAND_OR(final BinaryNode binaryNode) {
-        final Node lhs = binaryNode.lhs();
-        final Node rhs = binaryNode.rhs();
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
 
         final Label skip = new Label("skip");
 
@@ -2392,8 +2392,8 @@
 
     @Override
     public boolean enterASSIGN(final BinaryNode binaryNode) {
-        final Node lhs = binaryNode.lhs();
-        final Node rhs = binaryNode.rhs();
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
 
         final Type lhsType = lhs.getType();
         final Type rhsType = rhs.getType();
@@ -2661,8 +2661,8 @@
     }
 
     private boolean enterComma(final BinaryNode binaryNode) {
-        final Node lhs = binaryNode.lhs();
-        final Node rhs = binaryNode.rhs();
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
 
         load(lhs);
         load(rhs);
@@ -2693,7 +2693,7 @@
         return false;
     }
 
-    private boolean enterCmp(final Node lhs, final Node rhs, final Condition cond, final Type type, final Symbol symbol) {
+    private boolean enterCmp(final Expression lhs, final Expression rhs, final Condition cond, final Type type, final Symbol symbol) {
         final Type lhsType = lhs.getType();
         final Type rhsType = rhs.getType();
 
@@ -2846,21 +2846,21 @@
 
     @Override
     public boolean enterTernaryNode(final TernaryNode ternaryNode) {
-        final Node lhs   = ternaryNode.lhs();
-        final Node rhs   = ternaryNode.rhs();
-        final Node third = ternaryNode.third();
+        final Expression test      = ternaryNode.getTest();
+        final Expression trueExpr  = ternaryNode.getTrueExpression();
+        final Expression falseExpr = ternaryNode.getFalseExpression();
 
         final Symbol symbol     = ternaryNode.getSymbol();
         final Label  falseLabel = new Label("ternary_false");
         final Label  exitLabel  = new Label("ternary_exit");
 
-        Type widest = Type.widest(rhs.getType(), third.getType());
-        if (rhs.getType().isArray() || third.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type
+        Type widest = Type.widest(trueExpr.getType(), falseExpr.getType());
+        if (trueExpr.getType().isArray() || falseExpr.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type
             widest = Type.OBJECT;
         }
 
-        load(lhs);
-        assert lhs.getType().isBoolean() : "lhs in ternary must be boolean";
+        load(test);
+        assert test.getType().isBoolean() : "lhs in ternary must be boolean";
 
         // we still keep the conversion here as the AccessSpecializer can have separated the types, e.g. var y = x ? x=55 : 17
         // will left as (Object)x=55 : (Object)17 by Lower. Then the first term can be {I}x=55 of type int, which breaks the
@@ -2868,11 +2868,11 @@
         // to early, or Apply the AccessSpecializer too late. We are mostly probably looking for a separate type pass to
         // do this property. Then we never need any conversions in CodeGenerator
         method.ifeq(falseLabel);
-        load(rhs);
+        load(trueExpr);
         method.convert(widest);
         method._goto(exitLabel);
         method.label(falseLabel);
-        load(third);
+        load(falseExpr);
         method.convert(widest);
         method.label(exitLabel);
         method.store(symbol);
@@ -2925,8 +2925,8 @@
      *
      * @param <T>
      */
-    private abstract class SelfModifyingStore<T extends Node> extends Store<T> {
-        protected SelfModifyingStore(final T assignNode, final Node target) {
+    private abstract class SelfModifyingStore<T extends Expression> extends Store<T> {
+        protected SelfModifyingStore(final T assignNode, final Expression target) {
             super(assignNode, target);
         }
 
@@ -2939,13 +2939,13 @@
     /**
      * Helper class to generate stores
      */
-    private abstract class Store<T extends Node> {
+    private abstract class Store<T extends Expression> {
 
         /** An assignment node, e.g. x += y */
         protected final T assignNode;
 
         /** The target node to store to, e.g. x */
-        private final Node target;
+        private final Expression target;
 
         /** How deep on the stack do the arguments go if this generates an indy call */
         private int depth;
@@ -2959,7 +2959,7 @@
          * @param assignNode the node representing the whole assignment
          * @param target     the target node of the assignment (destination)
          */
-        protected Store(final T assignNode, final Node target) {
+        protected Store(final T assignNode, final Expression target) {
             this.assignNode = assignNode;
             this.target = target;
         }
@@ -3002,8 +3002,8 @@
 
                 private void enterBaseNode() {
                     assert target instanceof BaseNode : "error - base node " + target + " must be instanceof BaseNode";
-                    final BaseNode baseNode = (BaseNode)target;
-                    final Node     base     = baseNode.getBase();
+                    final BaseNode   baseNode = (BaseNode)target;
+                    final Expression base     = baseNode.getBase();
 
                     load(base);
                     method.convert(Type.OBJECT);
@@ -3024,7 +3024,7 @@
                 public boolean enterIndexNode(final IndexNode node) {
                     enterBaseNode();
 
-                    final Node index = node.getIndex();
+                    final Expression index = node.getIndex();
                     // could be boolean here as well
                     load(index);
                     if (!index.getType().isNumeric()) {
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Jul 11 18:33:33 2013 +0200
@@ -21,6 +21,7 @@
 import jdk.nashorn.internal.codegen.types.Range;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.LexicalContext;
@@ -256,17 +257,20 @@
 
                 @Override
                 public Node leaveDefault(final Node node) {
-                    final Symbol symbol = node.getSymbol();
-                    if (symbol != null) {
-                        final Range range  = symbol.getRange();
-                        final Type  symbolType = symbol.getSymbolType();
-                        if (!symbolType.isNumeric()) {
-                            return node;
-                        }
-                        final Type  rangeType  = range.getType();
-                        if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
-                            RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
-                            return node.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
+                    if(node instanceof Expression) {
+                        final Expression expr = (Expression)node;
+                        final Symbol symbol = expr.getSymbol();
+                        if (symbol != null) {
+                            final Range range  = symbol.getRange();
+                            final Type  symbolType = symbol.getSymbolType();
+                            if (!symbolType.isNumeric()) {
+                                return expr;
+                            }
+                            final Type  rangeType  = range.getType();
+                            if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
+                                RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
+                                return expr.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
+                            }
                         }
                     }
                     return node;
--- a/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Thu Jul 11 18:33:33 2013 +0200
@@ -39,7 +39,8 @@
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
-import jdk.nashorn.internal.ir.ExecuteNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
@@ -146,9 +147,9 @@
      * strings etc as well.
      */
     @Override
-    public Node leaveADD(final BinaryNode binaryNode) {
-        final Node lhs = binaryNode.lhs();
-        final Node rhs = binaryNode.rhs();
+    public Expression leaveADD(final BinaryNode binaryNode) {
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
 
         final Type type = binaryNode.getType();
 
@@ -240,7 +241,7 @@
         return leaveASSIGN(binaryNode);
     }
 
-    private boolean symbolIsInteger(Node node) {
+    private boolean symbolIsInteger(final Expression node) {
         final Symbol symbol = node.getSymbol();
         assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + lc.getCurrentFunction().getSource();
         return true;
@@ -372,7 +373,7 @@
 
     @Override
     public Node leaveCatchNode(final CatchNode catchNode) {
-        final Node exceptionCondition = catchNode.getExceptionCondition();
+        final Expression exceptionCondition = catchNode.getExceptionCondition();
         if (exceptionCondition != null) {
             return catchNode.setExceptionCondition(convert(exceptionCondition, Type.BOOLEAN));
         }
@@ -380,16 +381,16 @@
     }
 
     @Override
-    public Node leaveExecuteNode(final ExecuteNode executeNode) {
+    public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
         temporarySymbols.reuse();
-        return executeNode.setExpression(discard(executeNode.getExpression()));
+        return expressionStatement.setExpression(discard(expressionStatement.getExpression()));
     }
 
     @Override
     public Node leaveForNode(final ForNode forNode) {
-        final Node init   = forNode.getInit();
-        final Node test   = forNode.getTest();
-        final Node modify = forNode.getModify();
+        final Expression init   = forNode.getInit();
+        final Expression test   = forNode.getTest();
+        final Expression modify = forNode.getModify();
 
         if (forNode.isForIn()) {
             return forNode.setModify(lc, convert(forNode.getModify(), Type.OBJECT)); // NASHORN-400
@@ -439,13 +440,13 @@
     public boolean enterLiteralNode(final LiteralNode literalNode) {
         if (literalNode instanceof ArrayLiteralNode) {
             final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode)literalNode;
-            final Node[]           array            = arrayLiteralNode.getValue();
+            final Expression[]     array            = arrayLiteralNode.getValue();
             final Type             elementType      = arrayLiteralNode.getElementType();
 
             for (int i = 0; i < array.length; i++) {
                 final Node element = array[i];
                 if (element != null) {
-                    array[i] = convert(element.accept(this), elementType);
+                    array[i] = convert((Expression)element.accept(this), elementType);
                 }
             }
         }
@@ -455,7 +456,7 @@
 
     @Override
     public Node leaveReturnNode(final ReturnNode returnNode) {
-        final Node expr = returnNode.getExpression();
+        final Expression expr = returnNode.getExpression();
         if (expr != null) {
             return returnNode.setExpression(convert(expr, lc.getCurrentFunction().getReturnType()));
         }
@@ -464,8 +465,8 @@
 
     @Override
     public Node leaveRuntimeNode(final RuntimeNode runtimeNode) {
-        final List<Node> args = runtimeNode.getArgs();
-        for (final Node arg : args) {
+        final List<Expression> args = runtimeNode.getArgs();
+        for (final Expression arg : args) {
             assert !arg.getType().isUnknown();
         }
         return runtimeNode;
@@ -479,12 +480,12 @@
             return switchNode;
         }
 
-        final Node           expression  = switchNode.getExpression();
+        final Expression     expression  = switchNode.getExpression();
         final List<CaseNode> cases       = switchNode.getCases();
         final List<CaseNode> newCases    = new ArrayList<>();
 
         for (final CaseNode caseNode : cases) {
-            final Node test = caseNode.getTest();
+            final Expression test = caseNode.getTest();
             newCases.add(test != null ? caseNode.setTest(convert(test, Type.OBJECT)) : caseNode);
         }
 
@@ -495,7 +496,7 @@
 
     @Override
     public Node leaveTernaryNode(final TernaryNode ternaryNode) {
-        return ternaryNode.setLHS(convert(ternaryNode.lhs(), Type.BOOLEAN));
+        return ternaryNode.setTest(convert(ternaryNode.getTest(), Type.BOOLEAN));
     }
 
     @Override
@@ -505,16 +506,16 @@
 
     @Override
     public Node leaveVarNode(final VarNode varNode) {
-        final Node init = varNode.getInit();
+        final Expression init = varNode.getInit();
         if (init != null) {
             final SpecializedNode specialized = specialize(varNode);
             final VarNode specVarNode = (VarNode)specialized.node;
             Type destType = specialized.type;
             if (destType == null) {
-                destType = specVarNode.getType();
+                destType = specVarNode.getName().getType();
             }
-            assert specVarNode.hasType() : specVarNode + " doesn't have a type";
-            final Node convertedInit = convert(init, destType);
+            assert specVarNode.getName().hasType() : specVarNode + " doesn't have a type";
+            final Expression convertedInit = convert(init, destType);
             temporarySymbols.reuse();
             return specVarNode.setInit(convertedInit);
         }
@@ -524,7 +525,7 @@
 
     @Override
     public Node leaveWhileNode(final WhileNode whileNode) {
-        final Node test = whileNode.getTest();
+        final Expression test = whileNode.getTest();
         if (test != null) {
             return whileNode.setTest(lc, convert(test, Type.BOOLEAN));
         }
@@ -599,8 +600,8 @@
      */
     @SuppressWarnings("fallthrough")
     private Node leaveCmp(final BinaryNode binaryNode, final RuntimeNode.Request request) {
-        final Node lhs    = binaryNode.lhs();
-        final Node rhs    = binaryNode.rhs();
+        final Expression lhs    = binaryNode.lhs();
+        final Expression rhs    = binaryNode.rhs();
 
         Type widest = Type.widest(lhs.getType(), rhs.getType());
 
@@ -696,10 +697,10 @@
         }
     }
 
-    <T extends Node> SpecializedNode specialize(final Assignment<T> assignment) {
+    <T extends Expression> SpecializedNode specialize(final Assignment<T> assignment) {
         final Node node = ((Node)assignment);
         final T lhs = assignment.getAssignmentDest();
-        final Node rhs = assignment.getAssignmentSource();
+        final Expression rhs = assignment.getAssignmentSource();
 
         if (!canHaveCallSiteType(lhs)) {
             return new SpecializedNode(node, null);
@@ -718,8 +719,16 @@
         }
 
         final Node newNode = assignment.setAssignmentDest(setTypeOverride(lhs, to));
-        final Node typePropagatedNode = propagateType(newNode, to);
-
+        final Node typePropagatedNode;
+        if(newNode instanceof Expression) {
+            typePropagatedNode = propagateType((Expression)newNode, to);
+        } else if(newNode instanceof VarNode) {
+            // VarNode, being a statement, doesn't have its own symbol; it uses the symbol of its name instead.
+            final VarNode varNode = (VarNode)newNode;
+            typePropagatedNode = varNode.setName((IdentNode)propagateType(varNode.getName(), to));
+        } else {
+            throw new AssertionError();
+        }
         return new SpecializedNode(typePropagatedNode, to);
     }
 
@@ -759,7 +768,7 @@
      * @param to      new type
      */
     @SuppressWarnings("unchecked")
-    <T extends Node> T setTypeOverride(final T node, final Type to) {
+    <T extends Expression> T setTypeOverride(final T node, final Type to) {
         final Type from = node.getType();
         if (!node.getType().equals(to)) {
             LOG.info("Changing call override type for '", node, "' from ", node.getType(), " to ", to);
@@ -788,7 +797,7 @@
      * @param to   destination type
      * @return     conversion node
      */
-    private Node convert(final Node node, final Type to) {
+    private Expression convert(final Expression node, final Type to) {
         assert !to.isUnknown() : "unknown type for " + node + " class=" + node.getClass();
         assert node != null : "node is null";
         assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + lc.getCurrentFunction();
@@ -804,7 +813,7 @@
             return node;
         }
 
-        Node resultNode = node;
+        Expression resultNode = node;
 
         if (node instanceof LiteralNode && !(node instanceof ArrayLiteralNode) && !to.isObject()) {
             final LiteralNode<?> newNode = new LiteralNodeConstantEvaluator((LiteralNode<?>)node, to).eval();
@@ -828,9 +837,9 @@
         return temporarySymbols.ensureSymbol(lc, to, resultNode);
     }
 
-    private static Node discard(final Node node) {
+    private static Expression discard(final Expression node) {
         if (node.getSymbol() != null) {
-            final Node discard = new UnaryNode(Token.recast(node.getToken(), TokenType.DISCARD), node);
+            final UnaryNode discard = new UnaryNode(Token.recast(node.getToken(), TokenType.DISCARD), node);
             //discard never has a symbol in the discard node - then it would be a nop
             assert !node.isTerminal();
             return discard;
@@ -853,7 +862,7 @@
      * @param node
      * @param to
      */
-    private Node propagateType(final Node node, final Type to) {
+    private Expression propagateType(final Expression node, final Type to) {
         Symbol symbol = node.getSymbol();
         if (symbol.isTemp() && symbol.getSymbolType() != to) {
             symbol = symbol.setTypeOverrideShared(to, temporarySymbols);
--- a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java	Thu Jul 11 18:33:33 2013 +0200
@@ -28,8 +28,8 @@
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.BlockStatement;
 import jdk.nashorn.internal.ir.EmptyNode;
-import jdk.nashorn.internal.ir.ExecuteNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IfNode;
@@ -91,7 +91,7 @@
         if (test instanceof LiteralNode) {
             final Block shortCut = ((LiteralNode<?>)test).isTrue() ? ifNode.getPass() : ifNode.getFail();
             if (shortCut != null) {
-                return new ExecuteNode(shortCut.getLineNumber(), shortCut.getToken(), shortCut.getFinish(), shortCut);
+                return new BlockStatement(ifNode.getLineNumber(), shortCut);
             }
             return new EmptyNode(ifNode);
         }
@@ -100,9 +100,9 @@
 
     @Override
     public Node leaveTernaryNode(final TernaryNode ternaryNode) {
-        final Node test = ternaryNode.lhs();
+        final Node test = ternaryNode.getTest();
         if (test instanceof LiteralNode) {
-            return ((LiteralNode<?>)test).isTrue() ? ternaryNode.rhs() : ternaryNode.third();
+            return ((LiteralNode<?>)test).isTrue() ? ternaryNode.getTrueExpression() : ternaryNode.getFalseExpression();
         }
         return ternaryNode;
     }
--- a/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java	Thu Jul 11 18:33:33 2013 +0200
@@ -31,8 +31,8 @@
 import java.util.ArrayList;
 import java.util.List;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
 
@@ -63,7 +63,7 @@
      * @param retType   what is the return type
      * @param args      argument list of AST Nodes
      */
-    public FunctionSignature(final boolean hasSelf, final boolean hasCallee, final Type retType, final List<? extends Node> args) {
+    public FunctionSignature(final boolean hasSelf, final boolean hasCallee, final Type retType, final List<? extends Expression> args) {
         this(hasSelf, hasCallee, retType, FunctionSignature.typeArray(args));
     }
 
@@ -167,7 +167,7 @@
      *
      * @return the array of types
      */
-    private static Type[] typeArray(final List<? extends Node> args) {
+    private static Type[] typeArray(final List<? extends Expression> args) {
         if (args == null) {
             return null;
         }
@@ -175,7 +175,7 @@
         final Type[] typeArray = new Type[args.size()];
 
         int pos = 0;
-        for (final Node arg : args) {
+        for (final Expression arg : args) {
             typeArray[pos++] = arg.getType();
         }
 
--- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java	Thu Jul 11 18:33:33 2013 +0200
@@ -37,12 +37,14 @@
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.BlockLexicalContext;
+import jdk.nashorn.internal.ir.BlockStatement;
 import jdk.nashorn.internal.ir.BreakNode;
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CatchNode;
 import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.EmptyNode;
-import jdk.nashorn.internal.ir.ExecuteNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
@@ -138,7 +140,7 @@
     public boolean enterBlock(final Block block) {
         final FunctionNode   function = lc.getCurrentFunction();
         if (lc.isFunctionBody() && function.isProgram() && !function.hasDeclaredFunctions()) {
-            new ExecuteNode(block.getLineNumber(), block.getToken(), block.getFinish(), LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)).accept(this);
+            new ExpressionStatement(function.getLineNumber(), block.getToken(), block.getFinish(), LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)).accept(this);
         }
         return true;
     }
@@ -154,7 +156,7 @@
             final boolean isProgram = currentFunction.isProgram();
             final Statement last = lc.getLastStatement();
             final ReturnNode returnNode = new ReturnNode(
-                last == null ? block.getLineNumber() : last.getLineNumber(), //TODO?
+                last == null ? currentFunction.getLineNumber() : last.getLineNumber(), //TODO?
                 currentFunction.getToken(),
                 currentFunction.getFinish(),
                 isProgram ?
@@ -195,23 +197,21 @@
     }
 
     @Override
-    public Node leaveExecuteNode(final ExecuteNode executeNode) {
-        final Node expr = executeNode.getExpression();
-        ExecuteNode node = executeNode;
+    public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
+        final Expression expr = expressionStatement.getExpression();
+        ExpressionStatement node = expressionStatement;
 
         final FunctionNode currentFunction = lc.getCurrentFunction();
 
         if (currentFunction.isProgram()) {
-            if (!(expr instanceof Block) || expr instanceof FunctionNode) { // it's not a block, but can be a function
-                if (!isInternalExpression(expr) && !isEvalResultAssignment(expr)) {
-                    node = executeNode.setExpression(
-                        new BinaryNode(
-                            Token.recast(
-                                executeNode.getToken(),
-                                TokenType.ASSIGN),
-                            compilerConstant(RETURN),
-                        expr));
-                }
+            if (!isInternalExpression(expr) && !isEvalResultAssignment(expr)) {
+                node = expressionStatement.setExpression(
+                    new BinaryNode(
+                        Token.recast(
+                            expressionStatement.getToken(),
+                            TokenType.ASSIGN),
+                        compilerConstant(RETURN),
+                    expr));
             }
         }
 
@@ -219,6 +219,11 @@
     }
 
     @Override
+    public Node leaveBlockStatement(BlockStatement blockStatement) {
+        return addStatement(blockStatement);
+    }
+
+    @Override
     public Node leaveForNode(final ForNode forNode) {
         ForNode newForNode = forNode;
 
@@ -302,11 +307,11 @@
 
         final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName("catch_all"));
 
-        final Block catchBody = new Block(lineNumber, token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), ThrowNode.IS_SYNTHETIC_RETHROW)).
+        final Block catchBody = new Block(token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), ThrowNode.IS_SYNTHETIC_RETHROW)).
                 setIsTerminal(lc, true); //ends with throw, so terminal
 
         final CatchNode catchAllNode  = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, CatchNode.IS_SYNTHETIC_RETHROW);
-        final Block     catchAllBlock = new Block(lineNumber, token, finish, catchAllNode);
+        final Block     catchAllBlock = new Block(token, finish, catchAllNode);
 
         //catchallblock -> catchallnode (catchnode) -> exception -> throw
 
@@ -355,14 +360,14 @@
                     if (!isTerminal(newStatements)) {
                         newStatements.add(throwNode);
                     }
-                    return new Block(throwNode.getLineNumber(), throwNode.getToken(), throwNode.getFinish(), newStatements);
+                    return BlockStatement.createReplacement(throwNode, newStatements);
                 }
                 return throwNode;
             }
 
             @Override
             public Node leaveBreakNode(final BreakNode breakNode) {
-                return copy(breakNode, Lower.this.lc.getBreakable(breakNode.getLabel()));
+                return copy(breakNode, (Node)Lower.this.lc.getBreakable(breakNode.getLabel()));
             }
 
             @Override
@@ -372,15 +377,15 @@
 
             @Override
             public Node leaveReturnNode(final ReturnNode returnNode) {
-                final Node  expr  = returnNode.getExpression();
+                final Expression expr  = returnNode.getExpression();
                 final List<Statement> newStatements = new ArrayList<>();
 
-                final Node resultNode;
+                final Expression resultNode;
                 if (expr != null) {
                     //we need to evaluate the result of the return in case it is complex while
                     //still in the try block, store it in a result value and return it afterwards
                     resultNode = new IdentNode(Lower.this.compilerConstant(RETURN));
-                    newStatements.add(new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr)));
+                    newStatements.add(new ExpressionStatement(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr)));
                 } else {
                     resultNode = null;
                 }
@@ -390,7 +395,7 @@
                     newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode));
                 }
 
-                return new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new Block(returnNode.getLineNumber(), returnNode.getToken(), lc.getCurrentBlock().getFinish(), newStatements));
+                return BlockStatement.createReplacement(returnNode, lc.getCurrentBlock().getFinish(), newStatements);
             }
 
             private Node copy(final Statement endpoint, final Node targetNode) {
@@ -399,7 +404,7 @@
                     if (!isTerminal(newStatements)) {
                         newStatements.add(endpoint);
                     }
-                    return new ExecuteNode(endpoint.getLineNumber(), endpoint.getToken(), endpoint.getFinish(), new Block(endpoint.getLineNumber(), endpoint.getToken(), finish, newStatements));
+                    return BlockStatement.createReplacement(endpoint, finish, newStatements);
                 }
                 return endpoint;
             }
@@ -461,7 +466,7 @@
         if (tryNode.getCatchBlocks().isEmpty()) {
             newTryNode = tryNode.setFinallyBody(null);
         } else {
-            Block outerBody = new Block(tryNode.getLineNumber(), tryNode.getToken(), tryNode.getFinish(), new ArrayList<Statement>(Arrays.asList(tryNode.setFinallyBody(null))));
+            Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), new ArrayList<Statement>(Arrays.asList(tryNode.setFinallyBody(null))));
             newTryNode = tryNode.setBody(outerBody).setCatchBlocks(null);
         }
 
@@ -478,7 +483,7 @@
     public Node leaveVarNode(final VarNode varNode) {
         addStatement(varNode);
         if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && lc.getCurrentFunction().isProgram()) {
-            new ExecuteNode(varNode.getLineNumber(), varNode.getToken(), varNode.getFinish(), new IdentNode(varNode.getName())).accept(this);
+            new ExpressionStatement(varNode.getLineNumber(), varNode.getToken(), varNode.getFinish(), new IdentNode(varNode.getName())).accept(this);
         }
         return varNode;
     }
@@ -511,7 +516,7 @@
      * @param function function called by a CallNode
      * @return transformed node to marker function or identity if not ident/access/indexnode
      */
-    private static Node markerFunction(final Node function) {
+    private static Expression markerFunction(final Expression function) {
         if (function instanceof IdentNode) {
             return ((IdentNode)function).setIsFunction();
         } else if (function instanceof BaseNode) {
@@ -553,15 +558,15 @@
     private CallNode checkEval(final CallNode callNode) {
         if (callNode.getFunction() instanceof IdentNode) {
 
-            final List<Node> args   = callNode.getArgs();
-            final IdentNode  callee = (IdentNode)callNode.getFunction();
+            final List<Expression> args = callNode.getArgs();
+            final IdentNode callee = (IdentNode)callNode.getFunction();
 
             // 'eval' call with at least one argument
             if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) {
                 final FunctionNode currentFunction = lc.getCurrentFunction();
                 return callNode.setEvalArgs(
                     new CallNode.EvalArgs(
-                        ensureUniqueNamesIn(args.get(0)).accept(this),
+                        (Expression)ensureUniqueNamesIn(args.get(0)).accept(this),
                         compilerConstant(THIS),
                         evalLocation(callee),
                         currentFunction.isStrict()));
@@ -630,7 +635,7 @@
      * @param expression expression to check for internal symbol
      * @return true if internal, false otherwise
      */
-    private static boolean isInternalExpression(final Node expression) {
+    private static boolean isInternalExpression(final Expression expression) {
         final Symbol symbol = expression.getSymbol();
         return symbol != null && symbol.isInternal();
     }
--- a/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java	Thu Jul 11 18:33:33 2013 +0200
@@ -28,11 +28,11 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
-
 import jdk.nashorn.internal.codegen.types.Range;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.Assignment;
 import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.LexicalContext;
@@ -87,7 +87,7 @@
     }
 
     //destination visited
-    private Symbol setRange(final Node dest, final Range range) {
+    private Symbol setRange(final Expression dest, final Range range) {
         if (range.isUnknown()) {
             return null;
         }
@@ -352,7 +352,6 @@
             range = range.isUnknown() ? Range.createGenericRange() : range;
 
             setRange(node.getName(), range);
-            setRange(node, range);
         }
 
         return node;
@@ -438,12 +437,12 @@
      * @return
      */
     private static Symbol findLoopCounter(final LoopNode node) {
-        final Node test = node.getTest();
+        final Expression test = node.getTest();
 
         if (test != null && test.isComparison()) {
             final BinaryNode binaryNode = (BinaryNode)test;
-            final Node lhs = binaryNode.lhs();
-            final Node rhs = binaryNode.rhs();
+            final Expression lhs = binaryNode.lhs();
+            final Expression rhs = binaryNode.rhs();
 
             //detect ident cmp int_literal
             if (lhs instanceof IdentNode && rhs instanceof LiteralNode && ((LiteralNode<?>)rhs).getType().isInteger()) {
--- a/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Thu Jul 11 18:33:33 2013 +0200
@@ -25,26 +25,25 @@
 
 package jdk.nashorn.internal.codegen;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
+import static jdk.nashorn.internal.codegen.types.Type.OBJECT;
+
+import java.util.List;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.runtime.Property;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.scripts.JO;
 
-import java.util.List;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
-import static jdk.nashorn.internal.codegen.types.Type.OBJECT;
-
 /**
  * An object creator that uses spill properties.
  */
 public class SpillObjectCreator extends ObjectCreator {
 
-    private final List<Node> values;
+    private final List<Expression> values;
 
     /**
      * Constructor
@@ -54,7 +53,7 @@
      * @param symbols  symbols for fields in object
      * @param values   list of values corresponding to keys
      */
-    protected SpillObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<Node> values) {
+    protected SpillObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<Expression> values) {
         super(codegen, keys, symbols, false, false);
         this.values = values;
         makeMap();
@@ -107,7 +106,7 @@
         for (int i = 0; i < length; i++) {
             final String key = keys.get(i);
             final Property property = propertyMap.findProperty(key);
-            final Node value = values.get(i);
+            final Expression value = values.get(i);
 
             if (property == null && value != null) {
                 method.dup();
--- a/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java	Thu Jul 11 18:33:33 2013 +0200
@@ -31,7 +31,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
@@ -221,14 +220,13 @@
      * @return New split node.
      */
     private SplitNode createBlockSplitNode(final Block parent, final FunctionNode function, final List<Statement> statements, final long weight) {
-        final int    lineNumber = parent.getLineNumber();
         final long   token      = parent.getToken();
         final int    finish     = parent.getFinish();
         final String name       = function.uniqueName(SPLIT_PREFIX.symbolName());
 
-        final Block newBlock = new Block(lineNumber, token, finish, statements);
+        final Block newBlock = new Block(token, finish, statements);
 
-        return new SplitNode(lineNumber, name, newBlock, compiler.findUnit(weight + WeighNodes.FUNCTION_WEIGHT));
+        return new SplitNode(name, newBlock, compiler.findUnit(weight + WeighNodes.FUNCTION_WEIGHT));
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java	Thu Jul 11 18:33:33 2013 +0200
@@ -27,7 +27,6 @@
 
 import java.util.List;
 import java.util.Map;
-
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.BinaryNode;
@@ -36,7 +35,7 @@
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CatchNode;
 import jdk.nashorn.internal.ir.ContinueNode;
-import jdk.nashorn.internal.ir.ExecuteNode;
+import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IdentNode;
@@ -158,8 +157,8 @@
     }
 
     @Override
-    public Node leaveExecuteNode(final ExecuteNode executeNode) {
-        return executeNode;
+    public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
+        return expressionStatement;
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -45,12 +45,12 @@
      * @param base      base node
      * @param property  property
      */
-    public AccessNode(final long token, final int finish, final Node base, final IdentNode property) {
+    public AccessNode(final long token, final int finish, final Expression base, final IdentNode property) {
         super(token, finish, base, false, false);
         this.property = property.setIsPropertyName();
     }
 
-    private AccessNode(final AccessNode accessNode, final Node base, final IdentNode property, final boolean isFunction, final boolean hasCallSiteType) {
+    private AccessNode(final AccessNode accessNode, final Expression base, final IdentNode property, final boolean isFunction, final boolean hasCallSiteType) {
         super(accessNode, base, isFunction, hasCallSiteType);
         this.property = property;
     }
@@ -63,7 +63,7 @@
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterAccessNode(this)) {
             return visitor.leaveAccessNode(
-                setBase(base.accept(visitor)).
+                setBase((Expression)base.accept(visitor)).
                 setProperty((IdentNode)property.accept(visitor)));
         }
         return this;
@@ -103,7 +103,7 @@
         return property;
     }
 
-    private AccessNode setBase(final Node base) {
+    private AccessNode setBase(final Expression base) {
         if (this.base == base) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/Assignment.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/Assignment.java	Thu Jul 11 18:33:33 2013 +0200
@@ -31,7 +31,7 @@
  *
  * @param <D> the destination type
  */
-public interface Assignment<D extends Node> {
+public interface Assignment<D extends Expression> {
 
     /**
      * Get assignment destination
@@ -45,7 +45,7 @@
      *
      * @return get the assignment source node
      */
-    public Node getAssignmentSource();
+    public Expression getAssignmentSource();
 
     /**
      * Set assignment destination node.
--- a/nashorn/src/jdk/nashorn/internal/ir/BaseNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/BaseNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.ir;
 
 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
+
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -37,10 +38,10 @@
  * @see IndexNode
  */
 @Immutable
-public abstract class BaseNode extends Node implements FunctionCall, TypeOverride<BaseNode> {
+public abstract class BaseNode extends Expression implements FunctionCall, TypeOverride<BaseNode> {
 
     /** Base Node. */
-    protected final Node base;
+    protected final Expression base;
 
     private final boolean isFunction;
 
@@ -55,7 +56,7 @@
      * @param isFunction is this a function
      * @param hasCallSiteType does this access have a callsite type
      */
-    public BaseNode(final long token, final int finish, final Node base, final boolean isFunction, final boolean hasCallSiteType) {
+    public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction, final boolean hasCallSiteType) {
         super(token, base.getStart(), finish);
         this.base            = base;
         this.isFunction      = isFunction;
@@ -69,7 +70,7 @@
      * @param isFunction is this a function
      * @param hasCallSiteType does this access have a callsite type
      */
-    protected BaseNode(final BaseNode baseNode, final Node base, final boolean isFunction, final boolean hasCallSiteType) {
+    protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final boolean hasCallSiteType) {
         super(baseNode);
         this.base            = base;
         this.isFunction      = isFunction;
@@ -80,7 +81,7 @@
      * Get the base node for this access
      * @return the base node
      */
-    public Node getBase() {
+    public Expression getBase() {
         return base;
     }
 
--- a/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -34,11 +34,11 @@
  * BinaryNode nodes represent two operand operations.
  */
 @Immutable
-public final class BinaryNode extends Node implements Assignment<Node> {
+public final class BinaryNode extends Expression implements Assignment<Expression> {
     /** Left hand side argument. */
-    private final Node lhs;
+    private final Expression lhs;
 
-    private final Node rhs;
+    private final Expression rhs;
 
     /**
      * Constructor
@@ -47,13 +47,13 @@
      * @param lhs    left hand side
      * @param rhs    right hand side
      */
-    public BinaryNode(final long token, final Node lhs, final Node rhs) {
+    public BinaryNode(final long token, final Expression lhs, final Expression rhs) {
         super(token, lhs.getStart(), rhs.getFinish());
         this.lhs   = lhs;
         this.rhs   = rhs;
     }
 
-    private BinaryNode(final BinaryNode binaryNode, final Node lhs, final Node rhs) {
+    private BinaryNode(final BinaryNode binaryNode, final Expression lhs, final Expression rhs) {
         super(binaryNode);
         this.lhs = lhs;
         this.rhs = rhs;
@@ -141,17 +141,17 @@
     }
 
     @Override
-    public Node getAssignmentDest() {
+    public Expression getAssignmentDest() {
         return isAssignment() ? lhs() : null;
     }
 
     @Override
-    public Node setAssignmentDest(Node n) {
+    public BinaryNode setAssignmentDest(Expression n) {
         return setLHS(n);
     }
 
     @Override
-    public Node getAssignmentSource() {
+    public Expression getAssignmentSource() {
         return rhs();
     }
 
@@ -162,7 +162,7 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterBinaryNode(this)) {
-            return visitor.leaveBinaryNode(setLHS(lhs.accept(visitor)).setRHS(rhs.accept(visitor)));
+            return visitor.leaveBinaryNode(setLHS((Expression)lhs.accept(visitor)).setRHS((Expression)rhs.accept(visitor)));
         }
 
         return this;
@@ -218,7 +218,7 @@
      * Get the left hand side expression for this node
      * @return the left hand side expression
      */
-    public Node lhs() {
+    public Expression lhs() {
         return lhs;
     }
 
@@ -226,7 +226,7 @@
      * Get the right hand side expression for this node
      * @return the left hand side expression
      */
-    public Node rhs() {
+    public Expression rhs() {
         return rhs;
     }
 
@@ -235,7 +235,7 @@
      * @param lhs new left hand side expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public BinaryNode setLHS(final Node lhs) {
+    public BinaryNode setLHS(final Expression lhs) {
         if (this.lhs == lhs) {
             return this;
         }
@@ -247,7 +247,7 @@
      * @param rhs new left hand side expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public BinaryNode setRHS(final Node rhs) {
+    public BinaryNode setRHS(final Expression rhs) {
         if (this.rhs == rhs) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/Block.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/Block.java	Thu Jul 11 18:33:33 2013 +0200
@@ -38,11 +38,10 @@
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
 /**
- * IR representation for a list of statements and functions. All provides the
- * basis for script body.
+ * IR representation for a list of statements.
  */
 @Immutable
-public class Block extends BreakableNode implements Flags<Block> {
+public class Block extends Node implements BreakableNode, Flags<Block> {
     /** List of statements */
     protected final List<Statement> statements;
 
@@ -52,6 +51,9 @@
     /** Entry label. */
     protected final Label entryLabel;
 
+    /** Break label. */
+    private final Label breakLabel;
+
     /** Does the block/function need a new scope? */
     protected final int flags;
 
@@ -76,17 +78,17 @@
     /**
      * Constructor
      *
-     * @param lineNumber line number
      * @param token      token
      * @param finish     finish
      * @param statements statements
      */
-    public Block(final int lineNumber, final long token, final int finish, final Statement... statements) {
-        super(lineNumber, token, finish, new Label("block_break"));
+    public Block(final long token, final int finish, final Statement... statements) {
+        super(token, finish);
 
         this.statements = Arrays.asList(statements);
         this.symbols    = new LinkedHashMap<>();
         this.entryLabel = new Label("block_entry");
+        this.breakLabel = new Label("block_break");
         this.flags     =  0;
     }
 
@@ -98,8 +100,8 @@
      * @param finish     finish
      * @param statements statements
      */
-    public Block(final int lineNumber, final long token, final int finish, final List<Statement> statements) {
-        this(lineNumber, token, finish, statements.toArray(new Statement[statements.size()]));
+    public Block(final long token, final int finish, final List<Statement> statements) {
+        this(token, finish, statements.toArray(new Statement[statements.size()]));
     }
 
     private Block(final Block block, final int finish, final List<Statement> statements, final int flags, final Map<String, Symbol> symbols) {
@@ -108,6 +110,7 @@
         this.flags      = flags;
         this.symbols    = new LinkedHashMap<>(symbols); //todo - symbols have no dependencies on any IR node and can as far as we understand it be shallow copied now
         this.entryLabel = new Label(block.entryLabel);
+        this.breakLabel = new Label(block.breakLabel);
         this.finish     = finish;
     }
 
@@ -223,6 +226,11 @@
         return entryLabel;
     }
 
+    @Override
+    public Label getBreakLabel() {
+        return breakLabel;
+    }
+
     /**
      * Get the list of statements in this block
      *
@@ -322,7 +330,17 @@
     }
 
     @Override
-    protected boolean isBreakableWithoutLabel() {
+    public boolean isBreakableWithoutLabel() {
         return false;
     }
+
+    @Override
+    public List<Label> getLabels() {
+        return Collections.singletonList(breakLabel);
+    }
+
+    @Override
+    public Node accept(NodeVisitor<? extends LexicalContext> visitor) {
+        return Acceptor.accept(this, visitor);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/ir/BlockStatement.java	Thu Jul 11 18:33:33 2013 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.List;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * Represents a block used as a statement.
+ */
+public class BlockStatement extends Statement {
+    /** Block to execute. */
+    private final Block block;
+
+    /**
+     * Constructor
+     *
+     * @param lineNumber line number
+     * @param block the block to execute
+     */
+    public BlockStatement(final int lineNumber, final Block block) {
+        super(lineNumber, block.getToken(), block.getFinish());
+        this.block = block;
+    }
+
+    private BlockStatement(final BlockStatement blockStatement, final Block block) {
+        super(blockStatement);
+        this.block = block;
+    }
+
+    /**
+     * Use this method to create a block statement meant to replace a single statement.
+     * @param stmt the statement to replace
+     * @param newStmts the statements for the new block statement
+     * @return a block statement with the new statements. It will have the line number, token, and finish of the
+     * original statement.
+     */
+    public static Statement createReplacement(final Statement stmt, final List<Statement> newStmts) {
+        return createReplacement(stmt, stmt.getFinish(), newStmts);
+    }
+
+    /**
+     * Use this method to create a block statement meant to replace a single statement.
+     * @param stmt the statement to replace
+     * @param finish the new finish for the block
+     * @param newStmts the statements for the new block statement
+     * @return a block statement with the new statements. It will have the line number, and token of the
+     * original statement.
+     */
+    public static Statement createReplacement(final Statement stmt, int finish, final List<Statement> newStmts) {
+        return new BlockStatement(stmt.getLineNumber(), new Block(stmt.getToken(), finish, newStmts));
+    }
+
+    @Override
+    public boolean isTerminal() {
+        return block.isTerminal();
+    }
+
+    @Override
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        if (visitor.enterBlockStatement(this)) {
+            return visitor.leaveBlockStatement(setBlock((Block)block.accept(visitor)));
+        }
+
+        return this;
+    }
+
+    @Override
+    public void toString(final StringBuilder sb) {
+        block.toString(sb);
+    }
+
+    /**
+     * Return the block to be executed
+     * @return the block
+     */
+    public Block getBlock() {
+        return block;
+    }
+
+    /**
+     * Reset the block to be executed
+     * @param block the block
+     * @return new or same execute node
+     */
+    public BlockStatement setBlock(final Block block) {
+        if (this.block == block) {
+            return this;
+        }
+        return new BlockStatement(this, block);
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/ir/BreakableNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/BreakableNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -25,46 +25,14 @@
 
 package jdk.nashorn.internal.ir;
 
-import java.util.Arrays;
 import java.util.List;
-
 import jdk.nashorn.internal.codegen.Label;
-import jdk.nashorn.internal.ir.annotations.Immutable;
 
 /**
  * This class represents a node from which control flow can execute
  * a {@code break} statement
  */
-@Immutable
-public abstract class BreakableNode extends LexicalContextNode {
-
-    /** break label. */
-    protected final Label breakLabel;
-
-    /**
-     * Constructor
-     *
-     * @param lineNumber line number
-     * @param token      token
-     * @param finish     finish
-     * @param breakLabel break label
-     */
-    protected BreakableNode(final int lineNumber, final long token, final int finish, final Label breakLabel) {
-        super(lineNumber, token, finish);
-        this.breakLabel = breakLabel;
-    }
-
-    /**
-     * Copy constructor
-     *
-     * @param breakableNode source node
-     */
-    protected BreakableNode(final BreakableNode breakableNode) {
-        super(breakableNode);
-        this.breakLabel = new Label(breakableNode.getBreakLabel());
-    }
-
-    @Override
+public interface BreakableNode extends LexicalContextNode {
     public abstract Node ensureUniqueLabels(final LexicalContext lc);
 
     /**
@@ -72,17 +40,13 @@
      * e.g. everything but Blocks, basically
      * @return true if breakable without label
      */
-    protected boolean isBreakableWithoutLabel() {
-        return true;
-    }
+    public boolean isBreakableWithoutLabel();
 
     /**
      * Return the break label, i.e. the location to go to on break.
      * @return the break label
      */
-    public Label getBreakLabel() {
-        return breakLabel;
-    }
+    public Label getBreakLabel();
 
     /**
      * Return the labels associated with this node. Breakable nodes that
@@ -90,8 +54,5 @@
      * afterwards the node in code
      * @return list of labels representing locations around this node
      */
-    public List<Label> getLabels() {
-        return Arrays.asList(breakLabel);
-    }
-
+    public List<Label> getLabels();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/ir/BreakableStatement.java	Thu Jul 11 18:33:33 2013 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.Collections;
+import java.util.List;
+import jdk.nashorn.internal.codegen.Label;
+import jdk.nashorn.internal.ir.annotations.Immutable;
+
+@Immutable
+abstract class BreakableStatement extends LexicalContextStatement implements BreakableNode {
+
+    /** break label. */
+    protected final Label breakLabel;
+
+    /**
+     * Constructor
+     *
+     * @param lineNumber line number
+     * @param token      token
+     * @param finish     finish
+     * @param breakLabel break label
+     */
+    protected BreakableStatement(final int lineNumber, final long token, final int finish, final Label breakLabel) {
+        super(lineNumber, token, finish);
+        this.breakLabel = breakLabel;
+    }
+
+    /**
+     * Copy constructor
+     *
+     * @param breakableNode source node
+     */
+    protected BreakableStatement(final BreakableStatement breakableNode) {
+        super(breakableNode);
+        this.breakLabel = new Label(breakableNode.getBreakLabel());
+    }
+
+    /**
+     * Check whether this can be broken out from without using a label,
+     * e.g. everything but Blocks, basically
+     * @return true if breakable without label
+     */
+    @Override
+    public boolean isBreakableWithoutLabel() {
+        return true;
+    }
+
+    /**
+     * Return the break label, i.e. the location to go to on break.
+     * @return the break label
+     */
+    @Override
+    public Label getBreakLabel() {
+        return breakLabel;
+    }
+
+    /**
+     * Return the labels associated with this node. Breakable nodes that
+     * aren't LoopNodes only have a break label - the location immediately
+     * afterwards the node in code
+     * @return list of labels representing locations around this node
+     */
+    @Override
+    public List<Label> getLabels() {
+        return Collections.singletonList(breakLabel);
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/ir/CallNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/CallNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -27,7 +27,6 @@
 
 import java.util.Collections;
 import java.util.List;
-
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -37,27 +36,29 @@
  * IR representation for a function call.
  */
 @Immutable
-public final class CallNode extends LexicalContextNode implements TypeOverride<CallNode> {
+public final class CallNode extends LexicalContextExpression implements TypeOverride<CallNode> {
 
     private final Type type;
 
     /** Function identifier or function body. */
-    private final Node function;
+    private final Expression function;
 
     /** Call arguments. */
-    private final List<Node> args;
+    private final List<Expression> args;
 
     /** Is this a "new" operation */
     public static final int IS_NEW        = 0x1;
 
     private final int flags;
 
+    private final int lineNumber;
+
     /**
      * Arguments to be passed to builtin {@code eval} function
      */
     public static class EvalArgs {
         /** evaluated code */
-        private final Node code;
+        private final Expression code;
 
         /** 'this' passed to evaluated code */
         private final IdentNode evalThis;
@@ -76,7 +77,7 @@
          * @param location   location for the eval call
          * @param strictMode is this a call from a strict context?
          */
-        public EvalArgs(final Node code, final IdentNode evalThis, final String location, final boolean strictMode) {
+        public EvalArgs(final Expression code, final IdentNode evalThis, final String location, final boolean strictMode) {
             this.code = code;
             this.evalThis = evalThis;
             this.location = location;
@@ -87,11 +88,11 @@
          * Return the code that is to be eval:ed by this eval function
          * @return code as an AST node
          */
-        public Node getCode() {
+        public Expression getCode() {
             return code;
         }
 
-        private EvalArgs setCode(final Node code) {
+        private EvalArgs setCode(final Expression code) {
             if (this.code == code) {
                 return this;
             }
@@ -143,18 +144,20 @@
      * @param function   the function to call
      * @param args       args to the call
      */
-    public CallNode(final int lineNumber, final long token, final int finish, final Node function, final List<Node> args) {
-        super(lineNumber, token, finish);
+    public CallNode(final int lineNumber, final long token, final int finish, final Expression function, final List<Expression> args) {
+        super(token, finish);
 
-        this.function = function;
-        this.args     = args;
-        this.flags    = 0;
-        this.type     = null;
-        this.evalArgs = null;
+        this.function   = function;
+        this.args       = args;
+        this.flags      = 0;
+        this.type       = null;
+        this.evalArgs   = null;
+        this.lineNumber = lineNumber;
     }
 
-    private CallNode(final CallNode callNode, final Node function, final List<Node> args, final int flags, final Type type, final EvalArgs evalArgs) {
+    private CallNode(final CallNode callNode, final Expression function, final List<Expression> args, final int flags, final Type type, final EvalArgs evalArgs) {
         super(callNode);
+        this.lineNumber = callNode.lineNumber;
         this.function = function;
         this.args = args;
         this.flags = flags;
@@ -162,6 +165,14 @@
         this.evalArgs = evalArgs;
     }
 
+    /**
+     * Returns the line number.
+     * @return the line number.
+     */
+    public int getLineNumber() {
+        return lineNumber;
+    }
+
     @Override
     public Type getType() {
         if (hasCallSiteType()) {
@@ -198,13 +209,13 @@
     public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterCallNode(this)) {
             final CallNode newCallNode = (CallNode)visitor.leaveCallNode(
-                    setFunction(function.accept(visitor)).
-                    setArgs(Node.accept(visitor, Node.class, args)).
+                    setFunction((Expression)function.accept(visitor)).
+                    setArgs(Node.accept(visitor, Expression.class, args)).
                     setFlags(flags).
                     setType(null, lc, type).
                     setEvalArgs(evalArgs == null ?
                             null :
-                            evalArgs.setCode(evalArgs.getCode().accept(visitor)).
+                            evalArgs.setCode((Expression)evalArgs.getCode().accept(visitor)).
                                 setThis((IdentNode)evalArgs.getThis().accept(visitor))));
             // Theoretically, we'd need to instead pass lc to every setter and do a replacement on each. In practice,
             // setType from TypeOverride can't accept a lc, and we don't necessarily want to go there now.
@@ -248,7 +259,7 @@
      * Get the arguments for the call
      * @return a list of arguments
      */
-    public List<Node> getArgs() {
+    public List<Expression> getArgs() {
         return Collections.unmodifiableList(args);
     }
 
@@ -256,7 +267,7 @@
      * Reset the arguments for the call
      * @param args new arguments list
      */
-    private CallNode setArgs(final List<Node> args) {
+    private CallNode setArgs(final List<Expression> args) {
         if (this.args == args) {
             return this;
         }
@@ -297,7 +308,7 @@
      * Return the function expression that this call invokes
      * @return the function
      */
-    public Node getFunction() {
+    public Expression getFunction() {
         return function;
     }
 
@@ -306,7 +317,7 @@
      * @param function the function
      * @return same node or new one on state change
      */
-    public CallNode setFunction(final Node function) {
+    public CallNode setFunction(final Expression function) {
         if (this.function == function) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -36,7 +36,7 @@
 @Immutable
 public final class CaseNode extends Node {
     /** Test expression. */
-    private final Node test;
+    private final Expression test;
 
     /** Statements. */
     private final Block body;
@@ -52,7 +52,7 @@
      * @param test     case test node, can be any node in JavaScript
      * @param body     case body
      */
-    public CaseNode(final long token, final int finish, final Node test, final Block body) {
+    public CaseNode(final long token, final int finish, final Expression test, final Block body) {
         super(token, finish);
 
         this.test  = test;
@@ -60,7 +60,7 @@
         this.entry = new Label("entry");
     }
 
-    CaseNode(final CaseNode caseNode, final Node test, final Block body) {
+    CaseNode(final CaseNode caseNode, final Expression test, final Block body) {
         super(caseNode);
 
         this.test  = test;
@@ -80,7 +80,7 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterCaseNode(this)) {
-            final Node  newTest = test == null ? null : test.accept(visitor);
+            final Expression newTest = test == null ? null : (Expression)test.accept(visitor);
             final Block newBody = body == null ? null : (Block)body.accept(visitor);
 
             return visitor.leaveCaseNode(setTest(newTest).setBody(newBody));
@@ -120,7 +120,7 @@
      * Get the test expression for this case node
      * @return the test
      */
-    public Node getTest() {
+    public Expression getTest() {
         return test;
     }
 
@@ -129,7 +129,7 @@
      * @param test new test expression
      * @return new or same CaseNode
      */
-    public CaseNode setTest(final Node test) {
+    public CaseNode setTest(final Expression test) {
         if (this.test == test) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -37,7 +37,7 @@
     private final IdentNode exception;
 
     /** Exception condition. */
-    private final Node exceptionCondition;
+    private final Expression exceptionCondition;
 
     /** Catch body. */
     private final Block body;
@@ -58,7 +58,7 @@
      * @param body               catch body
      * @param flags              flags
      */
-    public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception, final Node exceptionCondition, final Block body, final int flags) {
+    public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception, final Expression exceptionCondition, final Block body, final int flags) {
         super(lineNumber, token, finish);
         this.exception          = exception;
         this.exceptionCondition = exceptionCondition;
@@ -66,7 +66,7 @@
         this.flags              = flags;
     }
 
-    private CatchNode(final CatchNode catchNode, final IdentNode exception, final Node exceptionCondition, final Block body, final int flags) {
+    private CatchNode(final CatchNode catchNode, final IdentNode exception, final Expression exceptionCondition, final Block body, final int flags) {
         super(catchNode);
         this.exception          = exception;
         this.exceptionCondition = exceptionCondition;
@@ -83,7 +83,7 @@
         if (visitor.enterCatchNode(this)) {
             return visitor.leaveCatchNode(
                 setException((IdentNode)exception.accept(visitor)).
-                setExceptionCondition(exceptionCondition == null ? null : exceptionCondition.accept(visitor)).
+                setExceptionCondition(exceptionCondition == null ? null : (Expression)exceptionCondition.accept(visitor)).
                 setBody((Block)body.accept(visitor)));
         }
 
@@ -119,7 +119,7 @@
      * Get the exception condition for this catch block
      * @return the exception condition
      */
-    public Node getExceptionCondition() {
+    public Expression getExceptionCondition() {
         return exceptionCondition;
     }
 
@@ -128,7 +128,7 @@
      * @param exceptionCondition the new exception condition
      * @return new or same CatchNode
      */
-    public CatchNode setExceptionCondition(final Node exceptionCondition) {
+    public CatchNode setExceptionCondition(final Expression exceptionCondition) {
         if (this.exceptionCondition == exceptionCondition) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/ExecuteNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.ir;
-
-import jdk.nashorn.internal.ir.annotations.Immutable;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-
-/**
- * IR representation for executing bare expressions. Basically, an expression
- * node means "this code will be executed" and evaluating it results in
- * statements being added to the IR
- */
-@Immutable
-public final class ExecuteNode extends Statement {
-    /** Expression to execute. */
-    private final Node expression;
-
-    /**
-     * Constructor
-     *
-     * @param lineNumber line number
-     * @param token      token
-     * @param finish     finish
-     * @param expression the expression to execute
-     */
-    public ExecuteNode(final int lineNumber, final long token, final int finish, final Node expression) {
-        super(lineNumber, token, finish);
-        this.expression = expression;
-    }
-
-    private ExecuteNode(final ExecuteNode executeNode, final Node expression) {
-        super(executeNode);
-        this.expression = expression;
-    }
-
-    @Override
-    public boolean isTerminal() {
-        return expression.isTerminal();
-    }
-
-    @Override
-    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
-        if (visitor.enterExecuteNode(this)) {
-            return visitor.leaveExecuteNode(setExpression(expression.accept(visitor)));
-        }
-
-        return this;
-    }
-
-    @Override
-    public void toString(final StringBuilder sb) {
-        expression.toString(sb);
-    }
-
-    /**
-     * Return the expression to be executed
-     * @return the expression
-     */
-    public Node getExpression() {
-        return expression;
-    }
-
-    /**
-     * Reset the expression to be executed
-     * @param expression the expression
-     * @return new or same execute node
-     */
-    public ExecuteNode setExpression(final Node expression) {
-        if (this.expression == expression) {
-            return this;
-        }
-        return new ExecuteNode(this, expression);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/ir/Expression.java	Thu Jul 11 18:33:33 2013 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * Common superclass for all expression nodes. Expression nodes can have
+ * an associated symbol as well as a type.
+ *
+ */
+public abstract class Expression extends Node {
+    private Symbol symbol;
+
+    Expression(long token, int start, int finish) {
+        super(token, start, finish);
+    }
+
+    Expression(long token, int finish) {
+        super(token, finish);
+    }
+
+    Expression(Expression expr) {
+        super(expr);
+        this.symbol = expr.symbol;
+    }
+
+    /**
+     * Return the Symbol the compiler has assigned to this Node. The symbol
+     * is the place where it's expression value is stored after evaluation
+     *
+     * @return the symbol
+     */
+    public Symbol getSymbol() {
+        return symbol;
+    }
+
+    /**
+     * Assign a symbol to this node. See {@link Expression#getSymbol()} for explanation
+     * of what a symbol is
+     *
+     * @param lc lexical context
+     * @param symbol the symbol
+     * @return new node
+     */
+    public Expression setSymbol(final LexicalContext lc, final Symbol symbol) {
+        if (this.symbol == symbol) {
+            return this;
+        }
+        final Expression newExpr = (Expression)clone();
+        newExpr.symbol = symbol;
+        return newExpr;
+    }
+
+    /**
+     * Check if the expression has a type. The default behavior is to go into the symbol
+     * and check the symbol type, but there may be overrides, for example in
+     * getters that require a different type than the internal representation
+     *
+     * @return true if a type exists
+     */
+    public boolean hasType() {
+        return getSymbol() != null;
+    }
+
+    /**
+     * Returns the type of the expression. Typically this is the symbol type. No types
+     * are stored in the expression itself, unless it implements TypeOverride.
+     *
+     * @return the type of the node.
+     */
+    public Type getType() {
+        assert hasType() : this + " has no type";
+        return symbol.getSymbolType();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/ir/ExpressionStatement.java	Thu Jul 11 18:33:33 2013 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.ir.annotations.Immutable;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * IR representation for executing bare expressions. Basically, an expression
+ * node means "this code will be executed" and evaluating it results in
+ * statements being added to the IR
+ */
+@Immutable
+public final class ExpressionStatement extends Statement {
+    /** Expression to execute. */
+    private final Expression expression;
+
+    /**
+     * Constructor
+     *
+     * @param lineNumber line number
+     * @param token      token
+     * @param finish     finish
+     * @param expression the expression to execute
+     */
+    public ExpressionStatement(final int lineNumber, final long token, final int finish, final Expression expression) {
+        super(lineNumber, token, finish);
+        this.expression = expression;
+    }
+
+    private ExpressionStatement(final ExpressionStatement expressionStatement, final Expression expression) {
+        super(expressionStatement);
+        this.expression = expression;
+    }
+
+    @Override
+    public boolean isTerminal() {
+        return expression.isTerminal();
+    }
+
+    @Override
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        if (visitor.enterExpressionStatement(this)) {
+            return visitor.leaveExpressionStatement(setExpression((Expression)expression.accept(visitor)));
+        }
+
+        return this;
+    }
+
+    @Override
+    public void toString(final StringBuilder sb) {
+        expression.toString(sb);
+    }
+
+    /**
+     * Return the expression to be executed
+     * @return the expression
+     */
+    public Expression getExpression() {
+        return expression;
+    }
+
+    /**
+     * Reset the expression to be executed
+     * @param expression the expression
+     * @return new or same execute node
+     */
+    public ExpressionStatement setExpression(final Expression expression) {
+        if (this.expression == expression) {
+            return this;
+        }
+        return new ExpressionStatement(this, expression);
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/ir/ForNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/ForNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -34,10 +34,10 @@
 @Immutable
 public final class ForNode extends LoopNode {
     /** Initialize expression. */
-    private final Node init;
+    private final Expression init;
 
     /** Test expression. */
-    private final Node modify;
+    private final Expression modify;
 
     /** Iterator symbol. */
     private Symbol iterator;
@@ -65,14 +65,14 @@
      * @param modify     modify
      * @param flags      flags
      */
-    public ForNode(final int lineNumber, final long token, final int finish, final Node init, final Node test, final Block body, final Node modify, final int flags) {
+    public ForNode(final int lineNumber, final long token, final int finish, final Expression init, final Expression test, final Block body, final Expression modify, final int flags) {
         super(lineNumber, token, finish, test, body, false);
         this.init   = init;
         this.modify = modify;
         this.flags  = flags;
     }
 
-    private ForNode(final ForNode forNode, final Node init, final Node test, final Block body, final Node modify, final int flags, final boolean controlFlowEscapes) {
+    private ForNode(final ForNode forNode, final Expression init, final Expression test, final Block body, final Expression modify, final int flags, final boolean controlFlowEscapes) {
         super(forNode, test, body, controlFlowEscapes);
         this.init   = init;
         this.modify = modify;
@@ -86,12 +86,12 @@
     }
 
     @Override
-    protected Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterForNode(this)) {
             return visitor.leaveForNode(
-                setInit(lc, init == null ? null : init.accept(visitor)).
-                setTest(lc, test == null ? null : test.accept(visitor)).
-                setModify(lc, modify == null ? null : modify.accept(visitor)).
+                setInit(lc, init == null ? null : (Expression)init.accept(visitor)).
+                setTest(lc, test == null ? null : (Expression)test.accept(visitor)).
+                setModify(lc, modify == null ? null : (Expression)modify.accept(visitor)).
                 setBody(lc, (Block)body.accept(visitor)));
         }
 
@@ -140,7 +140,7 @@
      * Get the initialization expression for this for loop
      * @return the initialization expression
      */
-    public Node getInit() {
+    public Expression getInit() {
         return init;
     }
 
@@ -150,7 +150,7 @@
      * @param init new initialization expression
      * @return new for node if changed or existing if not
      */
-    public ForNode setInit(final LexicalContext lc, final Node init) {
+    public ForNode setInit(final LexicalContext lc, final Expression init) {
         if (this.init == init) {
             return this;
         }
@@ -212,7 +212,7 @@
      * Get the modification expression for this ForNode
      * @return the modification expression
      */
-    public Node getModify() {
+    public Expression getModify() {
         return modify;
     }
 
@@ -222,7 +222,7 @@
      * @param modify new modification expression
      * @return new for node if changed or existing if not
      */
-    public ForNode setModify(final LexicalContext lc, final Node modify) {
+    public ForNode setModify(final LexicalContext lc, final Expression modify) {
         if (this.modify == modify) {
             return this;
         }
@@ -230,12 +230,12 @@
     }
 
     @Override
-    public Node getTest() {
+    public Expression getTest() {
         return test;
     }
 
     @Override
-    public ForNode setTest(final LexicalContext lc, final Node test) {
+    public ForNode setTest(final LexicalContext lc, final Expression test) {
         if (this.test == test) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -47,7 +47,7 @@
  * IR representation for function (or script.)
  */
 @Immutable
-public final class FunctionNode extends LexicalContextNode implements Flags<FunctionNode> {
+public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode> {
 
     /** Type used for all FunctionNodes */
     public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
@@ -138,6 +138,8 @@
     /** Function flags. */
     private final int flags;
 
+    private final int lineNumber;
+
     /** Is anonymous function flag. */
     public static final int IS_ANONYMOUS                = 1 << 0;
 
@@ -234,9 +236,10 @@
         final List<IdentNode> parameters,
         final FunctionNode.Kind kind,
         final int flags) {
-        super(lineNumber, token, finish);
+        super(token, finish);
 
         this.source           = source;
+        this.lineNumber       = lineNumber;
         this.ident            = ident;
         this.name             = name;
         this.kind             = kind;
@@ -266,7 +269,7 @@
         final FunctionNode snapshot,
         final Compiler.Hints hints) {
         super(functionNode);
-
+        this.lineNumber       = functionNode.lineNumber;
         this.flags            = flags;
         this.name             = name;
         this.returnType       = returnType;
@@ -305,6 +308,14 @@
     }
 
     /**
+     * Returns the line number.
+     * @return the line number.
+     */
+    public int getLineNumber() {
+        return lineNumber;
+    }
+
+    /**
      * Get the version of this function node's code as it looked upon construction
      * i.e typically parsed and nothing else
      * @return initial version of function node
--- a/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -29,6 +29,7 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__;
 import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__;
 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
+
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -38,7 +39,7 @@
  * IR representation for an identifier.
  */
 @Immutable
-public final class IdentNode extends Node implements PropertyKey, TypeOverride<IdentNode>, FunctionCall {
+public final class IdentNode extends Expression implements PropertyKey, TypeOverride<IdentNode>, FunctionCall {
     private static final int PROPERTY_NAME    = 1 << 0;
     private static final int INITIALIZED_HERE = 1 << 1;
     private static final int FUNCTION         = 1 << 2;
--- a/nashorn/src/jdk/nashorn/internal/ir/IfNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/IfNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -34,7 +34,7 @@
 @Immutable
 public final class IfNode extends Statement {
     /** Test expression. */
-    private final Node test;
+    private final Expression test;
 
     /** Pass statements. */
     private final Block pass;
@@ -52,14 +52,14 @@
      * @param pass       block to execute when test passes
      * @param fail       block to execute when test fails or null
      */
-    public IfNode(final int lineNumber, final long token, final int finish, final Node test, final Block pass, final Block fail) {
+    public IfNode(final int lineNumber, final long token, final int finish, final Expression test, final Block pass, final Block fail) {
         super(lineNumber, token, finish);
         this.test = test;
         this.pass = pass;
         this.fail = fail;
     }
 
-    private IfNode(final IfNode ifNode, final Node test, final Block pass, final Block fail) {
+    private IfNode(final IfNode ifNode, final Expression test, final Block pass, final Block fail) {
         super(ifNode);
         this.test = test;
         this.pass = pass;
@@ -75,7 +75,7 @@
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterIfNode(this)) {
             return visitor.leaveIfNode(
-                setTest(test.accept(visitor)).
+                setTest((Expression)test.accept(visitor)).
                 setPass((Block)pass.accept(visitor)).
                 setFail(fail == null ? null : (Block)fail.accept(visitor)));
         }
@@ -124,7 +124,7 @@
      * Get the test expression for this IfNode
      * @return the test expression
      */
-    public Node getTest() {
+    public Expression getTest() {
         return test;
     }
 
@@ -133,7 +133,7 @@
      * @param test a new test expression
      * @return new or same IfNode
      */
-    public IfNode setTest(final Node test) {
+    public IfNode setTest(final Expression test) {
         if (this.test == test) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -35,7 +35,7 @@
 @Immutable
 public final class IndexNode extends BaseNode {
     /** Property index. */
-    private final Node index;
+    private final Expression index;
 
     /**
      * Constructors
@@ -45,12 +45,12 @@
      * @param base    base node for access
      * @param index   index for access
      */
-    public IndexNode(final long token, final int finish, final Node base, final Node index) {
+    public IndexNode(final long token, final int finish, final Expression base, final Expression index) {
         super(token, finish, base, false, false);
         this.index = index;
     }
 
-    private IndexNode(final IndexNode indexNode, final Node base, final Node index, final boolean isFunction, final boolean hasCallSiteType) {
+    private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction, final boolean hasCallSiteType) {
         super(indexNode, base, isFunction, hasCallSiteType);
         this.index = index;
     }
@@ -59,8 +59,8 @@
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterIndexNode(this)) {
             return visitor.leaveIndexNode(
-                setBase(base.accept(visitor)).
-                setIndex(index.accept(visitor)));
+                setBase((Expression)base.accept(visitor)).
+                setIndex((Expression)index.accept(visitor)));
         }
         return this;
     }
@@ -95,11 +95,11 @@
      * Get the index expression for this IndexNode
      * @return the index
      */
-    public Node getIndex() {
+    public Expression getIndex() {
         return index;
     }
 
-    private IndexNode setBase(final Node base) {
+    private IndexNode setBase(final Expression base) {
         if (this.base == base) {
             return this;
         }
@@ -111,7 +111,7 @@
      * @param index new index expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public IndexNode setIndex(Node index) {
+    public IndexNode setIndex(Expression index) {
         if(this.index == index) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -32,7 +32,7 @@
  * IR representation for a labeled statement.
  */
 @Immutable
-public final class LabelNode extends LexicalContextNode {
+public final class LabelNode extends LexicalContextStatement {
     /** Label ident. */
     private final IdentNode label;
 
--- a/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java	Thu Jul 11 18:33:33 2013 +0200
@@ -576,19 +576,20 @@
         final StringBuffer sb = new StringBuffer();
         sb.append("[ ");
         for (int i = 0; i < sp; i++) {
-            final Node node = stack[i];
+            final Object node = stack[i];
             sb.append(node.getClass().getSimpleName());
             sb.append('@');
             sb.append(Debug.id(node));
             sb.append(':');
             if (node instanceof FunctionNode) {
-                final Source source = ((FunctionNode)node).getSource();
+                final FunctionNode fn = (FunctionNode)node;
+                final Source source = fn.getSource();
                 String src = source.toString();
                 if (src.indexOf(File.pathSeparator) != -1) {
                     src = src.substring(src.lastIndexOf(File.pathSeparator));
                 }
                 src += ' ';
-                src += source.getLine(node.getStart());
+                src += source.getLine(fn.getStart());
                 sb.append(src);
             }
             sb.append(' ');
@@ -631,7 +632,7 @@
 
         private T findNext() {
             for (int i = index; i >= 0; i--) {
-                final Node node = stack[i];
+                final Object node = stack[i];
                 if (node == until) {
                     return null;
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContextExpression.java	Thu Jul 11 18:33:33 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+abstract class LexicalContextExpression extends Expression implements LexicalContextNode {
+
+    LexicalContextExpression(LexicalContextExpression expr) {
+        super(expr);
+    }
+
+    LexicalContextExpression(long token, int start, int finish) {
+        super(token, start, finish);
+    }
+
+    LexicalContextExpression(long token, int finish) {
+        super(token, finish);
+    }
+
+    @Override
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        return Acceptor.accept(this, visitor);
+    }
+
+    /**
+     * Set the symbol and replace in lexical context if applicable
+     * @param lc     lexical context
+     * @param symbol symbol
+     * @return new node if symbol changed
+     */
+    @Override
+    public Expression setSymbol(final LexicalContext lc, final Symbol symbol) {
+        return Node.replaceInLexicalContext(lc, this, (LexicalContextExpression)super.setSymbol(null, symbol));
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -26,31 +26,12 @@
 
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
+
 /**
- * Superclass for nodes that can be part of the lexical context
+ * Interface for nodes that can be part of the lexical context.
  * @see LexicalContext
  */
-public abstract class LexicalContextNode extends Statement {
-    /**
-     * Constructor
-     *
-     * @param lineNumber line number
-     * @param token      token
-     * @param finish     finish
-     */
-    protected LexicalContextNode(final int lineNumber, final long token, final int finish) {
-        super(lineNumber, token, finish);
-    }
-
-    /**
-     * Copy constructor
-     *
-     * @param node source node
-     */
-    protected LexicalContextNode(final LexicalContextNode node) {
-        super(node);
-    }
-
+public interface LexicalContextNode {
     /**
      * Accept function for the node given a lexical context. It must be prepared
      * to replace itself if present in the lexical context
@@ -60,25 +41,15 @@
      *
      * @return new node or same node depending on state change
      */
-    protected abstract Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor);
-
-    @Override
-    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
-        final LexicalContext lc = visitor.getLexicalContext();
-        lc.push(this);
-        final LexicalContextNode newNode = (LexicalContextNode)accept(lc, visitor);
-        return lc.pop(newNode);
-    }
+    Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor);
 
-    /**
-     * Set the symbol and replace in lexical context if applicable
-     * @param lc     lexical context
-     * @param symbol symbol
-     * @return new node if symbol changed
-     */
-    @Override
-    public Node setSymbol(final LexicalContext lc, final Symbol symbol) {
-        return Node.replaceInLexicalContext(lc, this, (LexicalContextNode)super.setSymbol(null, symbol));
+    // Would be a default method on Java 8
+    static class Acceptor {
+        static Node accept(LexicalContextNode node, final NodeVisitor<? extends LexicalContext> visitor) {
+            final LexicalContext lc = visitor.getLexicalContext();
+            lc.push(node);
+            final LexicalContextNode newNode = (LexicalContextNode)node.accept(lc, visitor);
+            return (Node)lc.pop(newNode);
+        }
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContextStatement.java	Thu Jul 11 18:33:33 2013 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+abstract class LexicalContextStatement extends Statement implements LexicalContextNode {
+    /**
+     * Constructor
+     *
+     * @param lineNumber line number
+     * @param token      token
+     * @param finish     finish
+     */
+    protected LexicalContextStatement(final int lineNumber, final long token, final int finish) {
+        super(lineNumber, token, finish);
+    }
+
+    /**
+     * Copy constructor
+     *
+     * @param node source node
+     */
+    protected LexicalContextStatement(final LexicalContextStatement node) {
+        super(node);
+    }
+
+    @Override
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        return Acceptor.accept(this, visitor);
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -45,7 +45,7 @@
  * @param <T> the literal type
  */
 @Immutable
-public abstract class LiteralNode<T> extends Node implements PropertyKey {
+public abstract class LiteralNode<T> extends Expression implements PropertyKey {
     /** Literal value */
     protected final T value;
 
@@ -551,7 +551,7 @@
     /**
      * Array literal node class.
      */
-    public static final class ArrayLiteralNode extends LiteralNode<Node[]> {
+    public static final class ArrayLiteralNode extends LiteralNode<Expression[]> {
 
         /** Array element type. */
         private Type elementType;
@@ -619,7 +619,7 @@
          * @param finish  finish
          * @param value   array literal value, a Node array
          */
-        protected ArrayLiteralNode(final long token, final int finish, final Node[] value) {
+        protected ArrayLiteralNode(final long token, final int finish, final Expression[] value) {
             super(Token.recast(token, TokenType.ARRAY), finish, value);
             this.elementType = Type.UNKNOWN;
         }
@@ -628,7 +628,7 @@
          * Copy constructor
          * @param node source array literal node
          */
-        private ArrayLiteralNode(final ArrayLiteralNode node, final Node[] value) {
+        private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value) {
             super(node, value);
             this.elementType = node.elementType;
             this.presets     = node.presets;
@@ -737,7 +737,7 @@
         }
 
         private void analyzeElements() {
-            for (final Node node : value) {
+            for (final Expression node : value) {
                 if (node == null) {
                     elementType = elementType.widest(Type.OBJECT); //no way to represent undefined as number
                     break;
@@ -826,15 +826,15 @@
         @Override
         public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
             if (visitor.enterLiteralNode(this)) {
-                final List<Node> oldValue = Arrays.asList(value);
-                final List<Node> newValue = Node.accept(visitor, Node.class, oldValue);
+                final List<Expression> oldValue = Arrays.asList(value);
+                final List<Expression> newValue = Node.accept(visitor, Expression.class, oldValue);
                 return visitor.leaveLiteralNode(oldValue != newValue ? setValue(newValue) : this);
             }
             return this;
         }
 
-        private ArrayLiteralNode setValue(final List<Node> value) {
-            return new ArrayLiteralNode(this, value.toArray(new Node[value.size()]));
+        private ArrayLiteralNode setValue(final List<Expression> value) {
+            return new ArrayLiteralNode(this, value.toArray(new Expression[value.size()]));
         }
 
         @Override
@@ -866,8 +866,8 @@
      *
      * @return the new literal node
      */
-    public static LiteralNode<Node[]> newInstance(final long token, final int finish, final List<Node> value) {
-        return new ArrayLiteralNode(token, finish, value.toArray(new Node[value.size()]));
+    public static LiteralNode<Expression[]> newInstance(final long token, final int finish, final List<Expression> value) {
+        return new ArrayLiteralNode(token, finish, value.toArray(new Expression[value.size()]));
     }
 
 
@@ -879,8 +879,8 @@
      *
      * @return the new literal node
      */
-    public static LiteralNode<?> newInstance(final Node parent, final List<Node> value) {
-        return new ArrayLiteralNode(parent.getToken(), parent.getFinish(), value.toArray(new Node[value.size()]));
+    public static LiteralNode<?> newInstance(final Node parent, final List<Expression> value) {
+        return new ArrayLiteralNode(parent.getToken(), parent.getFinish(), value.toArray(new Expression[value.size()]));
     }
 
     /**
@@ -892,7 +892,7 @@
      *
      * @return the new literal node
      */
-    public static LiteralNode<Node[]> newInstance(final long token, final int finish, final Node[] value) {
+    public static LiteralNode<Expression[]> newInstance(final long token, final int finish, final Expression[] value) {
         return new ArrayLiteralNode(token, finish, value);
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/ir/LoopNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/LoopNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -27,18 +27,17 @@
 
 import java.util.Arrays;
 import java.util.List;
-
 import jdk.nashorn.internal.codegen.Label;
 
 /**
  * A loop node, for example a while node, do while node or for node
  */
-public abstract class LoopNode extends BreakableNode {
+public abstract class LoopNode extends BreakableStatement {
     /** loop continue label. */
     protected final Label continueLabel;
 
     /** Loop test node, null if infinite */
-    protected final Node test;
+    protected final Expression test;
 
     /** Loop body */
     protected final Block body;
@@ -56,7 +55,7 @@
      * @param body               loop body
      * @param controlFlowEscapes controlFlowEscapes
      */
-    protected LoopNode(final int lineNumber, final long token, final int finish, final Node test, final Block body, final boolean controlFlowEscapes) {
+    protected LoopNode(final int lineNumber, final long token, final int finish, final Expression test, final Block body, final boolean controlFlowEscapes) {
         super(lineNumber, token, finish, new Label("while_break"));
         this.continueLabel = new Label("while_continue");
         this.test = test;
@@ -72,7 +71,7 @@
      * @param body     new body
      * @param controlFlowEscapes controlFlowEscapes
      */
-    protected LoopNode(final LoopNode loopNode, final Node test, final Block body, final boolean controlFlowEscapes) {
+    protected LoopNode(final LoopNode loopNode, final Expression test, final Block body, final boolean controlFlowEscapes) {
         super(loopNode);
         this.continueLabel = new Label(loopNode.continueLabel);
         this.test = test;
@@ -151,7 +150,7 @@
      * Get the test for this for node
      * @return the test
      */
-    public abstract Node getTest();
+    public abstract Expression getTest();
 
     /**
      * Set the test for this for node
@@ -160,7 +159,7 @@
      * @param test new test
      * @return same or new node depending on if test was changed
      */
-    public abstract LoopNode setTest(final LexicalContext lc, final Node test);
+    public abstract LoopNode setTest(final LexicalContext lc, final Expression test);
 
     /**
      * Set the control flow escapes flag for this node.
--- a/nashorn/src/jdk/nashorn/internal/ir/Node.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/Node.java	Thu Jul 11 18:33:33 2013 +0200
@@ -27,7 +27,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.Token;
@@ -37,9 +36,6 @@
  * Nodes are used to compose Abstract Syntax Trees.
  */
 public abstract class Node implements Cloneable {
-    /** Node symbol. */
-    private Symbol symbol;
-
     /** Start of source range. */
     protected final int start;
 
@@ -81,34 +77,11 @@
      */
     protected Node(final Node node) {
         this.token  = node.token;
-        this.symbol = node.symbol;
         this.start  = node.start;
         this.finish = node.finish;
     }
 
     /**
-     * Check if the node has a type. The default behavior is to go into the symbol
-     * and check the symbol type, but there may be overrides, for example in
-     * getters that require a different type than the internal representation
-     *
-     * @return true if a type exists
-     */
-    public boolean hasType() {
-        return getSymbol() != null;
-    }
-
-    /**
-     * Returns the type of the node. Typically this is the symbol type. No types
-     * are stored in the node itself, unless it implements TypeOverride
-     *
-     * @return the type of the node.
-     */
-    public Type getType() {
-        assert hasType() : this + " has no type";
-        return symbol.getSymbolType();
-    }
-
-    /**
      * Is this an atom node - for example a literal or an identity
      *
      * @return true if atom
@@ -235,16 +208,6 @@
         return start;
     }
 
-    /**
-     * Return the Symbol the compiler has assigned to this Node. The symbol
-     * is the place where it's expression value is stored after evaluation
-     *
-     * @return the symbol
-     */
-    public Symbol getSymbol() {
-        return symbol;
-    }
-
     @Override
     protected Object clone() {
         try {
@@ -254,24 +217,6 @@
         }
     }
 
-    /**
-     * Assign a symbol to this node. See {@link Node#getSymbol()} for explanation
-     * of what a symbol is
-     *
-     * @param lc lexical context
-     * @param symbol the symbol
-     * @return new node
-     */
-    public Node setSymbol(final LexicalContext lc, final Symbol symbol) {
-        if (this.symbol == symbol) {
-            return this;
-        }
-        final Node newNode = (Node)clone();
-        newNode.symbol = symbol;
-        return newNode;
-    }
-
-
     @Override
     public final boolean equals(final Object other) {
         return super.equals(other);
--- a/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -34,7 +34,7 @@
  * IR representation of an object literal.
  */
 @Immutable
-public final class ObjectNode extends Node {
+public final class ObjectNode extends Expression {
 
     /** Literal elements. */
     private final List<PropertyNode> elements;
--- a/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -38,7 +38,7 @@
     private final PropertyKey key;
 
     /** Property value. */
-    private final Node value;
+    private final Expression value;
 
     /** Property getter. */
     private final FunctionNode getter;
@@ -56,7 +56,7 @@
      * @param getter  getter function body
      * @param setter  setter function body
      */
-    public PropertyNode(final long token, final int finish, final PropertyKey key, final Node value, final FunctionNode getter, final FunctionNode setter) {
+    public PropertyNode(final long token, final int finish, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) {
         super(token, finish);
         this.key    = key;
         this.value  = value;
@@ -64,7 +64,7 @@
         this.setter = setter;
     }
 
-    private PropertyNode(final PropertyNode propertyNode, final PropertyKey key, final Node value, final FunctionNode getter, final FunctionNode setter) {
+    private PropertyNode(final PropertyNode propertyNode, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) {
         super(propertyNode);
         this.key    = key;
         this.value  = value;
@@ -85,7 +85,7 @@
         if (visitor.enterPropertyNode(this)) {
             return visitor.leavePropertyNode(
                 setKey((PropertyKey)((Node)key).accept(visitor)).
-                setValue(value == null ? null : value.accept(visitor)).
+                setValue(value == null ? null : (Expression)value.accept(visitor)).
                 setGetter(getter == null ? null : (FunctionNode)getter.accept(visitor)).
                 setSetter(setter == null ? null : (FunctionNode)setter.accept(visitor)));
         }
@@ -140,8 +140,8 @@
      * Return the key for this property node
      * @return the key
      */
-    public Node getKey() {
-        return (Node)key;
+    public Expression getKey() {
+        return (Expression)key;
     }
 
     private PropertyNode setKey(final PropertyKey key) {
@@ -175,7 +175,7 @@
      * Get the value of this property
      * @return property value
      */
-    public Node getValue() {
+    public Expression getValue() {
         return value;
     }
 
@@ -184,7 +184,7 @@
      * @param value new value
      * @return same node or new node if state changed
      */
-    public PropertyNode setValue(final Node value) {
+    public PropertyNode setValue(final Expression value) {
         if (this.value == value) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -27,6 +27,7 @@
 
 import static jdk.nashorn.internal.parser.TokenType.RETURN;
 import static jdk.nashorn.internal.parser.TokenType.YIELD;
+
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -36,7 +37,7 @@
 @Immutable
 public class ReturnNode extends Statement {
     /** Optional expression. */
-    private final Node expression;
+    private final Expression expression;
 
     /**
      * Constructor
@@ -46,12 +47,12 @@
      * @param finish     finish
      * @param expression expression to return
      */
-    public ReturnNode(final int lineNumber, final long token, final int finish, final Node expression) {
+    public ReturnNode(final int lineNumber, final long token, final int finish, final Expression expression) {
         super(lineNumber, token, finish);
         this.expression = expression;
     }
 
-    private ReturnNode(final ReturnNode returnNode, final Node expression) {
+    private ReturnNode(final ReturnNode returnNode, final Expression expression) {
         super(returnNode);
         this.expression = expression;
     }
@@ -89,7 +90,7 @@
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterReturnNode(this)) {
             if (expression != null) {
-                return visitor.leaveReturnNode(setExpression(expression.accept(visitor)));
+                return visitor.leaveReturnNode(setExpression((Expression)expression.accept(visitor)));
             }
             return visitor.leaveReturnNode(this);
         }
@@ -111,7 +112,7 @@
      * Get the expression this node returns
      * @return return expression, or null if void return
      */
-    public Node getExpression() {
+    public Expression getExpression() {
         return expression;
     }
 
@@ -120,7 +121,7 @@
      * @param expression new expression, or null if void return
      * @return new or same return node
      */
-    public ReturnNode setExpression(final Node expression) {
+    public ReturnNode setExpression(final Expression expression) {
         if (this.expression == expression) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -29,7 +29,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -39,7 +38,7 @@
  * IR representation for a runtime call.
  */
 @Immutable
-public class RuntimeNode extends Node implements TypeOverride<RuntimeNode> {
+public class RuntimeNode extends Expression implements TypeOverride<RuntimeNode> {
 
     /**
      * Request enum used for meta-information about the runtime request
@@ -267,7 +266,7 @@
     private final Request request;
 
     /** Call arguments. */
-    private final List<Node> args;
+    private final List<Expression> args;
 
     /** Call site override - e.g. we know that a ScriptRuntime.ADD will return an int */
     private final Type callSiteType;
@@ -283,7 +282,7 @@
      * @param request the request
      * @param args    arguments to request
      */
-    public RuntimeNode(final long token, final int finish, final Request request, final List<Node> args) {
+    public RuntimeNode(final long token, final int finish, final Request request, final List<Expression> args) {
         super(token, finish);
 
         this.request      = request;
@@ -292,7 +291,7 @@
         this.isFinal      = false;
     }
 
-    private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final Type callSiteType, final boolean isFinal, final List<Node> args) {
+    private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final Type callSiteType, final boolean isFinal, final List<Expression> args) {
         super(runtimeNode);
 
         this.request      = request;
@@ -309,7 +308,7 @@
      * @param request the request
      * @param args    arguments to request
      */
-    public RuntimeNode(final long token, final int finish, final Request request, final Node... args) {
+    public RuntimeNode(final long token, final int finish, final Request request, final Expression... args) {
         this(token, finish, request, Arrays.asList(args));
     }
 
@@ -320,7 +319,7 @@
      * @param request the request
      * @param args    arguments to request
      */
-    public RuntimeNode(final Node parent, final Request request, final Node... args) {
+    public RuntimeNode(final Expression parent, final Request request, final Expression... args) {
         this(parent, request, Arrays.asList(args));
     }
 
@@ -331,7 +330,7 @@
      * @param request the request
      * @param args    arguments to request
      */
-    public RuntimeNode(final Node parent, final Request request, final List<Node> args) {
+    public RuntimeNode(final Expression parent, final Request request, final List<Expression> args) {
         super(parent);
 
         this.request      = request;
@@ -408,9 +407,9 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterRuntimeNode(this)) {
-            final List<Node> newArgs = new ArrayList<>();
+            final List<Expression> newArgs = new ArrayList<>();
             for (final Node arg : args) {
-                newArgs.add(arg.accept(visitor));
+                newArgs.add((Expression)arg.accept(visitor));
             }
             return visitor.leaveRuntimeNode(setArgs(newArgs));
         }
@@ -443,11 +442,11 @@
      * Get the arguments for this runtime node
      * @return argument list
      */
-    public List<Node> getArgs() {
+    public List<Expression> getArgs() {
         return Collections.unmodifiableList(args);
     }
 
-    private RuntimeNode setArgs(final List<Node> args) {
+    private RuntimeNode setArgs(final List<Expression> args) {
         if (this.args == args) {
             return this;
         }
@@ -470,7 +469,7 @@
      * @return true if all arguments now are primitive
      */
     public boolean isPrimitive() {
-        for (final Node arg : args) {
+        for (final Expression arg : args) {
             if (arg.getType().isObject()) {
                 return false;
             }
--- a/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -33,7 +33,7 @@
  * Node indicating code is split across classes.
  */
 @Immutable
-public class SplitNode extends LexicalContextNode {
+public class SplitNode extends LexicalContextStatement {
     /** Split node method name. */
     private final String name;
 
@@ -46,13 +46,12 @@
     /**
      * Constructor
      *
-     * @param lineNumber  lineNumber
      * @param name        name of split node
      * @param body        body of split code
      * @param compileUnit compile unit to use for the body
      */
-    public SplitNode(final int lineNumber, final String name, final Node body, final CompileUnit compileUnit) {
-        super(lineNumber, body.getToken(), body.getFinish());
+    public SplitNode(final String name, final Node body, final CompileUnit compileUnit) {
+        super(-1, body.getToken(), body.getFinish());
         this.name        = name;
         this.body        = body;
         this.compileUnit = compileUnit;
--- a/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -28,7 +28,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-
 import jdk.nashorn.internal.codegen.Label;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -37,9 +36,9 @@
  * IR representation of a SWITCH statement.
  */
 @Immutable
-public final class SwitchNode extends BreakableNode {
+public final class SwitchNode extends BreakableStatement {
     /** Switch expression. */
-    private final Node expression;
+    private final Expression expression;
 
     /** Switch cases. */
     private final List<CaseNode> cases;
@@ -60,14 +59,14 @@
      * @param cases       cases
      * @param defaultCase the default case node - null if none, otherwise has to be present in cases list
      */
-    public SwitchNode(final int lineNumber, final long token, final int finish, final Node expression, final List<CaseNode> cases, final CaseNode defaultCase) {
+    public SwitchNode(final int lineNumber, final long token, final int finish, final Expression expression, final List<CaseNode> cases, final CaseNode defaultCase) {
         super(lineNumber, token, finish, new Label("switch_break"));
         this.expression       = expression;
         this.cases            = cases;
         this.defaultCaseIndex = defaultCase == null ? -1 : cases.indexOf(defaultCase);
     }
 
-    private SwitchNode(final SwitchNode switchNode, final Node expression, final List<CaseNode> cases, final int defaultCase) {
+    private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases, final int defaultCase) {
         super(switchNode);
         this.expression       = expression;
         this.cases            = cases;
@@ -103,7 +102,7 @@
     public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterSwitchNode(this)) {
             return visitor.leaveSwitchNode(
-                setExpression(lc, expression.accept(visitor)).
+                setExpression(lc, (Expression)expression.accept(visitor)).
                 setCases(lc, Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex));
         }
 
@@ -167,7 +166,7 @@
      * Return the expression to switch on
      * @return switch expression
      */
-    public Node getExpression() {
+    public Expression getExpression() {
         return expression;
     }
 
@@ -177,7 +176,7 @@
      * @param expression switch expression
      * @return new switch node or same if no state was changed
      */
-    public SwitchNode setExpression(final LexicalContext lc, final Node expression) {
+    public SwitchNode setExpression(final LexicalContext lc, final Expression expression) {
         if (this.expression == expression) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/TemporarySymbols.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/TemporarySymbols.java	Thu Jul 11 18:33:33 2013 +0200
@@ -49,7 +49,7 @@
      * @param node the node
      * @return the node that is guaranteed to have a symbol.
      */
-    public Node ensureSymbol(final LexicalContext lc, final Type type, final Node node) {
+    public Expression ensureSymbol(final LexicalContext lc, final Type type, final Expression node) {
         final Symbol symbol = node.getSymbol();
         if (symbol != null) {
             return node;
--- a/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -32,43 +32,43 @@
  * TernaryNode nodes represent three operand operations (?:).
  */
 @Immutable
-public final class TernaryNode extends Node {
-    private final Node lhs;
+public final class TernaryNode extends Expression {
+    private final Expression test;
 
-    private final Node rhs;
+    private final Expression trueExpr;
 
     /** Third argument. */
-    private final Node third;
+    private final Expression falseExpr;
 
     /**
      * Constructor
      *
-     * @param token  token
-     * @param lhs    left hand side node
-     * @param rhs    right hand side node
-     * @param third  third node
+     * @param token     token
+     * @param test      test expression
+     * @param trueExpr  expression evaluated when test evaluates to true
+     * @param falseExpr expression evaluated when test evaluates to true
      */
-    public TernaryNode(final long token, final Node lhs, final Node rhs, final Node third) {
-        super(token, third.getFinish());
-        this.lhs = lhs;
-        this.rhs = rhs;
-        this.third = third;
+    public TernaryNode(final long token, final Expression test, final Expression trueExpr, final Expression falseExpr) {
+        super(token, falseExpr.getFinish());
+        this.test = test;
+        this.trueExpr = trueExpr;
+        this.falseExpr = falseExpr;
     }
 
-    private TernaryNode(final TernaryNode ternaryNode, final Node lhs, final Node rhs, final Node third) {
+    private TernaryNode(final TernaryNode ternaryNode, final Expression test, final Expression trueExpr, final Expression falseExpr) {
         super(ternaryNode);
-        this.lhs = lhs;
-        this.rhs = rhs;
-        this.third = third;
+        this.test = test;
+        this.trueExpr = trueExpr;
+        this.falseExpr = falseExpr;
     }
 
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterTernaryNode(this)) {
-            final Node newLhs = lhs().accept(visitor);
-            final Node newRhs = rhs().accept(visitor);
-            final Node newThird = third.accept(visitor);
-            return visitor.leaveTernaryNode(setThird(newThird).setLHS(newLhs).setRHS(newRhs));
+            final Expression newTest = (Expression)getTest().accept(visitor);
+            final Expression newTrueExpr = (Expression)getTrueExpression().accept(visitor);
+            final Expression newFalseExpr = (Expression)falseExpr.accept(visitor);
+            return visitor.leaveTernaryNode(setTest(newTest).setTrueExpression(newTrueExpr).setFalseExpression1(newFalseExpr));
         }
 
         return this;
@@ -76,96 +76,96 @@
 
     @Override
     public void toString(final StringBuilder sb) {
-        final boolean lhsParen   = tokenType().needsParens(lhs().tokenType(), true);
-        final boolean rhsParen   = tokenType().needsParens(rhs().tokenType(), false);
-        final boolean thirdParen = tokenType().needsParens(third().tokenType(), false);
+        final boolean testParen  = tokenType().needsParens(getTest().tokenType(), true);
+        final boolean trueParen  = tokenType().needsParens(getTrueExpression().tokenType(), false);
+        final boolean falseParen = tokenType().needsParens(getFalseExpression().tokenType(), false);
 
-        if (lhsParen) {
+        if (testParen) {
             sb.append('(');
         }
-        lhs().toString(sb);
-        if (lhsParen) {
+        getTest().toString(sb);
+        if (testParen) {
             sb.append(')');
         }
 
         sb.append(" ? ");
 
-        if (rhsParen) {
+        if (trueParen) {
             sb.append('(');
         }
-        rhs().toString(sb);
-        if (rhsParen) {
+        getTrueExpression().toString(sb);
+        if (trueParen) {
             sb.append(')');
         }
 
         sb.append(" : ");
 
-        if (thirdParen) {
+        if (falseParen) {
             sb.append('(');
         }
-        third().toString(sb);
-        if (thirdParen) {
+        getFalseExpression().toString(sb);
+        if (falseParen) {
             sb.append(')');
         }
     }
 
     /**
-     * Get the lhs node for this ternary expression, i.e. "x" in x ? y : z
-     * @return a node
+     * Get the test expression for this ternary expression, i.e. "x" in x ? y : z
+     * @return the test expression
      */
-    public Node lhs() {
-        return lhs;
+    public Expression getTest() {
+        return test;
     }
 
     /**
-     * Get the rhs node for this ternary expression, i.e. "y" in x ? y : z
-     * @return a node
+     * Get the true expression for this ternary expression, i.e. "y" in x ? y : z
+     * @return the true expression
      */
-    public Node rhs() {
-        return rhs;
+    public Expression getTrueExpression() {
+        return trueExpr;
     }
 
     /**
-     * Get the "third" node for this ternary expression, i.e. "z" in x ? y : z
-     * @return a node
+     * Get the false expression for this ternary expression, i.e. "z" in x ? y : z
+     * @return the false expression
      */
-    public Node third() {
-        return third;
+    public Expression getFalseExpression() {
+        return falseExpr;
     }
 
     /**
-     * Set the left hand side expression for this node
-     * @param lhs new left hand side expression
+     * Set the test expression for this node
+     * @param test new test expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public TernaryNode setLHS(final Node lhs) {
-        if (this.lhs == lhs) {
+    public TernaryNode setTest(final Expression test) {
+        if (this.test == test) {
             return this;
         }
-        return new TernaryNode(this, lhs, rhs, third);
+        return new TernaryNode(this, test, trueExpr, falseExpr);
     }
 
     /**
-     * Set the right hand side expression for this node
-     * @param rhs new left hand side expression
+     * Set the true expression for this node
+     * @param trueExpr new true expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public TernaryNode setRHS(final Node rhs) {
-        if (this.rhs == rhs) {
+    public TernaryNode setTrueExpression(final Expression trueExpr) {
+        if (this.trueExpr == trueExpr) {
             return this;
         }
-        return new TernaryNode(this, lhs, rhs, third);
+        return new TernaryNode(this, test, trueExpr, falseExpr);
     }
 
     /**
-     * Reset the "third" node for this ternary expression, i.e. "z" in x ? y : z
-     * @param third a node
+     * Set the false expression for this node
+     * @param falseExpr new false expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public TernaryNode setThird(final Node third) {
-        if (this.third == third) {
+    public TernaryNode setFalseExpression1(final Expression falseExpr) {
+        if (this.falseExpr == falseExpr) {
             return this;
         }
-        return new TernaryNode(this, lhs, rhs, third);
+        return new TernaryNode(this, test, trueExpr, falseExpr);
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -34,7 +34,7 @@
 @Immutable
 public final class ThrowNode extends Statement {
     /** Exception expression. */
-    private final Node expression;
+    private final Expression expression;
 
     private final int flags;
 
@@ -50,13 +50,13 @@
      * @param expression expression to throw
      * @param flags      flags
      */
-    public ThrowNode(final int lineNumber, final long token, final int finish, final Node expression, final int flags) {
+    public ThrowNode(final int lineNumber, final long token, final int finish, final Expression expression, final int flags) {
         super(lineNumber, token, finish);
         this.expression = expression;
         this.flags = flags;
     }
 
-    private ThrowNode(final ThrowNode node, final Node expression, final int flags) {
+    private ThrowNode(final ThrowNode node, final Expression expression, final int flags) {
         super(node);
         this.expression = expression;
         this.flags = flags;
@@ -74,7 +74,7 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterThrowNode(this)) {
-            return visitor.leaveThrowNode(setExpression(expression.accept(visitor)));
+            return visitor.leaveThrowNode(setExpression((Expression)expression.accept(visitor)));
         }
 
         return this;
@@ -93,7 +93,7 @@
      * Get the expression that is being thrown by this node
      * @return expression
      */
-    public Node getExpression() {
+    public Expression getExpression() {
         return expression;
     }
 
@@ -102,7 +102,7 @@
      * @param expression new expression
      * @return new or same thrownode
      */
-    public ThrowNode setExpression(final Node expression) {
+    public ThrowNode setExpression(final Expression expression) {
         if (this.expression == expression) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -29,6 +29,7 @@
 import static jdk.nashorn.internal.parser.TokenType.CONVERT;
 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
+
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -39,9 +40,9 @@
  * UnaryNode nodes represent single operand operations.
  */
 @Immutable
-public final class UnaryNode extends Node implements Assignment<Node> {
+public final class UnaryNode extends Expression implements Assignment<Expression> {
     /** Right hand side argument. */
-    private final Node rhs;
+    private final Expression rhs;
 
     /**
      * Constructor
@@ -49,7 +50,7 @@
      * @param token  token
      * @param rhs    expression
      */
-    public UnaryNode(final long token, final Node rhs) {
+    public UnaryNode(final long token, final Expression rhs) {
         this(token, Math.min(rhs.getStart(), Token.descPosition(token)), Math.max(Token.descPosition(token) + Token.descLength(token), rhs.getFinish()), rhs);
     }
 
@@ -61,13 +62,13 @@
      * @param finish finish
      * @param rhs    expression
      */
-    public UnaryNode(final long token, final int start, final int finish, final Node rhs) {
+    public UnaryNode(final long token, final int start, final int finish, final Expression rhs) {
         super(token, start, finish);
         this.rhs = rhs;
     }
 
 
-    private UnaryNode(final UnaryNode unaryNode, final Node rhs) {
+    private UnaryNode(final UnaryNode unaryNode, final Expression rhs) {
         super(unaryNode);
         this.rhs = rhs;
     }
@@ -101,17 +102,17 @@
     }
 
     @Override
-    public Node getAssignmentDest() {
+    public Expression getAssignmentDest() {
         return isAssignment() ? rhs() : null;
     }
 
     @Override
-    public Node setAssignmentDest(Node n) {
+    public UnaryNode setAssignmentDest(Expression n) {
         return setRHS(n);
     }
 
     @Override
-    public Node getAssignmentSource() {
+    public Expression getAssignmentSource() {
         return getAssignmentDest();
     }
 
@@ -122,7 +123,7 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterUnaryNode(this)) {
-            return visitor.leaveUnaryNode(setRHS(rhs.accept(visitor)));
+            return visitor.leaveUnaryNode(setRHS((Expression)rhs.accept(visitor)));
         }
 
         return this;
@@ -189,7 +190,7 @@
      *
      * @return right hand side or expression node
      */
-    public Node rhs() {
+    public Expression rhs() {
         return rhs;
     }
 
@@ -202,7 +203,7 @@
      * @param rhs right hand side or expression node
      * @return a node equivalent to this one except for the requested change.
      */
-    public UnaryNode setRHS(final Node rhs) {
+    public UnaryNode setRHS(final Expression rhs) {
         if (this.rhs == rhs) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/VarNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/VarNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -37,7 +37,7 @@
     private final IdentNode name;
 
     /** Initialization expression. */
-    private final Node init;
+    private final Expression init;
 
     /** Is this a var statement (as opposed to a "var" in a for loop statement) */
     private final int flags;
@@ -59,11 +59,11 @@
      * @param name       name of variable
      * @param init       init node or null if just a declaration
      */
-    public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Node init) {
+    public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Expression init) {
         this(lineNumber, token, finish, name, init, IS_STATEMENT);
     }
 
-    private VarNode(final VarNode varNode, final IdentNode name, final Node init, final int flags) {
+    private VarNode(final VarNode varNode, final IdentNode name, final Expression init, final int flags) {
         super(varNode);
         this.name = init == null ? name : name.setIsInitializedHere();
         this.init = init;
@@ -80,7 +80,7 @@
      * @param init       init node or null if just a declaration
      * @param flags      flags
      */
-    public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Node init, final int flags) {
+    public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Expression init, final int flags) {
         super(lineNumber, token, finish);
 
         this.name  = init == null ? name : name.setIsInitializedHere();
@@ -99,12 +99,12 @@
     }
 
     @Override
-    public Node setAssignmentDest(IdentNode n) {
+    public VarNode setAssignmentDest(IdentNode n) {
         return setName(n);
     }
 
     @Override
-    public Node getAssignmentSource() {
+    public Expression getAssignmentSource() {
         return isAssignment() ? getInit() : null;
     }
 
@@ -123,9 +123,9 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterVarNode(this)) {
-            final IdentNode newName = (IdentNode)name.accept(visitor);
-            final Node      newInit = init == null ? null : init.accept(visitor);
-            final VarNode   newThis;
+            final IdentNode  newName = (IdentNode)name.accept(visitor);
+            final Expression newInit = init == null ? null : (Expression)init.accept(visitor);
+            final VarNode    newThis;
             if (name != newName || init != newInit) {
                 newThis = new VarNode(this, newName, newInit, flags);
             } else {
@@ -151,7 +151,7 @@
      * If this is an assignment of the form {@code var x = init;}, get the init part.
      * @return the expression to initialize the variable to, null if just a declaration
      */
-    public Node getInit() {
+    public Expression getInit() {
         return init;
     }
 
@@ -160,7 +160,7 @@
      * @param init new initialization expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public VarNode setInit(final Node init) {
+    public VarNode setInit(final Expression init) {
         if (this.init == init) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -59,7 +59,7 @@
      * @param body      body
      * @param controlFlowEscapes control flow escapes?
      */
-    protected WhileNode(final WhileNode whileNode, final Node test, final Block body, final boolean controlFlowEscapes) {
+    protected WhileNode(final WhileNode whileNode, final Expression test, final Block body, final boolean controlFlowEscapes) {
         super(whileNode, test, body, controlFlowEscapes);
         this.isDoWhile = whileNode.isDoWhile;
     }
@@ -75,28 +75,28 @@
     }
 
     @Override
-    protected Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterWhileNode(this)) {
             if (isDoWhile()) {
                 return visitor.leaveWhileNode(
-                        setTest(lc, test.accept(visitor)).
+                        setTest(lc, (Expression)test.accept(visitor)).
                         setBody(lc, (Block)body.accept(visitor)));
             }
             return visitor.leaveWhileNode(
                     setBody(lc, (Block)body.accept(visitor)).
-                    setTest(lc, test.accept(visitor)));
+                    setTest(lc, (Expression)test.accept(visitor)));
 
         }
         return this;
     }
 
     @Override
-    public Node getTest() {
+    public Expression getTest() {
         return test;
     }
 
     @Override
-    public WhileNode setTest(final LexicalContext lc, final Node test) {
+    public WhileNode setTest(final LexicalContext lc, final Expression test) {
         if (this.test == test) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/WithNode.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/WithNode.java	Thu Jul 11 18:33:33 2013 +0200
@@ -32,9 +32,9 @@
  * IR representation for {@code with} statements.
  */
 @Immutable
-public final class WithNode extends LexicalContextNode {
+public final class WithNode extends LexicalContextStatement {
    /** This expression. */
-    private final Node expression;
+    private final Expression expression;
 
     /** Statements. */
     private final Block body;
@@ -52,7 +52,7 @@
         this.body       = null;
     }
 
-    private WithNode(final WithNode node, final Node expression, final Block body) {
+    private WithNode(final WithNode node, final Expression expression, final Block body) {
         super(node);
         this.expression = expression;
         this.body       = body;
@@ -67,7 +67,7 @@
     public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterWithNode(this)) {
              return visitor.leaveWithNode(
-                setExpression(lc, expression.accept(visitor)).
+                setExpression(lc, (Expression)expression.accept(visitor)).
                 setBody(lc, (Block)body.accept(visitor)));
         }
         return this;
@@ -110,7 +110,7 @@
      * Get the expression of this WithNode
      * @return the expression
      */
-    public Node getExpression() {
+    public Expression getExpression() {
         return expression;
     }
 
@@ -120,7 +120,7 @@
      * @param expression new expression
      * @return new or same withnode
      */
-    public WithNode setExpression(final LexicalContext lc, final Node expression) {
+    public WithNode setExpression(final LexicalContext lc, final Expression expression) {
         if (this.expression == expression) {
             return this;
         }
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/ASTWriter.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/ASTWriter.java	Thu Jul 11 18:33:33 2013 +0200
@@ -33,10 +33,11 @@
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.annotations.Reference;
@@ -111,8 +112,15 @@
             type = "ref: " + type;
         }
         type += "@" + Debug.id(node);
-        if (node.getSymbol() != null) {
-            type += "#" + node.getSymbol();
+        final Symbol symbol;
+        if(node instanceof Expression) {
+            symbol = ((Expression)node).getSymbol();
+        } else {
+            symbol = null;
+        }
+
+        if (symbol != null) {
+            type += "#" + symbol;
         }
 
         if (node instanceof Block && ((Block)node).needsScope()) {
@@ -135,8 +143,8 @@
             status += " Goto ";
         }
 
-        if (node.getSymbol() != null) {
-            status += node.getSymbol();
+        if (symbol != null) {
+            status += symbol;
         }
 
         status = status.trim();
@@ -144,8 +152,8 @@
             status = " [" + status + "]";
         }
 
-        if (node.getSymbol() != null) {
-            String tname = node.getType().toString();
+        if (symbol != null) {
+            String tname = ((Expression)node).getType().toString();
             if (tname.indexOf('.') != -1) {
                 tname = tname.substring(tname.lastIndexOf('.') + 1, tname.length());
             }
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Thu Jul 11 18:33:33 2013 +0200
@@ -27,18 +27,18 @@
 
 import java.util.Arrays;
 import java.util.List;
-
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.BlockStatement;
 import jdk.nashorn.internal.ir.BreakNode;
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
 import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.EmptyNode;
-import jdk.nashorn.internal.ir.ExecuteNode;
+import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IdentNode;
@@ -298,14 +298,27 @@
     }
 
     @Override
-    public boolean enterExecuteNode(final ExecuteNode executeNode) {
-        enterDefault(executeNode);
+    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
+        enterDefault(expressionStatement);
 
         type("ExpressionStatement");
         comma();
 
         property("expression");
-        executeNode.getExpression().accept(this);
+        expressionStatement.getExpression().accept(this);
+
+        return leave();
+    }
+
+    @Override
+    public boolean enterBlockStatement(BlockStatement blockStatement) {
+        enterDefault(blockStatement);
+
+        type("BlockStatement");
+        comma();
+
+        property("block");
+        blockStatement.getBlock().accept(this);
 
         return leave();
     }
@@ -680,15 +693,15 @@
         comma();
 
         property("test");
-        ternaryNode.lhs().accept(this);
+        ternaryNode.getTest().accept(this);
         comma();
 
         property("consequent");
-        ternaryNode.rhs().accept(this);
+        ternaryNode.getTrueExpression().accept(this);
         comma();
 
         property("alternate");
-        ternaryNode.third().accept(this);
+        ternaryNode.getFalseExpression().accept(this);
 
         return leave();
     }
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Thu Jul 11 18:33:33 2013 +0200
@@ -26,12 +26,11 @@
 package jdk.nashorn.internal.ir.debug;
 
 import java.util.List;
-
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
-import jdk.nashorn.internal.ir.ExecuteNode;
+import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IfNode;
@@ -41,7 +40,6 @@
 import jdk.nashorn.internal.ir.SplitNode;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.SwitchNode;
-import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.TryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
@@ -167,14 +165,6 @@
                 continue;
             }
 
-            final Symbol symbol = statement.getSymbol();
-
-            if (symbol != null) {
-                sb.append("  [");
-                sb.append(symbol.toString());
-                sb.append(']');
-            }
-
             int  lastIndex = sb.length() - 1;
             char lastChar  = sb.charAt(lastIndex);
             while (Character.isWhitespace(lastChar) && lastIndex >= 0) {
@@ -215,8 +205,8 @@
     }
 
     @Override
-    public boolean enterExecuteNode(final ExecuteNode executeNode) {
-        executeNode.getExpression().accept(this);
+    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
+        expressionStatement.getExpression().accept(this);
         return false;
     }
 
--- a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Thu Jul 11 18:33:33 2013 +0200
@@ -1263,6 +1263,4 @@
     public Node leaveSUB(final BinaryNode binaryNode) {
         return leaveDefault(binaryNode);
     }
-
-
 }
--- a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Thu Jul 11 18:33:33 2013 +0200
@@ -28,13 +28,14 @@
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.BlockStatement;
 import jdk.nashorn.internal.ir.BreakNode;
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
 import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.EmptyNode;
-import jdk.nashorn.internal.ir.ExecuteNode;
+import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IdentNode;
@@ -308,23 +309,43 @@
     }
 
     /**
-     * Callback for entering an ExecuteNode
+     * Callback for entering an ExpressionStatement
      *
-     * @param  executeNode the node
+     * @param  expressionStatement the node
      * @return true if traversal should continue and node children be traversed, false otherwise
      */
-    public boolean enterExecuteNode(final ExecuteNode executeNode) {
-        return enterDefault(executeNode);
+    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
+        return enterDefault(expressionStatement);
     }
 
     /**
-     * Callback for leaving an ExecuteNode
+     * Callback for leaving an ExpressionStatement
      *
-     * @param  executeNode the node
+     * @param  expressionStatement the node
      * @return processed node, which will replace the original one, or the original node
      */
-    public Node leaveExecuteNode(final ExecuteNode executeNode) {
-        return leaveDefault(executeNode);
+    public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
+        return leaveDefault(expressionStatement);
+    }
+
+    /**
+     * Callback for entering a BlockStatement
+     *
+     * @param  blockStatement the node
+     * @return true if traversal should continue and node children be traversed, false otherwise
+     */
+    public boolean enterBlockStatement(final BlockStatement blockStatement) {
+        return enterDefault(blockStatement);
+    }
+
+    /**
+     * Callback for leaving a BlockStatement
+     *
+     * @param  blockStatement the node
+     * @return processed node, which will replace the original one, or the original node
+     */
+    public Node leaveBlockStatement(final BlockStatement blockStatement) {
+        return leaveDefault(blockStatement);
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java	Thu Jul 11 18:33:33 2013 +0200
@@ -35,6 +35,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ObjectNode;
@@ -274,7 +275,7 @@
      * Parse a JSON literal from the token stream
      * @return the JSON literal as a Node
      */
-    private Node jsonLiteral() {
+    private Expression jsonLiteral() {
         final long literalToken = token;
 
         switch (type) {
@@ -326,7 +327,7 @@
      * Parse an array literal from the token stream
      * @return the array literal as a Node
      */
-    private Node arrayLiteral() {
+    private LiteralNode<Expression[]> arrayLiteral() {
         // Unlike JavaScript array literals, elison is not permitted in JSON.
 
         // Capture LBRACKET token.
@@ -334,9 +335,9 @@
         // LBRACKET tested in caller.
         next();
 
-        Node result = null;
+        LiteralNode<Expression[]> result = null;
         // Prepare to accummulating elements.
-        final List<Node> elements = new ArrayList<>();
+        final List<Expression> elements = new ArrayList<>();
 
 loop:
         while (true) {
@@ -368,7 +369,7 @@
      * Parse an object literal from the token stream
      * @return the object literal as a Node
      */
-    private Node objectLiteral() {
+    private ObjectNode objectLiteral() {
         // Capture LBRACE token.
         final long objectToken = token;
         // LBRACE tested in caller.
@@ -423,7 +424,7 @@
 
         if (name != null) {
             expect(COLON);
-            final Node value = jsonLiteral();
+            final Expression value = jsonLiteral();
             return new PropertyNode(propertyToken, value.getFinish(), name, value, null, null);
         }
 
--- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Thu Jul 11 18:33:33 2013 +0200
@@ -54,6 +54,7 @@
 import static jdk.nashorn.internal.parser.TokenType.WHILE;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -66,6 +67,7 @@
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.BlockLexicalContext;
+import jdk.nashorn.internal.ir.BlockStatement;
 import jdk.nashorn.internal.ir.BreakNode;
 import jdk.nashorn.internal.ir.BreakableNode;
 import jdk.nashorn.internal.ir.CallNode;
@@ -73,7 +75,8 @@
 import jdk.nashorn.internal.ir.CatchNode;
 import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.EmptyNode;
-import jdk.nashorn.internal.ir.ExecuteNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
@@ -350,7 +353,7 @@
      * @return New block.
      */
     private Block newBlock() {
-        return lc.push(new Block(line, token, Token.descPosition(token)));
+        return lc.push(new Block(token, Token.descPosition(token)));
     }
 
     /**
@@ -516,7 +519,7 @@
      * @param rhs Right hand side expression.
      * @return Verified expression.
      */
-    private Node verifyAssignment(final long op, final Node lhs, final Node rhs) {
+    private Expression verifyAssignment(final long op, final Expression lhs, final Expression rhs) {
         final TokenType opType = Token.descType(op);
 
         switch (opType) {
@@ -562,7 +565,7 @@
      * @param isPostfix  Prefix or postfix.
      * @return           Reduced expression.
      */
-    private static Node incDecExpression(final long firstToken, final TokenType tokenType, final Node expression, final boolean isPostfix) {
+    private static UnaryNode incDecExpression(final long firstToken, final TokenType tokenType, final Expression expression, final boolean isPostfix) {
         if (isPostfix) {
             return new UnaryNode(Token.recast(firstToken, tokenType == DECPREFIX ? DECPOSTFIX : INCPOSTFIX), expression.getStart(), Token.descPosition(firstToken) + Token.descLength(firstToken), expression);
         }
@@ -622,8 +625,8 @@
      * @return Directive value if the given statement is a directive
      */
     private String getDirective(final Node stmt) {
-        if (stmt instanceof ExecuteNode) {
-            final Node expr = ((ExecuteNode)stmt).getExpression();
+        if (stmt instanceof ExpressionStatement) {
+            final Node expr = ((ExpressionStatement)stmt).getExpression();
             if (expr instanceof LiteralNode) {
                 final LiteralNode<?> lit = (LiteralNode<?>)expr;
                 final long litToken = lit.getToken();
@@ -836,9 +839,7 @@
      * Parse a statement block.
      */
     private void block() {
-        final Block newBlock = getBlock(true);
-        // Force block execution.
-        appendStatement(new ExecuteNode(newBlock.getLineNumber(), newBlock.getToken(), finish, newBlock));
+        appendStatement(new BlockStatement(line, getBlock(true)));
     }
 
     /**
@@ -921,7 +922,7 @@
             verifyStrictIdent(name, "variable name");
 
             // Assume no init.
-            Node init = null;
+            Expression init = null;
 
             // Look for initializer assignment.
             if (type == ASSIGN) {
@@ -985,20 +986,20 @@
         final long expressionToken = token;
 
         // Get expression and add as statement.
-        final Node expression = expression();
-
-        ExecuteNode executeNode = null;
+        final Expression expression = expression();
+
+        ExpressionStatement expressionStatement = null;
         if (expression != null) {
-            executeNode = new ExecuteNode(expressionLine, expressionToken, finish, expression);
-            appendStatement(executeNode);
+            expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
+            appendStatement(expressionStatement);
         } else {
             expect(null);
         }
 
         endOfLine();
 
-        if (executeNode != null) {
-            executeNode.setFinish(finish);
+        if (expressionStatement != null) {
+            expressionStatement.setFinish(finish);
             lc.getCurrentBlock().setFinish(finish);
         }
     }
@@ -1020,7 +1021,7 @@
         next();
 
         expect(LPAREN);
-        final Node test = expression();
+        final Expression test = expression();
         expect(RPAREN);
         final Block pass = getStatement();
 
@@ -1049,8 +1050,6 @@
         // Create FOR node, capturing FOR token.
         ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, null, null, null, ForNode.IS_FOR);
 
-        // Set up new block for scope of vars. Captures first token.
-        Block outer = newBlock();
         lc.push(forNode);
 
         try {
@@ -1076,7 +1075,7 @@
             case SEMICOLON:
                 break;
             default:
-                final Node expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
+                final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
                 forNode = forNode.setInit(lc, expression);
                 break;
             }
@@ -1148,15 +1147,11 @@
             final Block body = getStatement();
             forNode = forNode.setBody(lc, body);
             forNode.setFinish(body.getFinish());
-            outer.setFinish(body.getFinish());
 
             appendStatement(forNode);
         } finally {
             lc.pop(forNode);
-            outer = restoreBlock(outer);
         }
-
-        appendStatement(new ExecuteNode(outer.getLineNumber(), outer.getToken(), outer.getFinish(), outer));
      }
 
     /**
@@ -1364,7 +1359,7 @@
         // RETURN tested in caller.
         nextOrEOL();
 
-        Node expression = null;
+        Expression expression = null;
 
         // SEMICOLON or expression.
         switch (type) {
@@ -1400,7 +1395,7 @@
         // YIELD tested in caller.
         nextOrEOL();
 
-        Node expression = null;
+        Expression expression = null;
 
         // SEMICOLON or expression.
         switch (type) {
@@ -1502,7 +1497,7 @@
 
             while (type != RBRACE) {
                 // Prepare for next case.
-                Node caseExpression = null;
+                Expression caseExpression = null;
                 final long caseToken = token;
 
                 switch (type) {
@@ -1595,7 +1590,7 @@
         // THROW tested in caller.
         nextOrEOL();
 
-        Node expression = null;
+        Expression expression = null;
 
         // SEMICOLON or expression.
         switch (type) {
@@ -1643,6 +1638,7 @@
         next();
 
         // Container block needed to act as target for labeled break statements
+        final int startLine = line;
         Block outer = newBlock();
 
         // Create try.
@@ -1662,11 +1658,13 @@
                 verifyStrictIdent(exception, "catch argument");
 
                 // Check for conditional catch.
-                Node ifExpression = null;
+                final Expression ifExpression;
                 if (type == IF) {
                     next();
                     // Get the exception condition.
                     ifExpression = expression();
+                } else {
+                    ifExpression = null;
                 }
 
                 expect(RPAREN);
@@ -1713,7 +1711,7 @@
             outer = restoreBlock(outer);
         }
 
-        appendStatement(new ExecuteNode(outer.getLineNumber(), outer.getToken(), outer.getFinish(), outer));
+        appendStatement(new BlockStatement(startLine, outer));
     }
 
     /**
@@ -1731,7 +1729,7 @@
         // DEBUGGER tested in caller.
         next();
         endOfLine();
-        appendStatement(new ExecuteNode(debuggerLine, debuggerToken, finish, new RuntimeNode(debuggerToken, finish, RuntimeNode.Request.DEBUGGER, new ArrayList<Node>())));
+        appendStatement(new ExpressionStatement(debuggerLine, debuggerToken, finish, new RuntimeNode(debuggerToken, finish, RuntimeNode.Request.DEBUGGER, new ArrayList<Expression>())));
     }
 
     /**
@@ -1749,7 +1747,7 @@
      * @return Expression node.
      */
     @SuppressWarnings("fallthrough")
-    private Node primaryExpression() {
+    private Expression primaryExpression() {
         // Capture first token.
         final int  primaryLine  = line;
         final long primaryToken = token;
@@ -1796,7 +1794,7 @@
         case LPAREN:
             next();
 
-            final Node expression = expression();
+            final Expression expression = expression();
 
             expect(RPAREN);
 
@@ -1823,17 +1821,16 @@
      * @param primaryToken Original string token.
      * @return callNode to $EXEC.
      */
-    Node execString(final int primaryLine, final long primaryToken) {
+    CallNode execString(final int primaryLine, final long primaryToken) {
         // Synthesize an ident to call $EXEC.
         final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
         // Skip over EXECSTRING.
         next();
         // Set up argument list for call.
-        final List<Node> arguments = new ArrayList<>();
         // Skip beginning of edit string expression.
         expect(LBRACE);
         // Add the following expression to arguments.
-        arguments.add(expression());
+        final List<Expression> arguments = Collections.singletonList(expression());
         // Skip ending of edit string expression.
         expect(RBRACE);
 
@@ -1860,14 +1857,14 @@
      * Parse array literal.
      * @return Expression node.
      */
-    private Node arrayLiteral() {
+    private LiteralNode<Expression[]> arrayLiteral() {
         // Capture LBRACKET token.
         final long arrayToken = token;
         // LBRACKET tested in caller.
         next();
 
         // Prepare to accummulating elements.
-        final List<Node> elements = new ArrayList<>();
+        final List<Expression> elements = new ArrayList<>();
         // Track elisions.
         boolean elision = true;
 loop:
@@ -1895,7 +1892,7 @@
                     throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
                 }
                 // Add expression element.
-                final Node expression = assignmentExpression(false);
+                final Expression expression = assignmentExpression(false);
 
                 if (expression != null) {
                     elements.add(expression);
@@ -1925,7 +1922,7 @@
      * Parse an object literal.
      * @return Expression node.
      */
-    private Node objectLiteral() {
+    private ObjectNode objectLiteral() {
         // Capture LBRACE token.
         final long objectToken = token;
         // LBRACE tested in caller.
@@ -1972,11 +1969,11 @@
 
                     // ECMA section 11.1.5 Object Initialiser
                     // point # 4 on property assignment production
-                    final Node         value  = property.getValue();
+                    final Expression   value  = property.getValue();
                     final FunctionNode getter = property.getGetter();
                     final FunctionNode setter = property.getSetter();
 
-                    final Node         prevValue  = existingProperty.getValue();
+                    final Expression   prevValue  = existingProperty.getValue();
                     final FunctionNode prevGetter = existingProperty.getGetter();
                     final FunctionNode prevSetter = existingProperty.getSetter();
 
@@ -2052,7 +2049,7 @@
     private PropertyKey propertyName() {
         switch (type) {
         case IDENT:
-            return getIdent();
+            return getIdent().setIsPropertyName();
         case OCTAL:
             if (isStrictMode) {
                 throw error(AbstractParser.message("strict.no.octal"), token);
@@ -2129,7 +2126,7 @@
                 }
             }
 
-            propertyName =  new IdentNode(propertyToken, finish, ident);
+            propertyName =  new IdentNode(propertyToken, finish, ident).setIsPropertyName();
         } else {
             propertyName = propertyName();
         }
@@ -2155,14 +2152,14 @@
      * Parse left hand side expression.
      * @return Expression node.
      */
-    private Node leftHandSideExpression() {
+    private Expression leftHandSideExpression() {
         int  callLine  = line;
         long callToken = token;
 
-        Node lhs = memberExpression();
+        Expression lhs = memberExpression();
 
         if (type == LPAREN) {
-            final List<Node> arguments = argumentList();
+            final List<Expression> arguments = optimizeList(argumentList());
 
             // Catch special functions.
             if (lhs instanceof IdentNode) {
@@ -2181,7 +2178,7 @@
             switch (type) {
             case LPAREN:
                 // Get NEW or FUNCTION arguments.
-                final List<Node> arguments = argumentList();
+                final List<Expression> arguments = optimizeList(argumentList());
 
                 // Create call node.
                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments);
@@ -2192,7 +2189,7 @@
                 next();
 
                 // Get array index.
-                final Node rhs = expression();
+                final Expression rhs = expression();
 
                 expect(RBRACKET);
 
@@ -2229,19 +2226,19 @@
      * Parse new expression.
      * @return Expression node.
      */
-    private Node newExpression() {
+    private Expression newExpression() {
         final long newToken = token;
         // NEW is tested in caller.
         next();
 
         // Get function base.
         final int  callLine    = line;
-        final Node constructor = memberExpression();
+        final Expression constructor = memberExpression();
         if (constructor == null) {
             return null;
         }
         // Get arguments.
-        List<Node> arguments;
+        ArrayList<Expression> arguments;
 
         // Allow for missing arguments.
         if (type == LPAREN) {
@@ -2259,12 +2256,11 @@
         //
         // The object literal following the "new Constructor()" expresssion
         // is passed as an additional (last) argument to the constructor.
-
         if (!env._no_syntax_extensions && type == LBRACE) {
             arguments.add(objectLiteral());
         }
 
-        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, arguments);
+        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments));
 
         return new UnaryNode(newToken, callNode);
     }
@@ -2282,9 +2278,9 @@
      * Parse member expression.
      * @return Expression node.
      */
-    private Node memberExpression() {
+    private Expression memberExpression() {
         // Prepare to build operation.
-        Node lhs;
+        Expression lhs;
 
         switch (type) {
         case NEW:
@@ -2313,7 +2309,7 @@
                 next();
 
                 // Get array index.
-                final Node index = expression();
+                final Expression index = expression();
 
                 expect(RBRACKET);
 
@@ -2358,9 +2354,9 @@
      * Parse function call arguments.
      * @return Argument list.
      */
-    private List<Node> argumentList() {
+    private ArrayList<Expression> argumentList() {
         // Prepare to accumulate list of arguments.
-        final List<Node> nodeList = new ArrayList<>();
+        final ArrayList<Expression> nodeList = new ArrayList<>();
         // LPAREN tested in caller.
         next();
 
@@ -2380,9 +2376,23 @@
         }
 
         expect(RPAREN);
-
         return nodeList;
-   }
+    }
+
+    private static <T> List<T> optimizeList(ArrayList<T> list) {
+        switch(list.size()) {
+            case 0: {
+                return Collections.emptyList();
+            }
+            case 1: {
+                return Collections.singletonList(list.get(0));
+            }
+            default: {
+                list.trimToSize();
+                return list;
+            }
+        }
+    }
 
     /**
      * FunctionDeclaration :
@@ -2398,7 +2408,7 @@
      *
      * @return Expression node.
      */
-    private Node functionExpression(final boolean isStatement, final boolean topLevel) {
+    private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
         final long functionToken = token;
         final int  functionLine  = line;
         // FUNCTION is tested in caller.
@@ -2574,10 +2584,8 @@
                  */
 
                 // just expression as function body
-                final Node expr = assignmentExpression(true);
+                final Expression expr = assignmentExpression(true);
                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
-                // create a return statement - this creates code in itself and does not need to be
-                // wrapped into an ExecuteNode
                 final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), finish, expr);
                 appendStatement(returnNode);
                 lastToken = token;
@@ -2620,11 +2628,11 @@
         }
     }
 
-    private RuntimeNode referenceError(final Node lhs, final Node rhs, final boolean earlyError) {
+    private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
         if (earlyError) {
             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
         }
-        final ArrayList<Node> args = new ArrayList<>();
+        final ArrayList<Expression> args = new ArrayList<>();
         args.add(lhs);
         if (rhs == null) {
             args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
@@ -2669,18 +2677,18 @@
      * Parse unary expression.
      * @return Expression node.
      */
-    private Node unaryExpression() {
+    private Expression unaryExpression() {
         final int  unaryLine  = line;
         final long unaryToken = token;
 
         switch (type) {
         case DELETE: {
             next();
-            final Node expr = unaryExpression();
+            final Expression expr = unaryExpression();
             if (expr instanceof BaseNode || expr instanceof IdentNode) {
                 return new UnaryNode(unaryToken, expr);
             }
-            appendStatement(new ExecuteNode(unaryLine, unaryToken, finish, expr));
+            appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
             return LiteralNode.newInstance(unaryToken, finish, true);
         }
         case VOID:
@@ -2690,7 +2698,7 @@
         case BIT_NOT:
         case NOT:
             next();
-            final Node expr = unaryExpression();
+            final Expression expr = unaryExpression();
             return new UnaryNode(unaryToken, expr);
 
         case INCPREFIX:
@@ -2698,7 +2706,7 @@
             final TokenType opType = type;
             next();
 
-            final Node lhs = leftHandSideExpression();
+            final Expression lhs = leftHandSideExpression();
             // ++, -- without operand..
             if (lhs == null) {
                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
@@ -2723,14 +2731,14 @@
             break;
         }
 
-        Node expression = leftHandSideExpression();
+        Expression expression = leftHandSideExpression();
 
         if (last != EOL) {
             switch (type) {
             case INCPREFIX:
             case DECPREFIX:
                 final TokenType opType = type;
-                final Node lhs = expression;
+                final Expression lhs = expression;
                 // ++, -- without operand..
                 if (lhs == null) {
                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
@@ -2855,16 +2863,16 @@
      * Parse expression.
      * @return Expression node.
      */
-    private Node expression() {
+    private Expression expression() {
         // TODO - Destructuring array.
         // Include commas in expression parsing.
         return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
     }
 
-    private Node expression(final Node exprLhs, final int minPrecedence, final boolean noIn) {
+    private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
         // Get the precedence of the next operator.
         int precedence = type.getPrecedence();
-        Node lhs = exprLhs;
+        Expression lhs = exprLhs;
 
         // While greater precedence.
         while (type.isOperator(noIn) && precedence >= minPrecedence) {
@@ -2877,12 +2885,12 @@
 
                 // Pass expression. Middle expression of a conditional expression can be a "in"
                 // expression - even in the contexts where "in" is not permitted.
-                final Node rhs = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
+                final Expression rhs = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
 
                 expect(COLON);
 
                 // Fail expression.
-                final Node third = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
+                final Expression third = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
 
                 // Build up node.
                 lhs = new TernaryNode(op, lhs, rhs, third);
@@ -2891,7 +2899,7 @@
                 next();
 
                  // Get the next primary expression.
-                Node rhs = unaryExpression();
+                Expression rhs = unaryExpression();
 
                 // Get precedence of next operator.
                 int nextPrecedence = type.getPrecedence();
@@ -2913,7 +2921,7 @@
         return lhs;
     }
 
-    private Node assignmentExpression(final boolean noIn) {
+    private Expression assignmentExpression(final boolean noIn) {
         // TODO - Handle decompose.
         // Exclude commas in expression parsing.
         return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Thu Jul 11 18:33:33 2013 +0200
@@ -28,7 +28,6 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.invoke.MethodType;
-import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import jdk.internal.dynalink.CallSiteDescriptor;
@@ -111,7 +110,7 @@
         final NashornCallSiteDescriptor csd = new NashornCallSiteDescriptor(lookup, operator, operand, methodType, flags);
         // Many of these call site descriptors are identical (e.g. every getter for a property color will be
         // "dyn:getProp:color(Object)Object", so it makes sense canonicalizing them.
-        final Map<NashornCallSiteDescriptor, NashornCallSiteDescriptor> classCanonicals = canonicals.get(lookup.lookupClass());
+        final ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor> classCanonicals = canonicals.get(lookup.lookupClass());
         final NashornCallSiteDescriptor canonical = classCanonicals.putIfAbsent(csd, csd);
         return canonical != null ? canonical : csd;
     }
--- a/nashorn/test/script/trusted/JDK-8006529.js	Thu Jul 11 18:23:13 2013 +0530
+++ b/nashorn/test/script/trusted/JDK-8006529.js	Thu Jul 11 18:33:33 2013 +0200
@@ -39,26 +39,26 @@
  * and FunctionNode because of package-access check and so reflective calls.
  */
 
-var Parser            = Java.type("jdk.nashorn.internal.parser.Parser")
-var Compiler          = Java.type("jdk.nashorn.internal.codegen.Compiler")
-var Context           = Java.type("jdk.nashorn.internal.runtime.Context")
-var ScriptEnvironment = Java.type("jdk.nashorn.internal.runtime.ScriptEnvironment")
-var Source            = Java.type("jdk.nashorn.internal.runtime.Source")
-var FunctionNode      = Java.type("jdk.nashorn.internal.ir.FunctionNode")
-var Block             = Java.type("jdk.nashorn.internal.ir.Block")
-var VarNode           = Java.type("jdk.nashorn.internal.ir.VarNode")
-var ExecuteNode       = Java.type("jdk.nashorn.internal.ir.ExecuteNode")
-var UnaryNode         = Java.type("jdk.nashorn.internal.ir.UnaryNode")
-var BinaryNode        = Java.type("jdk.nashorn.internal.ir.BinaryNode")
-var ThrowErrorManager = Java.type("jdk.nashorn.internal.runtime.Context$ThrowErrorManager")
-var Debug             = Java.type("jdk.nashorn.internal.runtime.Debug")
+var Parser              = Java.type("jdk.nashorn.internal.parser.Parser")
+var Compiler            = Java.type("jdk.nashorn.internal.codegen.Compiler")
+var Context             = Java.type("jdk.nashorn.internal.runtime.Context")
+var ScriptEnvironment   = Java.type("jdk.nashorn.internal.runtime.ScriptEnvironment")
+var Source              = Java.type("jdk.nashorn.internal.runtime.Source")
+var FunctionNode        = Java.type("jdk.nashorn.internal.ir.FunctionNode")
+var Block               = Java.type("jdk.nashorn.internal.ir.Block")
+var VarNode             = Java.type("jdk.nashorn.internal.ir.VarNode")
+var ExpressionStatement = Java.type("jdk.nashorn.internal.ir.ExpressionStatement")
+var UnaryNode           = Java.type("jdk.nashorn.internal.ir.UnaryNode")
+var BinaryNode          = Java.type("jdk.nashorn.internal.ir.BinaryNode")
+var ThrowErrorManager   = Java.type("jdk.nashorn.internal.runtime.Context$ThrowErrorManager")
+var Debug               = Java.type("jdk.nashorn.internal.runtime.Debug")
 
 var parseMethod = Parser.class.getMethod("parse");
 var compileMethod = Compiler.class.getMethod("compile", FunctionNode.class);
 var getBodyMethod = FunctionNode.class.getMethod("getBody");
 var getStatementsMethod = Block.class.getMethod("getStatements");
 var getInitMethod = VarNode.class.getMethod("getInit");
-var getExpressionMethod = ExecuteNode.class.getMethod("getExpression")
+var getExpressionMethod = ExpressionStatement.class.getMethod("getExpression")
 var rhsMethod = UnaryNode.class.getMethod("rhs")
 var lhsMethod = BinaryNode.class.getMethod("lhs")
 var binaryRhsMethod = BinaryNode.class.getMethod("rhs")
@@ -101,7 +101,7 @@
         return findFunction(rhsMethod.invoke(node))
     } else if(node instanceof BinaryNode) {
         return findFunction(lhsMethod.invoke(node)) || findFunction(binaryRhsMethod.invoke(node))
-	} else if(node instanceof ExecuteNode) {
+	} else if(node instanceof ExpressionStatement) {
 		return findFunction(getExpressionMethod.invoke(node))
     } else if(node instanceof FunctionNode) {
         return node