changeset 441:8108ba8366fd

Merge
author sundar
date Fri, 12 Jul 2013 20:12:29 +0530
parents c96745616167 e27ebcfed6fa
children cbfeffbcd3f2
files src/jdk/nashorn/internal/ir/ExecuteNode.java test/script/currently-failing/JDK-8006529.js
diffstat 111 files changed, 2797 insertions(+), 1348 deletions(-) [+]
line wrap: on
line diff
--- a/make/build.xml	Mon Jul 08 18:43:41 2013 +0530
+++ b/make/build.xml	Fri Jul 12 20:12:29 2013 +0530
@@ -219,8 +219,10 @@
            target="${javac.target}"
            debug="${javac.debug}"
            encoding="${javac.encoding}"
-           includeantruntime="false">
-        <compilerarg line="-extdirs &quot;&quot;"/>
+           includeantruntime="false" fork="true">
+        <compilerarg value="-J-Djava.ext.dirs="/>
+        <compilerarg value="-Xlint:unchecked"/>
+        <compilerarg value="-Xlint:deprecation"/>
     </javac>
 
     <!-- tests that check nashorn internals and internal API -->
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Fri Jul 12 20:12:29 2013 +0530
@@ -33,6 +33,7 @@
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.net.URL;
 import java.nio.charset.Charset;
 import java.security.AccessController;
@@ -184,6 +185,19 @@
     }
 
     private <T> T getInterfaceInner(final Object self, final Class<T> clazz) {
+        if (clazz == null || !clazz.isInterface()) {
+            throw new IllegalArgumentException("interface Class expected");
+        }
+
+        // perform security access check as early as possible
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (! Modifier.isPublic(clazz.getModifiers())) {
+                throw new SecurityException("attempt to implement non-public interfce: " + clazz);
+            }
+            Context.checkPackageAccess(clazz.getName());
+        }
+
         final ScriptObject realSelf;
         final ScriptObject ctxtGlobal = getNashornGlobalFrom(context);
         if(self == null) {
@@ -193,6 +207,7 @@
         } else {
             realSelf = (ScriptObject)self;
         }
+
         try {
             final ScriptObject oldGlobal = getNashornGlobal();
             try {
--- a/src/jdk/nashorn/internal/codegen/Attr.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/Attr.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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;
@@ -94,7 +94,6 @@
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.Property;
 import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptObject;
 
 /**
  * This is the attribution pass of the code generator. Attr takes Lowered IR,
@@ -166,19 +165,19 @@
     }
 
     private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) {
-        initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL, FunctionNode.FUNCTION_TYPE);
+        initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL);
         initCompileConstant(THIS, body, IS_PARAM | IS_THIS, Type.OBJECT);
 
         if (functionNode.isVarArg()) {
-            initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL, Type.OBJECT_ARRAY);
+            initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL);
             if (functionNode.needsArguments()) {
-                initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.typeFor(ScriptObject.class));
+                initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED);
                 addLocalDef(ARGUMENTS.symbolName());
             }
         }
 
         initParameters(functionNode, body);
-        initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.typeFor(ScriptObject.class));
+        initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED);
         initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.OBJECT);
     }
 
@@ -513,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());
@@ -741,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) {
@@ -785,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 {
@@ -848,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);
@@ -869,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) {
@@ -880,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);
     }
@@ -908,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).
@@ -923,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));
@@ -935,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);
@@ -999,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);
@@ -1041,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);
@@ -1097,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()) {
@@ -1134,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
@@ -1414,19 +1405,26 @@
 
     @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));
     }
 
+    private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) {
+        final Class<?> type = cc.type();
+        // Must not call this method for constants with no explicit types; use the one with (..., Type) signature instead.
+        assert type != null;
+        initCompileConstant(cc, block, flags, Type.typeFor(type));
+    }
+
     private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags, final Type type) {
         final Symbol symbol = defineSymbol(block, cc.symbolName(), flags);
-        newType(symbol, type);
+        symbol.setTypeOverride(type);
         symbol.setNeedsSlot(true);
     }
 
@@ -1531,7 +1529,7 @@
         }
     }
 
-    private static void ensureTypeNotUnknown(final Node node) {
+    private static void ensureTypeNotUnknown(final Expression node) {
 
         final Symbol symbol = node.getSymbol();
 
@@ -1588,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();
@@ -1636,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;
                     }
@@ -1648,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;
                     }
@@ -1703,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
@@ -1711,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) {
@@ -1835,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();
@@ -1854,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/src/jdk/nashorn/internal/codegen/BranchOptimizer.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Fri Jul 12 20:12:29 2013 +0530
@@ -55,10 +55,12 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.EnumSet;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 import java.util.TreeMap;
 import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
@@ -69,6 +71,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 +79,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;
@@ -182,6 +186,8 @@
     /** From what size should we use spill instead of fields for JavaScript objects? */
     private static final int OBJECT_SPILL_THRESHOLD = 300;
 
+    private final Set<String> emittedMethods = new HashSet<>();
+
     /**
      * Constructor.
      *
@@ -350,11 +356,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.
@@ -488,6 +494,9 @@
 
     @Override
     public boolean enterBlock(final Block block) {
+        if(lc.isFunctionBody() && emittedMethods.contains(lc.getCurrentFunction().getName())) {
+            return false;
+        }
         method.label(block.getEntryLabel());
         initLocals(block);
 
@@ -539,11 +548,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 +562,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 +583,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 +780,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 +811,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 +844,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 +859,7 @@
         method._goto(forNode.getContinueLabel());
         method.label(loopLabel);
 
-        new Store<Node>(init) {
+        new Store<Expression>(init) {
             @Override
             protected void storeNonDiscard() {
                 return;
@@ -1003,17 +1014,28 @@
             return false;
         }
 
-        LOG.info("=== BEGIN ", functionNode.getName());
-
-        assert functionNode.getCompileUnit() != null : "no compile unit for " + functionNode.getName() + " " + Debug.id(functionNode);
-        unit = lc.pushCompileUnit(functionNode.getCompileUnit());
-        assert lc.hasCompileUnits();
-
-        method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode));
-        // new method - reset last line number
-        lastLineNumber = -1;
-        // Mark end for variable tables.
-        method.begin();
+        final String fnName = functionNode.getName();
+        // NOTE: we only emit the method for a function with the given name once. We can have multiple functions with
+        // the same name as a result of inlining finally blocks. However, in the future -- with type specialization,
+        // notably -- we might need to check for both name *and* signature. Of course, even that might not be
+        // sufficient; the function might have a code dependency on the type of the variables in its enclosing scopes,
+        // and the type of such a variable can be different in catch and finally blocks. So, in the future we will have
+        // to decide to either generate a unique method for each inlined copy of the function, maybe figure out its
+        // exact type closure and deduplicate based on that, or just decide that functions in finally blocks aren't
+        // worth it, and generate one method with most generic type closure.
+        if(!emittedMethods.contains(fnName)) {
+            LOG.info("=== BEGIN ", fnName);
+
+            assert functionNode.getCompileUnit() != null : "no compile unit for " + fnName + " " + Debug.id(functionNode);
+            unit = lc.pushCompileUnit(functionNode.getCompileUnit());
+            assert lc.hasCompileUnits();
+
+            method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode));
+            // new method - reset last line number
+            lastLineNumber = -1;
+            // Mark end for variable tables.
+            method.begin();
+        }
 
         return true;
     }
@@ -1021,13 +1043,14 @@
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         try {
-            method.end(); // wrap up this method
-            unit   = lc.popCompileUnit(functionNode.getCompileUnit());
-            method = lc.popMethodEmitter(method);
-            LOG.info("=== END ", functionNode.getName());
+            if(emittedMethods.add(functionNode.getName())) {
+                method.end(); // wrap up this method
+                unit   = lc.popCompileUnit(functionNode.getCompileUnit());
+                method = lc.popMethodEmitter(method);
+                LOG.info("=== END ", functionNode.getName());
+            }
 
             final FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.EMITTED);
-
             newFunctionObject(newFunctionNode, functionNode);
             return newFunctionNode;
         } catch (final Throwable t) {
@@ -1047,7 +1070,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 +1110,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 +1132,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 +1192,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 +1208,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);
 
@@ -1313,7 +1339,7 @@
     }
 
     @Override
-    public boolean enterLiteralNode(final LiteralNode literalNode) {
+    public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
         assert literalNode.getSymbol() != null : literalNode + " has no symbol";
         load(literalNode).store(literalNode.getSymbol());
         return false;
@@ -1323,16 +1349,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 +1372,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 +1445,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 +1461,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 +1470,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 +1528,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 +1581,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 +1622,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 +1630,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 +1641,7 @@
                 false,
                 false,
                 runtimeNode.getType(),
-                runtimeNode.getArgs().size()).toString());
+                args.size()).toString());
         method.convert(runtimeNode.getType());
         method.store(runtimeNode.getSymbol());
 
@@ -1626,8 +1650,6 @@
 
     @Override
     public boolean enterSplitNode(final SplitNode splitNode) {
-        lineNumber(splitNode);
-
         final CompileUnit splitCompileUnit = splitNode.getCompileUnit();
 
         final FunctionNode fn   = lc.getCurrentFunction();
@@ -1772,7 +1794,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();
@@ -1869,11 +1891,13 @@
                 method.store(tag);
                 method.conditionalJump(Condition.NE, true, defaultLabel);
             } else {
+                assert tag.getSymbolType().isObject();
+                method.convert(Type.OBJECT); //e.g. 1 literal pushed and tag is object
                 method.store(tag);
             }
 
             for (final CaseNode caseNode : cases) {
-                final Node test = caseNode.getTest();
+                final Expression test = caseNode.getTest();
 
                 if (test != null) {
                     method.load(tag);
@@ -1913,10 +1937,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();
@@ -1965,10 +1989,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
@@ -2036,7 +2060,7 @@
     @Override
     public boolean enterVarNode(final VarNode varNode) {
 
-        final Node init = varNode.getInit();
+        final Expression init = varNode.getInit();
 
         if (init == null) {
             return false;
@@ -2044,8 +2068,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;
 
@@ -2065,9 +2089,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);
         }
 
@@ -2078,11 +2100,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);
@@ -2109,8 +2131,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
@@ -2185,7 +2207,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) {
@@ -2222,11 +2244,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();
 
@@ -2270,7 +2292,7 @@
 
     @Override
     public boolean enterDISCARD(final UnaryNode unaryNode) {
-        final Node rhs = unaryNode.rhs();
+        final Expression rhs = unaryNode.rhs();
 
         lc.pushDiscard(rhs);
         load(rhs);
@@ -2287,7 +2309,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
@@ -2300,7 +2322,7 @@
 
     @Override
     public boolean enterNOT(final UnaryNode unaryNode) {
-        final Node rhs = unaryNode.rhs();
+        final Expression rhs = unaryNode.rhs();
 
         load(rhs);
 
@@ -2334,19 +2356,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()) {
@@ -2362,8 +2383,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");
 
@@ -2390,8 +2411,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();
@@ -2659,8 +2680,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);
@@ -2691,7 +2712,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();
 
@@ -2844,21 +2865,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
@@ -2866,11 +2887,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);
@@ -2923,8 +2944,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);
         }
 
@@ -2937,13 +2958,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;
@@ -2957,7 +2978,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;
         }
@@ -3000,8 +3021,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);
@@ -3022,7 +3043,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/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/Compiler.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Fri Jul 12 20:12:29 2013 +0530
@@ -528,8 +528,8 @@
         return this.env;
     }
 
-    private static String safeSourceName(final Source source) {
-        String baseName = new File(source.getName()).getName();
+    private String safeSourceName(final Source src) {
+        String baseName = new File(src.getName()).getName();
 
         final int index = baseName.lastIndexOf(".js");
         if (index != -1) {
@@ -537,6 +537,9 @@
         }
 
         baseName = baseName.replace('.', '_').replace('-', '_');
+        if (! env._loader_per_compile) {
+            baseName = baseName + installer.getUniqueScriptId();
+        }
         final String mangled = NameCodec.encode(baseName);
 
         return mangled != null ? mangled : baseName;
--- a/src/jdk/nashorn/internal/codegen/CompilerConstants.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/CompilerConstants.java	Fri Jul 12 20:12:29 2013 +0530
@@ -100,10 +100,10 @@
     CALLEE(":callee", ScriptFunction.class),
 
     /** the varargs variable when necessary */
-    VARARGS(":varargs"),
+    VARARGS(":varargs", Object[].class),
 
     /** the arguments vector when necessary and the slot */
-    ARGUMENTS("arguments", Object.class, 2),
+    ARGUMENTS("arguments", ScriptObject.class, 2),
 
     /** prefix for iterators for for (x in ...) */
     ITERATOR_PREFIX(":i", Iterator.class),
--- a/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/FoldConstants.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/FunctionSignature.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/FunctionSignature.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/Lower.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/Lower.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Fri Jul 12 20:12:29 2013 +0530
@@ -435,13 +435,13 @@
      * @return Open method emitter.
      */
     private static MethodEmitter newInitScopeWithArgumentsMethod(final ClassEmitter classEmitter) {
-        final MethodEmitter init = classEmitter.init(PropertyMap.class, ScriptObject.class, Object.class);
+        final MethodEmitter init = classEmitter.init(PropertyMap.class, ScriptObject.class, ScriptObject.class);
         init.begin();
         init.load(Type.OBJECT, JAVA_THIS.slot());
         init.load(Type.OBJECT, INIT_MAP.slot());
         init.load(Type.OBJECT, INIT_SCOPE.slot());
         init.load(Type.OBJECT, INIT_ARGUMENTS.slot());
-        init.invoke(constructorNoLookup(FunctionScope.class, PropertyMap.class, ScriptObject.class, Object.class));
+        init.invoke(constructorNoLookup(FunctionScope.class, PropertyMap.class, ScriptObject.class, ScriptObject.class));
 
         return init;
     }
--- a/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/Splitter.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/Splitter.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/WeighNodes.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/WeighNodes.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/codegen/types/Type.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/codegen/types/Type.java	Fri Jul 12 20:12:29 2013 +0530
@@ -47,9 +47,8 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.T_LONG;
 
 import java.lang.invoke.MethodHandle;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 
@@ -548,19 +547,19 @@
      * @return the Type representing this class
      */
     public static Type typeFor(final Class<?> clazz) {
-        Type type = cache.get(clazz);
-
-        if (type == null) {
-            assert !clazz.isPrimitive() || clazz == void.class;
-            if (clazz.isArray()) {
-                type = new ArrayType(clazz);
-            } else {
-                type = new ObjectType(clazz);
-            }
-            cache.put(clazz, type);
+        final Type type = cache.get(clazz);
+        if(type != null) {
+            return type;
         }
-
-        return type;
+        assert !clazz.isPrimitive() || clazz == void.class;
+        final Type newType;
+        if (clazz.isArray()) {
+            newType = new ArrayType(clazz);
+        } else {
+            newType = new ObjectType(clazz);
+        }
+        final Type existingType = cache.putIfAbsent(clazz, newType);
+        return existingType == null ? newType : existingType;
     }
 
     @Override
@@ -663,35 +662,38 @@
         }
     }
 
+    /** Mappings between java classes and their Type singletons */
+    private static final ConcurrentMap<Class<?>, Type> cache = new ConcurrentHashMap<>();
+
     /**
      * This is the boolean singleton, used for all boolean types
      */
-    public static final Type BOOLEAN = new BooleanType();
+    public static final Type BOOLEAN = putInCache(new BooleanType());
 
     /**
      * This is an integer type, i.e INT, INT32.
      */
-    public static final Type INT = new IntType();
+    public static final Type INT = putInCache(new IntType());
 
     /**
      * This is the number singleton, used for all number types
      */
-    public static final Type NUMBER = new NumberType();
+    public static final Type NUMBER = putInCache(new NumberType());
 
     /**
      * This is the long singleton, used for all long types
      */
-    public static final Type LONG = new LongType();
+    public static final Type LONG = putInCache(new LongType());
 
     /**
      * A string singleton
      */
-    public static final Type STRING = new ObjectType(String.class);
+    public static final Type STRING = putInCache(new ObjectType(String.class));
 
     /**
      * This is the object singleton, used for all object types
      */
-    public static final Type OBJECT = new ObjectType();
+    public static final Type OBJECT = putInCache(new ObjectType());
 
     /**
      * This is the singleton for integer arrays
@@ -775,13 +777,13 @@
     };
 
     /** Singleton for method handle arrays used for properties etc. */
-    public static final ArrayType METHODHANDLE_ARRAY = new ArrayType(MethodHandle[].class);
+    public static final ArrayType METHODHANDLE_ARRAY = putInCache(new ArrayType(MethodHandle[].class));
 
     /** This is the singleton for string arrays */
-    public static final ArrayType STRING_ARRAY = new ArrayType(String[].class);
+    public static final ArrayType STRING_ARRAY = putInCache(new ArrayType(String[].class));
 
     /** This is the singleton for object arrays */
-    public static final ArrayType OBJECT_ARRAY = new ArrayType(Object[].class);
+    public static final ArrayType OBJECT_ARRAY = putInCache(new ArrayType(Object[].class));
 
     /** This type, always an object type, just a toString override */
     public static final Type THIS = new ObjectType() {
@@ -855,18 +857,8 @@
         }
     };
 
-    /** Mappings between java classes and their Type singletons */
-    private static final Map<Class<?>, Type> cache = Collections.synchronizedMap(new HashMap<Class<?>, Type>());
-
-    //TODO may need to be cleared, as all types are retained throughout code generation
-    static {
-        cache.put(BOOLEAN.getTypeClass(), BOOLEAN);
-        cache.put(INT.getTypeClass(),     INT);
-        cache.put(LONG.getTypeClass(),    LONG);
-        cache.put(NUMBER.getTypeClass(),  NUMBER);
-        cache.put(STRING.getTypeClass(),  STRING);
-        cache.put(OBJECT.getTypeClass(),  OBJECT);
-        cache.put(OBJECT_ARRAY.getTypeClass(), OBJECT_ARRAY);
+    private static <T extends Type> T putInCache(T type) {
+        cache.put(type.getTypeClass(), type);
+        return type;
     }
-
 }
--- a/src/jdk/nashorn/internal/ir/AccessNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/AccessNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/Assignment.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/Assignment.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/BaseNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/BaseNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/BinaryNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/BinaryNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/Block.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/Block.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/BlockStatement.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/BreakableNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/BreakableNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/BreakableStatement.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/CallNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/CallNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/CaseNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/CaseNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/CatchNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/CatchNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/ExecuteNode.java	Mon Jul 08 18:43:41 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/src/jdk/nashorn/internal/ir/Expression.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/ExpressionStatement.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/ForNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/ForNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/FunctionNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/FunctionNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/IdentNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/IdentNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/IfNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/IfNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/IndexNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/IndexNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/LabelNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/LabelNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/LexicalContext.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/LexicalContext.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/LexicalContextExpression.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/LexicalContextNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/LexicalContextNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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);
+    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);
+    // 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);
+        }
     }
-
-    /**
-     * 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));
-    }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/ir/LexicalContextStatement.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/LiteralNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/LiteralNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/LoopNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/LoopNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/Node.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/Node.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/ObjectNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/ObjectNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/PropertyNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/PropertyNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/ReturnNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/ReturnNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/RuntimeNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/SplitNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/SplitNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/SwitchNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/SwitchNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/TemporarySymbols.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/TemporarySymbols.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/TernaryNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/TernaryNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/ThrowNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/ThrowNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/UnaryNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/UnaryNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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;
@@ -130,6 +131,22 @@
 
     @Override
     public void toString(final StringBuilder sb) {
+        toString(sb, new Runnable() {
+            @Override
+            public void run() {
+                sb.append(rhs().toString());
+            }
+        });
+    }
+
+    /**
+     * Creates the string representation of this unary node, delegating the creation of the string representation of its
+     * operand to a specified runnable.
+     * @param sb the string builder to use
+     * @param rhsStringBuilder the runnable that appends the string representation of the operand to the string builder
+     * when invoked.
+     */
+    public void toString(final StringBuilder sb, final Runnable rhsStringBuilder) {
         final TokenType type      = tokenType();
         final String    name      = type.getName();
         final boolean   isPostfix = type == DECPOSTFIX || type == INCPOSTFIX;
@@ -161,7 +178,7 @@
         if (rhsParen) {
             sb.append('(');
         }
-        rhs().toString(sb);
+        rhsStringBuilder.run();
         if (rhsParen) {
             sb.append(')');
         }
@@ -189,7 +206,7 @@
      *
      * @return right hand side or expression node
      */
-    public Node rhs() {
+    public Expression rhs() {
         return rhs;
     }
 
@@ -202,7 +219,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/src/jdk/nashorn/internal/ir/VarNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/VarNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/WhileNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/WhileNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/WithNode.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/WithNode.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/debug/ASTWriter.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/debug/ASTWriter.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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,8 +40,8 @@
 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.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
@@ -167,14 +166,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 +206,19 @@
     }
 
     @Override
-    public boolean enterExecuteNode(final ExecuteNode executeNode) {
-        executeNode.getExpression().accept(this);
+    public boolean enterUnaryNode(final UnaryNode unaryNode) {
+        unaryNode.toString(sb, new Runnable() {
+            @Override
+            public void run() {
+                unaryNode.rhs().accept(PrintVisitor.this);
+            }
+        });
+        return false;
+    }
+
+    @Override
+    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
+        expressionStatement.getExpression().accept(this);
         return false;
     }
 
--- a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Fri Jul 12 20:12:29 2013 +0530
@@ -1263,6 +1263,4 @@
     public Node leaveSUB(final BinaryNode binaryNode) {
         return leaveDefault(binaryNode);
     }
-
-
 }
--- a/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/lookup/Lookup.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/lookup/Lookup.java	Fri Jul 12 20:12:29 2013 +0530
@@ -32,8 +32,6 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import jdk.nashorn.internal.runtime.JSType;
-import jdk.nashorn.internal.runtime.Property;
-import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
 /**
--- a/src/jdk/nashorn/internal/objects/NativeDebug.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/objects/NativeDebug.java	Fri Jul 12 20:12:29 2013 +0530
@@ -179,6 +179,9 @@
 
     /**
      * Returns the property listener count for a script object
+     *
+     * @param self self reference
+     * @param obj  script object whose listener count is returned
      * @return listener count
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Fri Jul 12 20:12:29 2013 +0530
@@ -622,12 +622,15 @@
         case "getMethod":
             final FindProperty find = adaptee.findProperty(__call__, true);
             if (find != null) {
-                final ScriptFunctionImpl func = (ScriptFunctionImpl)getObjectValue(find);
-                // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound
-                // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
-                return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
-                        func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
-                        adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null));
+                final Object value = getObjectValue(find);
+                if (value instanceof ScriptFunction) {
+                    final ScriptFunctionImpl func = (ScriptFunctionImpl)value;
+                    // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound
+                    // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
+                    return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
+                            func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
+                            adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null));
+                }
             }
             throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
         default:
@@ -687,16 +690,19 @@
         final MethodType type = desc.getMethodType();
         if (findData != null) {
             final String name = desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null;
-            final ScriptFunction func = (ScriptFunction)getObjectValue(findData);
+            final Object value = getObjectValue(findData);
+            if (value instanceof ScriptFunction) {
+                final ScriptFunction func = (ScriptFunction)value;
 
-            final MethodHandle methodHandle = getCallMethodHandle(findData, type,
+                final MethodHandle methodHandle = getCallMethodHandle(findData, type,
                     useName ? name : null);
-            if (methodHandle != null) {
-                return new GuardedInvocation(
-                        methodHandle,
-                        adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
-                        testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
-            }
+                if (methodHandle != null) {
+                    return new GuardedInvocation(
+                            methodHandle,
+                            adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
+                            testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
+                }
+             }
         }
 
         switch (hook) {
--- a/src/jdk/nashorn/internal/objects/NativeNumber.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/objects/NativeNumber.java	Fri Jul 12 20:12:29 2013 +0530
@@ -48,7 +48,6 @@
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
 
 /**
--- a/src/jdk/nashorn/internal/objects/NativeObject.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/objects/NativeObject.java	Fri Jul 12 20:12:29 2013 +0530
@@ -27,18 +27,24 @@
 
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
+import java.lang.invoke.MethodHandle;
+import java.util.ArrayList;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.AccessorProperty;
 import jdk.nashorn.internal.runtime.ECMAException;
 import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.Property;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.linker.InvokeByName;
 
 /**
@@ -471,4 +477,114 @@
 
         return false;
     }
+
+    /**
+     * Nashorn extension: Object.bindProperties
+     *
+     * Binds the source object's properties to the target object. Binding
+     * properties allows two-way read/write for the properties of the source object.
+     *
+     * Example:
+     * <pre>
+     * var obj = { x: 34, y: 100 };
+     * var foo = {}
+     *
+     * // bind properties of "obj" to "foo" object
+     * Object.bindProperties(foo, obj);
+     *
+     * // now, we can access/write on 'foo' properties
+     * print(foo.x); // prints obj.x which is 34
+     *
+     * // update obj.x via foo.x
+     * foo.x = "hello";
+     * print(obj.x); // prints "hello" now
+     *
+     * obj.x = 42;   // foo.x also becomes 42
+     * print(foo.x); // prints 42
+     * </pre>
+     * <p>
+     * The source object bound can be a ScriptObject or a ScriptOjectMirror.
+     * null or undefined source object results in TypeError being thrown.
+     * </p>
+     * Example:
+     * <pre>
+     * var obj = loadWithNewGlobal({
+     *    name: "test",
+     *    script: "obj = { x: 33, y: 'hello' }"
+     * });
+     *
+     * // bind 'obj's properties to global scope 'this'
+     * Object.bindProperties(this, obj);
+     * print(x);         // prints 33
+     * print(y);         // prints "hello"
+     * x = Math.PI;      // changes obj.x to Math.PI
+     * print(obj.x);     // prints Math.PI
+     * </pre>
+     *
+     * Limitations of property binding:
+     * <ul>
+     * <li> Only enumerable, immediate (not proto inherited) properties of the source object are bound.
+     * <li> If the target object already contains a property called "foo", the source's "foo" is skipped (not bound).
+     * <li> Properties added to the source object after binding to the target are not bound.
+     * <li> Property configuration changes on the source object (or on the target) is not propagated.
+     * <li> Delete of property on the target (or the source) is not propagated -
+     * only the property value is set to 'undefined' if the property happens to be a data property.
+     * </ul>
+     * <p>
+     * It is recommended that the bound properties be treated as non-configurable
+     * properties to avoid surprises.
+     * </p>
+     *
+     * @param self self reference
+     * @param target the target object to which the source object's properties are bound
+     * @param source the source object whose properties are bound to the target
+     * @return the target object after property binding
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object bindProperties(final Object self, final Object target, final Object source) {
+        // target object has to be a ScriptObject
+        Global.checkObject(target);
+        // check null or undefined source object
+        Global.checkObjectCoercible(source);
+
+        final ScriptObject targetObj = (ScriptObject)target;
+
+        if (source instanceof ScriptObject) {
+            final ScriptObject sourceObj = (ScriptObject)source;
+            final Property[] properties = sourceObj.getMap().getProperties();
+
+            // filter non-enumerable properties
+            final ArrayList<Property> propList = new ArrayList<>();
+            for (Property prop : properties) {
+                if (prop.isEnumerable()) {
+                    propList.add(prop);
+                }
+            }
+
+            if (! propList.isEmpty()) {
+                targetObj.addBoundProperties(sourceObj, propList.toArray(new Property[propList.size()]));
+            }
+        } else if (source instanceof ScriptObjectMirror) {
+            // get enumerable, immediate properties of mirror
+            final ScriptObjectMirror mirror = (ScriptObjectMirror)source;
+            final String[] keys = mirror.getOwnKeys(false);
+            if (keys.length == 0) {
+                // nothing to bind
+                return target;
+            }
+
+            // make accessor properties using dynamic invoker getters and setters
+            final AccessorProperty[] props = new AccessorProperty[keys.length];
+            for (int idx = 0; idx < keys.length; idx++) {
+                final String name = keys[idx];
+                final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, Object.class, ScriptObjectMirror.class);
+                final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, Object.class, ScriptObjectMirror.class, Object.class);
+                props[idx] = (AccessorProperty.create(name, 0, getter, setter));
+            }
+
+            targetObj.addBoundProperties(source, props);
+        }
+
+        return target;
+    }
 }
--- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Fri Jul 12 20:12:29 2013 +0530
@@ -212,10 +212,10 @@
     // Instance of this class is used as global anonymous function which
     // serves as Function.prototype object.
     private static class AnonymousFunction extends ScriptFunctionImpl {
-        private static final PropertyMap map$ = PropertyMap.newMap().setIsShared();
+        private static final PropertyMap anonmap$ = PropertyMap.newMap().setIsShared();
 
         static PropertyMap getInitialMap() {
-            return map$;
+            return anonmap$;
         }
 
         AnonymousFunction(final Global global) {
--- a/src/jdk/nashorn/internal/parser/JSONParser.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/parser/JSONParser.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/parser/Lexer.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/parser/Lexer.java	Fri Jul 12 20:12:29 2013 +0530
@@ -546,14 +546,27 @@
     }
 
     /**
+     * interface to receive line information for multi-line literals.
+     */
+    protected interface LineInfoReceiver {
+        /**
+         * Receives line information
+         * @param line last line number
+         * @param linePosition position of last line
+         */
+        public void lineInfo(int line, int linePosition);
+    }
+
+    /**
      * Check whether the given token represents the beginning of a literal. If so scan
      * the literal and return <tt>true</tt>, otherwise return false.
      *
      * @param token the token.
      * @param startTokenType the token type.
+     * @parasm lir LineInfoReceiver that receives line info for multi-line string literals.
      * @return True if a literal beginning with startToken was found and scanned.
      */
-    protected boolean scanLiteral(final long token, final TokenType startTokenType) {
+    protected boolean scanLiteral(final long token, final TokenType startTokenType, final LineInfoReceiver lir) {
         // Check if it can be a literal.
         if (!canStartLiteral(startTokenType)) {
             return false;
@@ -569,7 +582,7 @@
             return scanRegEx();
         } else if (ch0 == '<') {
             if (ch1 == '<') {
-                return scanHereString();
+                return scanHereString(lir);
             } else if (Character.isJavaIdentifierStart(ch1)) {
                 return scanXMLLiteral();
             }
@@ -1417,7 +1430,7 @@
      *
      * @return TRUE if is a here string.
      */
-    private boolean scanHereString() {
+    private boolean scanHereString(final LineInfoReceiver lir) {
         assert ch0 == '<' && ch1 == '<';
         if (scripting) {
             // Record beginning of here string.
@@ -1446,7 +1459,13 @@
 
             // Record rest of line.
             final State restState = saveState();
+            // keep line number updated
+            int lastLine = line;
+            int lastLinePosition = linePosition;
+
             skipLine(false);
+            lastLine++;
+            lastLinePosition = position;
             restState.setLimit(position);
 
             // Record beginning of string.
@@ -1463,9 +1482,14 @@
                 }
 
                 skipLine(false);
+                lastLine++;
+                lastLinePosition = position;
                 stringEnd = position;
             }
 
+            // notify last line information
+            lir.lineInfo(lastLine, lastLinePosition);
+
             // Record end of string.
             stringState.setLimit(stringEnd);
 
--- a/src/jdk/nashorn/internal/parser/Parser.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/parser/Parser.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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;
@@ -127,6 +130,9 @@
 
     private static final DebugLogger LOG = new DebugLogger("parser");
 
+    /** to receive line information from Lexer when scanning multine literals. */
+    protected final Lexer.LineInfoReceiver lineInfoReceiver;
+
     /**
      * Constructor
      *
@@ -151,6 +157,19 @@
         this.env       = env;
         this.namespace = new Namespace(env.getNamespace());
         this.scripting = env._scripting;
+        if (this.scripting) {
+            this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
+                @Override
+                public void lineInfo(final int line, final int linePosition) {
+                    // update the parser maintained line information
+                    Parser.this.line = line;
+                    Parser.this.linePosition = linePosition;
+                }
+            };
+        } else {
+            // non-scripting mode script can't have multi-line literals
+            this.lineInfoReceiver = null;
+        }
     }
 
     /**
@@ -350,7 +369,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 +535,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 +581,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 +641,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 +855,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 +938,7 @@
             verifyStrictIdent(name, "variable name");
 
             // Assume no init.
-            Node init = null;
+            Expression init = null;
 
             // Look for initializer assignment.
             if (type == ASSIGN) {
@@ -985,20 +1002,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 +1037,7 @@
         next();
 
         expect(LPAREN);
-        final Node test = expression();
+        final Expression test = expression();
         expect(RPAREN);
         final Block pass = getStatement();
 
@@ -1049,8 +1066,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 +1091,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 +1163,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 +1375,7 @@
         // RETURN tested in caller.
         nextOrEOL();
 
-        Node expression = null;
+        Expression expression = null;
 
         // SEMICOLON or expression.
         switch (type) {
@@ -1400,7 +1411,7 @@
         // YIELD tested in caller.
         nextOrEOL();
 
-        Node expression = null;
+        Expression expression = null;
 
         // SEMICOLON or expression.
         switch (type) {
@@ -1502,7 +1513,7 @@
 
             while (type != RBRACE) {
                 // Prepare for next case.
-                Node caseExpression = null;
+                Expression caseExpression = null;
                 final long caseToken = token;
 
                 switch (type) {
@@ -1595,7 +1606,7 @@
         // THROW tested in caller.
         nextOrEOL();
 
-        Node expression = null;
+        Expression expression = null;
 
         // SEMICOLON or expression.
         switch (type) {
@@ -1643,6 +1654,7 @@
         next();
 
         // Container block needed to act as target for labeled break statements
+        final int startLine = line;
         Block outer = newBlock();
 
         // Create try.
@@ -1662,11 +1674,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 +1727,7 @@
             outer = restoreBlock(outer);
         }
 
-        appendStatement(new ExecuteNode(outer.getLineNumber(), outer.getToken(), outer.getFinish(), outer));
+        appendStatement(new BlockStatement(startLine, outer));
     }
 
     /**
@@ -1731,7 +1745,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 +1763,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 +1810,7 @@
         case LPAREN:
             next();
 
-            final Node expression = expression();
+            final Expression expression = expression();
 
             expect(RPAREN);
 
@@ -1804,7 +1818,7 @@
 
         default:
             // In this context some operator tokens mark the start of a literal.
-            if (lexer.scanLiteral(primaryToken, type)) {
+            if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
                 next();
                 return getLiteral();
             }
@@ -1823,17 +1837,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 +1873,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 +1908,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 +1938,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 +1985,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 +2065,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 +2142,7 @@
                 }
             }
 
-            propertyName =  new IdentNode(propertyToken, finish, ident);
+            propertyName =  new IdentNode(propertyToken, finish, ident).setIsPropertyName();
         } else {
             propertyName = propertyName();
         }
@@ -2155,14 +2168,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 +2194,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 +2205,7 @@
                 next();
 
                 // Get array index.
-                final Node rhs = expression();
+                final Expression rhs = expression();
 
                 expect(RBRACKET);
 
@@ -2229,19 +2242,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 +2272,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 +2294,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 +2325,7 @@
                 next();
 
                 // Get array index.
-                final Node index = expression();
+                final Expression index = expression();
 
                 expect(RBRACKET);
 
@@ -2358,9 +2370,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 +2392,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 +2424,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 +2600,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 +2644,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 +2693,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 +2714,7 @@
         case BIT_NOT:
         case NOT:
             next();
-            final Node expr = unaryExpression();
+            final Expression expr = unaryExpression();
             return new UnaryNode(unaryToken, expr);
 
         case INCPREFIX:
@@ -2698,7 +2722,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 +2747,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 +2879,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 +2901,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 +2915,7 @@
                 next();
 
                  // Get the next primary expression.
-                Node rhs = unaryExpression();
+                Expression rhs = unaryExpression();
 
                 // Get precedence of next operator.
                 int nextPrecedence = type.getPrecedence();
@@ -2913,7 +2937,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/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Fri Jul 12 20:12:29 2013 +0530
@@ -147,9 +147,9 @@
      * and are thus rebound with that as receiver
      *
      * @param property  accessor property to rebind
-     * @param delegate  delegate script object to rebind receiver to
+     * @param delegate  delegate object to rebind receiver to
      */
-    public AccessorProperty(final AccessorProperty property, final ScriptObject delegate) {
+    public AccessorProperty(final AccessorProperty property, final Object delegate) {
         super(property);
 
         this.primitiveGetter = bindTo(property.primitiveGetter, delegate);
@@ -248,11 +248,10 @@
         primitiveSetter = null;
 
         if (isParameter() && hasArguments()) {
-            final MethodHandle arguments   = MH.getter(lookup, structure, "arguments", Object.class);
-            final MethodHandle argumentsSO = MH.asType(arguments, arguments.type().changeReturnType(ScriptObject.class));
+            final MethodHandle arguments   = MH.getter(lookup, structure, "arguments", ScriptObject.class);
 
-            objectGetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot), Lookup.GET_OBJECT_TYPE);
-            objectSetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot), Lookup.SET_OBJECT_TYPE);
+            objectGetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.GET_OBJECT_TYPE);
+            objectSetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.SET_OBJECT_TYPE);
         } else {
             final GettersSetters gs = GETTERS_SETTERS.get(structure);
             objectGetter = gs.getters[slot];
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Fri Jul 12 20:12:29 2013 +0530
@@ -62,4 +62,10 @@
      * @param code bytecode to verify
      */
     public void verify(final byte[] code);
+
+    /**
+     * Get next unique script id
+     * @return unique script id
+     */
+    public long getUniqueScriptId();
 }
--- a/src/jdk/nashorn/internal/runtime/Context.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/Context.java	Fri Jul 12 20:12:29 2013 +0530
@@ -36,15 +36,13 @@
 import java.io.PrintWriter;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.util.concurrent.atomic.AtomicLong;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.CodeSigner;
 import java.security.CodeSource;
-import java.security.Permissions;
 import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
 import java.util.Map;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
@@ -96,6 +94,11 @@
         public void verify(final byte[] code) {
             context.verify(code);
         }
+
+        @Override
+        public long getUniqueScriptId() {
+            return context.getUniqueScriptId();
+        }
     }
 
     /** Is Context global debug mode enabled ? */
@@ -197,6 +200,9 @@
     /** Current error manager. */
     private final ErrorManager errors;
 
+    /** Unique id for script. Used only when --loader-per-compile=false */
+    private final AtomicLong uniqueScriptId;
+
     private static final ClassLoader myLoader = Context.class.getClassLoader();
     private static final StructureLoader sharedLoader;
 
@@ -253,7 +259,13 @@
         this.env       = new ScriptEnvironment(options, out, err);
         this._strict   = env._strict;
         this.appLoader = appLoader;
-        this.scriptLoader = env._loader_per_compile? null : createNewLoader();
+        if (env._loader_per_compile) {
+            this.scriptLoader = null;
+            this.uniqueScriptId = null;
+        } else {
+            this.scriptLoader = createNewLoader();
+            this.uniqueScriptId = new AtomicLong();
+        }
         this.errors    = errors;
 
         // if user passed -classpath option, make a class loader with that and set it as
@@ -543,6 +555,21 @@
     }
 
     /**
+     * Checks that the given package can be accessed from current call stack.
+     *
+     * @param fullName fully qualified package name
+     */
+    public static void checkPackageAccess(final String fullName) {
+        final int index = fullName.lastIndexOf('.');
+        if (index != -1) {
+            final SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPackageAccess(fullName.substring(0, index));
+            }
+        }
+    }
+
+    /**
      * Lookup a Java class. This is used for JSR-223 stuff linking in from
      * {@code jdk.nashorn.internal.objects.NativeJava} and {@code jdk.nashorn.internal.runtime.NativeJavaPackage}
      *
@@ -554,19 +581,7 @@
      */
     public Class<?> findClass(final String fullName) throws ClassNotFoundException {
         // check package access as soon as possible!
-        final int index = fullName.lastIndexOf('.');
-        if (index != -1) {
-            final SecurityManager sm = System.getSecurityManager();
-            if (sm != null) {
-                AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                    @Override
-                    public Void run() {
-                        sm.checkPackageAccess(fullName.substring(0, index));
-                        return null;
-                    }
-                }, createNoPermissionsContext());
-            }
-        }
+        checkPackageAccess(fullName);
 
         // try the script -classpath loader, if that is set
         if (classPathLoader != null) {
@@ -707,10 +722,6 @@
         return (context != null) ? context : Context.getContextTrusted();
     }
 
-    private static AccessControlContext createNoPermissionsContext() {
-        return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, new Permissions()) });
-    }
-
     private Object evaluateSource(final Source source, final ScriptObject scope, final ScriptObject thiz) {
         ScriptFunction script = null;
 
@@ -818,4 +829,8 @@
     private ScriptObject newGlobalTrusted() {
         return new Global(this);
     }
+
+    private long getUniqueScriptId() {
+        return uniqueScriptId.getAndIncrement();
+    }
 }
--- a/src/jdk/nashorn/internal/runtime/FunctionScope.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/FunctionScope.java	Fri Jul 12 20:12:29 2013 +0530
@@ -41,7 +41,7 @@
 public class FunctionScope extends ScriptObject implements Scope {
 
     /** Area to store scope arguments. (public for access from scripts.) */
-    public final Object arguments;
+    public final ScriptObject arguments;
 
     /** Flag to indicate that a split method issued a return statement */
     private int splitState = -1;
@@ -53,7 +53,7 @@
      * @param callerScope caller scope
      * @param arguments   arguments
      */
-    public FunctionScope(final PropertyMap map, final ScriptObject callerScope, final Object arguments) {
+    public FunctionScope(final PropertyMap map, final ScriptObject callerScope, final ScriptObject arguments) {
         super(callerScope, map);
         this.arguments = arguments;
         setIsScope();
--- a/src/jdk/nashorn/internal/runtime/PropertyMap.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java	Fri Jul 12 20:12:29 2013 +0530
@@ -260,7 +260,7 @@
      *
      * @return New {@link PropertyMap} with {@link Property} added.
      */
-    PropertyMap addPropertyBind(final AccessorProperty property, final ScriptObject bindTo) {
+    PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) {
         return addProperty(new AccessorProperty(property, bindTo));
     }
 
--- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Fri Jul 12 20:12:29 2013 +0530
@@ -71,6 +71,8 @@
 
     private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class);
 
+    private static final MethodHandle ADD_ZEROTH_ELEMENT = findOwnMH("addZerothElement", Object[].class, Object[].class, Object.class);
+
     /** The parent scope. */
     private final ScriptObject scope;
 
@@ -546,7 +548,21 @@
     }
 
     private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) {
-        return bindName == null ? methodHandle : MH.insertArguments(methodHandle, 1, bindName);
+        if (bindName == null) {
+            return methodHandle;
+        } else {
+            // if it is vararg method, we need to extend argument array with
+            // a new zeroth element that is set to bindName value.
+            final MethodType methodType = methodHandle.type();
+            final int parameterCount = methodType.parameterCount();
+            final boolean isVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
+
+            if (isVarArg) {
+                return MH.filterArguments(methodHandle, 1, MH.insertArguments(ADD_ZEROTH_ELEMENT, 1, bindName));
+            } else {
+                return MH.insertArguments(methodHandle, 1, bindName);
+            }
+        }
     }
 
     /**
@@ -586,6 +602,16 @@
         return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject;
     }
 
+    @SuppressWarnings("unused")
+    private static Object[] addZerothElement(final Object[] args, final Object value) {
+        // extends input array with by adding new zeroth element
+        final Object[] src = (args == null)? ScriptRuntime.EMPTY_ARRAY : args;
+        final Object[] result = new Object[src.length + 1];
+        System.arraycopy(src, 0, result, 1, src.length);
+        result[0] = value;
+        return result;
+    }
+
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
         final Class<?>   own = ScriptFunction.class;
         final MethodType mt  = MH.type(rtype, types);
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Jul 12 20:12:29 2013 +0530
@@ -203,9 +203,19 @@
      * @param source The source object to copy from.
      */
     public void addBoundProperties(final ScriptObject source) {
+        addBoundProperties(source, source.getMap().getProperties());
+    }
+
+    /**
+     * Copy all properties from the array with their receiver bound to the source.
+     *
+     * @param source The source object to copy from.
+     * @param properties The array of properties to copy.
+     */
+    public void addBoundProperties(final ScriptObject source, final Property[] properties) {
         PropertyMap newMap = this.getMap();
 
-        for (final Property property : source.getMap().getProperties()) {
+        for (final Property property : properties) {
             final String key = property.getKey();
 
             if (newMap.findProperty(key) == null) {
@@ -222,6 +232,26 @@
     }
 
     /**
+     * Copy all properties from the array with their receiver bound to the source.
+     *
+     * @param source The source object to copy from.
+     * @param properties The collection of accessor properties to copy.
+     */
+    public void addBoundProperties(final Object source, final AccessorProperty[] properties) {
+        PropertyMap newMap = this.getMap();
+
+        for (final AccessorProperty property : properties) {
+            final String key = property.getKey();
+
+            if (newMap.findProperty(key) == null) {
+                newMap = newMap.addPropertyBind(property, source);
+            }
+        }
+
+        this.setMap(newMap);
+    }
+
+    /**
      * Bind the method handle to the specified receiver, while preserving its original type (it will just ignore the
      * first argument in lieu of the bound argument).
      * @param methodHandle Method handle to bind to.
@@ -1948,7 +1978,12 @@
             return noSuchProperty(desc, request);
         }
 
-        final ScriptFunction func = (ScriptFunction)getObjectValue(find);
+        final Object value = getObjectValue(find);
+        if (! (value instanceof ScriptFunction)) {
+            return createEmptyGetter(desc, name);
+        }
+
+        final ScriptFunction func = (ScriptFunction)value;
         final Object thiz = scopeCall && func.isStrict() ? ScriptRuntime.UNDEFINED : this;
         // TODO: It'd be awesome if we could bind "name" without binding "this".
         return new GuardedInvocation(MH.dropArguments(MH.constant(ScriptFunction.class,
@@ -1968,8 +2003,13 @@
         final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
 
         if (find != null) {
-            final ScriptFunction func = (ScriptFunction)getObjectValue(find);
-            MethodHandle methodHandle = getCallMethodHandle(func, desc.getMethodType(), name);
+            final Object value = getObjectValue(find);
+            ScriptFunction func = null;
+            MethodHandle methodHandle = null;
+            if (value instanceof ScriptFunction) {
+                func = (ScriptFunction)value;
+                methodHandle = getCallMethodHandle(func, desc.getMethodType(), name);
+            }
 
             if (methodHandle != null) {
                 if (scopeAccess && func.isStrict()) {
--- a/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java	Fri Jul 12 20:12:29 2013 +0530
@@ -83,7 +83,7 @@
      */
     public InvokeByName(final String name, final Class<?> targetClass, final Class<?> rtype, final Class<?>... ptypes) {
         this.name = name;
-        getter  = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getItem:" + name, Object.class, targetClass);
+        getter  = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, Object.class, targetClass);
 
         final Class<?>[] finalPtypes;
         final int plength = ptypes.length;
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Fri Jul 12 20:12:29 2013 +0530
@@ -43,6 +43,7 @@
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.support.LinkRequestImpl;
 import jdk.nashorn.internal.objects.NativeJava;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ECMAException;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
@@ -99,6 +100,13 @@
      */
     public static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides) {
         assert types != null && types.length > 0;
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            for (Class<?> type : types) {
+                // check for restricted package access
+                Context.checkPackageAccess(type.getName());
+            }
+        }
         return getAdapterInfo(types).getAdapterClassFor(classOverrides);
     }
 
--- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Fri Jul 12 20:12:29 2013 +0530
@@ -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/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java	Fri Jul 12 20:12:29 2013 +0530
@@ -25,10 +25,14 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import java.lang.reflect.Modifier;
+import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.internal.runtime.Context;
 
 /**
  * Check java reflection permission for java reflective and java.lang.invoke access from scripts
@@ -52,6 +56,25 @@
             throws Exception {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
+            final LinkRequest requestWithoutContext = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
+            final Object self = requestWithoutContext.getReceiver();
+            // allow 'static' access on Class objects representing public classes of non-restricted packages
+            if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) {
+                final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
+                final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
+                // check for 'get' on 'static' property
+                switch (operator) {
+                    case "getProp":
+                    case "getMethod": {
+                       if ("static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
+                           Context.checkPackageAccess(((Class)self).getName());
+                           // let bean linker do the actual linking part
+                           return null;
+                       }
+                    }
+                    break;
+                } // fall through for all other stuff
+            }
             sm.checkPermission(new RuntimePermission("nashorn.JavaReflection"));
         }
         // let the next linker deal with actual linking
--- a/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java	Fri Jul 12 20:12:29 2013 +0530
@@ -57,7 +57,10 @@
     private final LinkedList<Integer> forwardReferences = new LinkedList<>();
 
     /** Current level of zero-width negative lookahead assertions. */
-    private int negativeLookaheadLevel;
+    private int negLookaheadLevel;
+
+    /** Sequential id of current top-level zero-width negative lookahead assertion. */
+    private int negLookaheadGroup;
 
     /** Are we currently inside a character class? */
     private boolean inCharClass = false;
@@ -68,17 +71,18 @@
     private static final String NON_IDENT_ESCAPES = "$^*+(){}[]|\\.?-";
 
     private static class Capture {
-        /**
-         * Zero-width negative lookaheads enclosing the capture.
-         */
-        private final int negativeLookaheadLevel;
+        /** Zero-width negative lookaheads enclosing the capture. */
+        private final int negLookaheadLevel;
+        /** Sequential id of top-level negative lookaheads containing the capture. */
+        private  final int negLookaheadGroup;
 
-        Capture(final int negativeLookaheadLevel) {
-            this.negativeLookaheadLevel = negativeLookaheadLevel;
+        Capture(final int negLookaheadGroup, final int negLookaheadLevel) {
+            this.negLookaheadGroup = negLookaheadGroup;
+            this.negLookaheadLevel = negLookaheadLevel;
         }
 
-        public int getNegativeLookaheadLevel() {
-            return negativeLookaheadLevel;
+        boolean isContained(final int group, final int level) {
+            return group == this.negLookaheadGroup && level >= this.negLookaheadLevel;
         }
 
     }
@@ -152,7 +156,7 @@
         BitVector vec = null;
         for (int i = 0; i < caps.size(); i++) {
             final Capture cap = caps.get(i);
-            if (cap.getNegativeLookaheadLevel() > 0) {
+            if (cap.negLookaheadLevel > 0) {
                 if (vec == null) {
                     vec = new BitVector(caps.size() + 1);
                 }
@@ -311,11 +315,14 @@
             commit(3);
 
             if (isNegativeLookahead) {
-                negativeLookaheadLevel++;
+                if (negLookaheadLevel == 0) {
+                    negLookaheadGroup++;
+                }
+                negLookaheadLevel++;
             }
             disjunction();
             if (isNegativeLookahead) {
-                negativeLookaheadLevel--;
+                negLookaheadLevel--;
             }
 
             if (ch0 == ')') {
@@ -432,20 +439,17 @@
         }
 
         if (ch0 == '(') {
-            boolean capturingParens = true;
             commit(1);
             if (ch0 == '?' && ch1 == ':') {
-                capturingParens = false;
                 commit(2);
+            } else {
+                caps.add(new Capture(negLookaheadGroup, negLookaheadLevel));
             }
 
             disjunction();
 
             if (ch0 == ')') {
                 commit(1);
-                if (capturingParens) {
-                    caps.add(new Capture(negativeLookaheadLevel));
-                }
                 return true;
             }
         }
@@ -675,24 +679,22 @@
                     sb.setLength(sb.length() - 1);
                     octalOrLiteral(Integer.toString(decimalValue), sb);
 
-                } else if (decimalValue <= caps.size() && caps.get(decimalValue - 1).getNegativeLookaheadLevel() > 0) {
-                    //  Captures that live inside a negative lookahead are dead after the
-                    //  lookahead and will be undefined if referenced from outside.
-                    if (caps.get(decimalValue - 1).getNegativeLookaheadLevel() > negativeLookaheadLevel) {
+                } else if (decimalValue <= caps.size()) {
+                    //  Captures inside a negative lookahead are undefined when referenced from the outside.
+                    if (!caps.get(decimalValue - 1).isContained(negLookaheadGroup, negLookaheadLevel)) {
+                        // Reference to capture in negative lookahead, omit from output buffer.
                         sb.setLength(sb.length() - 1);
                     } else {
+                        // Append backreference to output buffer.
                         sb.append(decimalValue);
                     }
-                } else if (decimalValue > caps.size()) {
-                    // Forward reference to a capture group. Forward references are always undefined so we can omit
-                    // it from the output buffer. However, if the target capture does not exist, we need to rewrite
-                    // the reference as hex escape or literal string, so register the reference for later processing.
+                } else {
+                    // Forward references to a capture group are always undefined so we can omit it from the output buffer.
+                    // However, if the target capture does not exist, we need to rewrite the reference as hex escape
+                    // or literal string, so register the reference for later processing.
                     sb.setLength(sb.length() - 1);
                     forwardReferences.add(decimalValue);
                     forwardReferences.add(sb.length());
-                } else {
-                    // Append as backreference
-                    sb.append(decimalValue);
                 }
 
             }
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java	Fri Jul 12 20:12:29 2013 +0530
@@ -183,7 +183,7 @@
 
     // add_code_range, be aware of it returning null!
     public static CodeRangeBuffer addCodeRange(CodeRangeBuffer pbuf, ScanEnvironment env, int from, int to) {
-        if (from >to) {
+        if (from > to) {
             if (env.syntax.allowEmptyRangeInCC()) {
                 return pbuf;
             } else {
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java	Fri Jul 12 20:12:29 2013 +0530
@@ -125,32 +125,8 @@
                 break;
 
             case RAW_BYTE:
-                if (token.base != 0) { /* tok->base != 0 : octal or hexadec. */
-                    byte[] buf = new byte[4];
-                    int psave = p;
-                    int base = token.base;
-                    buf[0] = (byte)token.getC();
-                    int i;
-                    for (i=1; i<4; i++) {
-                        fetchTokenInCC();
-                        if (token.type != TokenType.RAW_BYTE || token.base != base) {
-                            fetched = true;
-                            break;
-                        }
-                        buf[i] = (byte)token.getC();
-                    }
-
-                    if (i == 1) {
-                        arg.v = buf[0] & 0xff;
-                        arg.inType = CCVALTYPE.SB; // goto raw_single
-                    } else {
-                        arg.v = EncodingHelper.mbcToCode(buf, 0, buf.length);
-                        arg.inType = CCVALTYPE.CODE_POINT;
-                    }
-                } else {
-                    arg.v = token.getC();
-                    arg.inType = CCVALTYPE.SB; // raw_single:
-                }
+                arg.v = token.getC();
+                arg.inType = CCVALTYPE.SB; // raw_single:
                 arg.vIsRaw = true;
                 parseCharClassValEntry2(cc, arg); // goto val_entry2
                 break;
@@ -615,31 +591,10 @@
         StringNode node = new StringNode((char)token.getC());
         node.setRaw();
 
-        int len = 1;
-        while (true) {
-            if (len >= 1) {
-                if (len == 1) {
-                    fetchToken();
-                    node.clearRaw();
-                    // !goto string_end;!
-                    return parseExpRepeat(node, group);
-                }
-            }
-
-            fetchToken();
-            if (token.type != TokenType.RAW_BYTE) {
-                /* Don't use this, it is wrong for little endian encodings. */
-                // USE_PAD_TO_SHORT_BYTE_CHAR ...
-
-                newValueException(ERR_TOO_SHORT_MULTI_BYTE_STRING);
-            }
-
-            // important: we don't use 0xff mask here neither in the compiler
-            // (in the template string) so we won't have to mask target
-            // strings when comparing against them in the matcher
-            node.cat((char)token.getC());
-            len++;
-        } // while
+        fetchToken();
+        node.clearRaw();
+        // !goto string_end;!
+        return parseExpRepeat(node, group);
     }
 
     private Node parseExpRepeat(Node target, boolean group) {
--- a/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Mon Jul 08 18:43:41 2013 +0530
+++ b/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Fri Jul 12 20:12:29 2013 +0530
@@ -48,7 +48,7 @@
         var _packages = [];
         var global = this;
         var oldNoSuchProperty = global.__noSuchProperty__;
-        global.__noSuchProperty__ = function(name) {
+        var __noSuchProperty__ = function(name) {
             'use strict';
             for (var i in _packages) {
                 try {
@@ -69,6 +69,11 @@
             }
         }
 
+        Object.defineProperty(global, "__noSuchProperty__", {
+            writable: true, configurable: true, enumerable: false,
+            value: __noSuchProperty__
+        });
+
         var prefix = "[JavaPackage ";
         return function() {
             for (var i in arguments) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8012191.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8012191: noSuchProperty can't cope with vararg functions
+ *
+ * @test
+ * @run
+ */
+
+// ClassCastException: Cannot cast java.lang.String to [Ljava.lang.Object; 
+__noSuchProperty__ = function() {
+    print("obj.__noSuchProperty__ invoked for " + arguments[0]);
+}
+
+nonExistent;
+
+// related issue was seen in JSAdapter __get__, __set__ too
+var obj = new JSAdapter() {
+    __put__: function() {
+        print("JSAdapter.__put__");
+        print(arguments[0]);
+        print(arguments[1]);
+    },
+
+    __get__: function() {
+        print("JSAdapter.__get__");
+        print(arguments[0]);
+    }
+};
+
+obj.x = 343;
+obj.y
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8012191.js.EXPECTED	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,6 @@
+obj.__noSuchProperty__ invoked for nonExistent
+JSAdapter.__put__
+x
+343
+JSAdapter.__get__
+y
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8014785.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8014785: Ability to extend global instance by binding properties of another object
+ *
+ * @test
+ * @run
+ */
+
+var obj = { x: 34, y: 100 };
+var foo = {}
+
+// bind properties of "obj" to "foo" obj
+Object.bindProperties(foo, obj);
+
+// now we can access/write on foo properties
+print("foo.x = " + foo.x); // prints obj.x which is 34
+
+// update obj.x via foo.x
+foo.x = "hello";
+print("obj.x = " + obj.x); // prints "hello" now
+     
+obj.x = 42;   // foo.x also becomes 42
+print("obj.x = " + obj.x); // prints 42
+print("foo.x = " + foo.x); // prints 42
+
+// now bind a mirror object to an object
+var obj = loadWithNewGlobal({
+  name: "test",
+  script: "obj = { x: 33, y: 'hello' }"
+});
+
+Object.bindProperties(this, obj);
+print("x = " + x); // prints 33
+print("y = " + y); // prints "hello"
+
+x = Math.PI;               // changes obj.x to Math.PI
+print("obj.x = " +obj.x);  // prints Math.PI
+
+obj.y = 32;
+print("y = " + y);  // should print 32
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8014785.js.EXPECTED	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,8 @@
+foo.x = 34
+obj.x = hello
+obj.x = 42
+foo.x = 42
+x = 33
+y = hello
+obj.x = 3.141592653589793
+y = 32
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8016681.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8016681: regex capture behaves differently than on V8
+ *
+ * @test
+ * @run
+ */
+
+// regexp similar to the one used in marked.js
+/^((?:[^\n]+\n?(?!( *[-*_]){3,} *(?:\n+|$)| *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)|([^\n]+)\n *(=|-){3,} *\n*))+)\n*/
+    .exec("a\n\nb")
+    .forEach(function(e) { print(e); });
+
+// simplified regexp
+/(x(?!(a))(?!(b))y)/
+    .exec("xy")
+    .forEach(function(e) { print(e); });
+
+// should not match as cross-negative-lookeahead backreference \2 should be undefined
+print(/(x(?!(a))(?!(b)\2))/.exec("xbc"));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8016681.js.EXPECTED	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,15 @@
+a
+
+
+a
+
+undefined
+undefined
+undefined
+undefined
+undefined
+xy
+xy
+undefined
+undefined
+null
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8019822.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8019822: Duplicate name/signature for a function in finally block
+ *
+ * @test
+ */
+try { function (x) /x/ } finally { (function(id) { return id }); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8019963.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8019963: empty char range in regex
+ *
+ * @test
+ * @run
+ */
+
+var re1 = /[\x00-\x08\x0B\x0C\x0E-\x9F\uD800-\uDFFF\uFFFE\uFFFF]/;
+
+print(re1.test("\x00"));
+print(re1.test("\x04"));
+print(re1.test("\x08"));
+print(re1.test("\x0a"));
+print(re1.test("\x0B"));
+print(re1.test("\x0C"));
+print(re1.test("\x0E"));
+print(re1.test("\x10"));
+print(re1.test("\x1A"));
+print(re1.test("\x2F"));
+print(re1.test("\x8E"));
+print(re1.test("\x8F"));
+print(re1.test("\x9F"));
+print(re1.test("\xA0"));
+print(re1.test("\xAF"));
+print(re1.test("\uD800"));
+print(re1.test("\xDA00"));
+print(re1.test("\xDCFF"));
+print(re1.test("\xDFFF"));
+print(re1.test("\xFFFE"));
+print(re1.test("\xFFFF"));
+
+var re2 = /[\x1F\x7F-\x84\x86]/;
+
+print(re2.test("\x1F"));
+print(re2.test("\x2F"));
+print(re2.test("\x3F"));
+print(re2.test("\x7F"));
+print(re2.test("\x80"));
+print(re2.test("\x84"));
+print(re2.test("\x85"));
+print(re2.test("\x86"));
+
+var re3 = /^([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8019963.js.EXPECTED	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,29 @@
+true
+true
+true
+false
+true
+true
+true
+true
+true
+true
+true
+true
+true
+false
+false
+true
+true
+true
+true
+true
+true
+true
+false
+false
+true
+true
+true
+false
+true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8020124.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8020124: explicit conversion needed for switch tag
+ *
+ * @test
+ * @run
+ */
+
+x = {};
+Function("switch((a? x = 1 : 3)) { default: return; }")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8020223.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8020223: ClassCastException: String can not be casted to ScriptFunction
+ *
+ * @test
+ * @run
+ */
+
+__noSuchMethod__ = "";
+
+try {
+    foo();
+    fail("Must have thrown exception");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        fail("TypeError expected, got " + e);
+    }
+}
+
+__noSuchProperty__ = 23;
+
+try {
+    foo;
+    fail("Must have thrown exception");
+} catch (e) {
+    if (! (e instanceof ReferenceError)) {
+        fail("ReferenceError expected, got " + e);
+    }
+}
+
+var obj = new JSAdapter() {
+    __get__: 332,
+    __call__: "hello"
+}
+
+try {
+    obj.foo; // should just be undefined
+} catch (e) {
+    fail("unexpected error : " + e);
+}
+
+try {
+    obj.foo();
+    fail("Must have thrown exception");
+} catch(e) {
+    if (! (e instanceof TypeError)) {
+        fail("TypeError expected, got " + e);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8020325.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8020325: static property does not work on accessible, public classes
+ *
+ * @test
+ * @run
+ */
+
+function printStatic(obj) {
+    print(obj.getClass().static);
+}
+
+printStatic(new java.util.ArrayList());
+printStatic(new java.util.HashMap());
+printStatic(new java.lang.Object());
+printStatic(new (Java.type("java.lang.Object[]"))(0));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8020325.js.EXPECTED	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,4 @@
+[JavaClass java.util.ArrayList]
+[JavaClass java.util.HashMap]
+[JavaClass java.lang.Object]
+[JavaClass [Ljava.lang.Object;]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8020380.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8020380: __noSuchProperty__ defined in mozilla_compat.js script should be non-enumerable
+ *
+ * @test
+ * @run
+ */
+
+load("nashorn:mozilla_compat.js");
+
+var desc = Object.getOwnPropertyDescriptor(this, "__noSuchProperty__");
+if (typeof desc.enumerable != 'boolean' || desc.enumerable != false) {
+    fail("__noSuchProperty__ is enumerable");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8020437.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8020437: Wrong handling of line numbers with multiline string literals
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+print({
+   text: <<EOF
+This is a multiple line
+text inside a sting literal.
+Run this with -scripting option.
+EOF}); f();
+
+function f() {
+   try {
+       func();
+   } catch (e) {
+       print(e.stack.replace(/\\/g, '/'));
+   }
+}
+
+function func() {
+    throw new Error();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8020437.js.EXPECTED	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,5 @@
+[object Object]
+Error
+	at func (test/script/basic/JDK-8020437.js:48)
+	at f (test/script/basic/JDK-8020437.js:41)
+	at <program> (test/script/basic/JDK-8020437.js:37)
--- a/test/script/currently-failing/JDK-8006529.js	Mon Jul 08 18:43:41 2013 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +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.
- * 
- * 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.
- */
-
-/**
- * JDK-8006529 : Methods should not always get callee parameter, and they
- * should not be too eager in creation of scopes.
- *
- * @test
- * @run
- */
-
-/*
- * This test script depends on nashorn Compiler internals. It uses reflection
- * to get access to private field and many public methods of Compiler and
- * FunctionNode classes. Note that this is trusted code and access to such
- * internal package classes and methods is okay. But, if you modify any 
- * Compiler or FunctionNode class, you may have to revisit this script.
- * We cannot use direct Java class (via dynalink bean linker) to Compiler
- * 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 ThrowErrorManager = Java.type("jdk.nashorn.internal.runtime.Context$ThrowErrorManager");
-
-// Compiler class methods and fields
-var parseMethod = Parser.class.getMethod("parse");
-var compileMethod = Compiler.class.getMethod("compile");
-
-// NOTE: private field. But this is a trusted test!
-// Compiler.functionNode
-var functionNodeField = Compiler.class.getDeclaredField("functionNode");
-functionNodeField.setAccessible(true);
-
-// FunctionNode methods
-
-// FunctionNode.getFunctions method
-var getFunctionsMethod = FunctionNode.class.getMethod("getFunctions");
-
-// These are method names of methods in FunctionNode class
-var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'needsScope', 'needsSelfSymbol', 'isSplit', 'hasEval', 'hasWith', 'hasDeepWithOrEval', 'allVarsInScope', 'isStrictMode']
-
-// corresponding Method objects of FunctionNode class
-var functionNodeMethods = {};
-// initialize FunctionNode methods
-(function() {
-    for (var f in allAssertionList) {
-        var method = allAssertionList[f];
-        functionNodeMethods[method] = FunctionNode.class.getMethod(method);
-    }
-})();
-
-// returns "script" functionNode from Compiler instance
-function getScriptNode(compiler) {
-    // compiler.functionNode
-    return functionNodeField.get(compiler);
-}
-
-// returns functionNode.getFunctions().get(0)
-function getFirstFunction(functionNode) {
-    // functionNode.getFunctions().get(0)
-    return getFunctionsMethod.invoke(functionNode).get(0);
-}
-
-// compile(script) -- compiles a script specified as a string with its 
-// source code, returns a jdk.nashorn.internal.ir.FunctionNode object 
-// representing it.
-function compile(source) {
-    var source   = new Source("<no name>", source);
-    var parser   = new Parser(Context.getContext().getEnv(), source, new ThrowErrorManager());
-    var func     = parseMethod.invoke(parser);
-    var compiler = new Compiler(Context.getContext().getEnv(), func);
-
-    compileMethod.invoke(compiler);
-
-    return getScriptNode(compiler);
-};
-
-var allAssertions = (function() {
-    var allAssertions = {}
-    for(var assertion in allAssertionList) {
-        allAssertions[allAssertionList[assertion]] = true
-    }
-    return allAssertions;
-})();
-
-
-// test(f[, assertions...]) tests whether all the specified assertions on the
-// passed function node are true.
-function test(f) {
-    var assertions = {}
-    for(var i = 1; i < arguments.length; ++i) {
-        var assertion = arguments[i]
-        if(!allAssertions[assertion]) {
-            throw "Unknown assertion " + assertion + " for " + f;
-        }
-        assertions[assertion] = true
-    }
-    for(var assertion in allAssertions) {
-        var expectedValue = !!assertions[assertion]
-        if(functionNodeMethods[assertion].invoke(f) !== expectedValue) {
-            throw "Expected " + assertion + " === " + expectedValue + " for " + f;
-        }
-    }
-}
-
-// testFirstFn(script[, assertions...] tests whether all the specified
-// assertions are true in the first function in the given script; "script"
-// is a string with the source text of the script.
-function testFirstFn(script) {
-    arguments[0] = getFirstFunction(compile(script))
-    test.apply(null, arguments)
-}
-
-// ---------------------------------- ACTUAL TESTS START HERE --------------
-
-// The simplest possible functions have no attributes set
-testFirstFn("function f() { }")
-testFirstFn("function f(x) { x }")
-
-// A function referencing a global needs parent scope, and it needs callee
-// (because parent scope is passed through callee)
-testFirstFn("function f() { x }", 'needsCallee', 'needsParentScope')
-
-// A function referencing "arguments" will have to be vararg. It also needs
-// the callee, as it needs to fill out "arguments.callee".
-testFirstFn("function f() { arguments }", 'needsCallee', 'isVarArg')
-
-// A function referencing "arguments" will have to be vararg. If it is
-// strict, it will not have to have a callee, though.
-testFirstFn("function f() {'use strict'; arguments }", 'isVarArg', 'isStrictMode')
-
-// A function defining "arguments" as a parameter will not be vararg.
-testFirstFn("function f(arguments) { arguments }")
-
-// A function defining "arguments" as a nested function will not be vararg.
-testFirstFn("function f() { function arguments() {}; arguments; }")
-
-// A function defining "arguments" as a local variable will be vararg.
-testFirstFn("function f() { var arguments; arguments; }", 'isVarArg', 'needsCallee')
-
-// A self-referencing function defined as a statement doesn't need a self 
-// symbol, as it'll rather obtain itself from the parent scope.
-testFirstFn("function f() { f() }", 'needsCallee', 'needsParentScope')
-
-// A self-referencing function defined as an expression needs a self symbol,
-// as it can't obtain itself from the parent scope.
-testFirstFn("(function f() { f() })", 'needsCallee', 'needsSelfSymbol')
-
-// A child function accessing parent's variable triggers the need for scope
-// in parent
-testFirstFn("(function f() { var x; function g() { x } })", 'needsScope')
-
-// A child function accessing parent's parameter triggers the need for scope
-// in parent
-testFirstFn("(function f(x) { function g() { x } })", 'needsScope')
-
-// A child function accessing a global variable triggers the need for parent
-// scope in parent
-testFirstFn("(function f() { function g() { x } })", 'needsParentScope', 'needsCallee')
-
-// A child function redefining a local variable from its parent should not 
-// affect the parent function in any way
-testFirstFn("(function f() { var x; function g() { var x; x } })")
-
-// Using "with" unleashes a lot of needs: parent scope, callee, own scope, 
-// and all variables in scope. Actually, we could make "with" less wasteful,
-// and only put those variables in scope that it actually references, similar
-// to what nested functions do with variables in their parents.
-testFirstFn("(function f() { var o; with(o) {} })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasWith', 'hasDeepWithOrEval', 'allVarsInScope')
-
-// Using "eval" is as bad as using "with" with the added requirement of
-// being vararg, 'cause we don't know if eval will be using "arguments".
-testFirstFn("(function f() { eval() })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasEval', 'isVarArg', 'hasDeepWithOrEval', 'allVarsInScope')
-
-// Nested function using "with" is pretty much the same as the parent
-// function needing with.
-testFirstFn("(function f() { function g() { var o; with(o) {} } })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasDeepWithOrEval', 'allVarsInScope')
-// Nested function using "eval" is almost the same as parent function using
-// eval, but at least the parent doesn't have to be vararg.
-testFirstFn("(function f() { function g() { eval() } })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasDeepWithOrEval', 'allVarsInScope')
-
-// Function with 250 named parameters is ordinary
-testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250) { p250 = p249 }")
-
-// Function with 251 named parameters is variable arguments
-testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250, p251) { p250 = p251 }", 'isVarArg')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/error/JDK-8020437-2.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8020437: Wrong handling of line numbers with multiline string literals
+ *
+ * @test/compile-error
+ * @option -scripting
+ */
+
+print({
+   text: <<EOF
+This is a multiple line
+text inside a sting literal.
+Run this with -scripting option.
+EOF}); var x++; // syntax error in same line
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/error/JDK-8020437-2.js.EXPECTED	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,3 @@
+test/script/error/JDK-8020437-2.js:36:12 Expected ; but found ++
+EOF}); var x++; // syntax error in same line
+            ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/error/JDK-8020437.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8020437: Wrong handling of line numbers with multiline string literals
+ *
+ * @test/compile-error
+ * @option -scripting
+ */
+
+print({
+   text: <<EOF
+This is a multiple line
+text inside a sting literal.
+Run this with -scripting option.
+EOF);  // missing "}" to end object literal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/error/JDK-8020437.js.EXPECTED	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,3 @@
+test/script/error/JDK-8020437.js:36:3 Expected comma but found )
+EOF);  // missing "}" to end object literal
+   ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/trusted/JDK-8006529.js	Fri Jul 12 20:12:29 2013 +0530
@@ -0,0 +1,246 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8006529 : Methods should not always get callee parameter, and they
+ * should not be too eager in creation of scopes.
+ *
+ * @test
+ * @run
+ */
+
+/*
+ * This test script depends on nashorn Compiler internals. It uses reflection
+ * to get access to private field and many public methods of Compiler and
+ * FunctionNode classes. Note that this is trusted code and access to such
+ * internal package classes and methods is okay. But, if you modify any 
+ * Compiler or FunctionNode class, you may have to revisit this script.
+ * We cannot use direct Java class (via dynalink bean linker) to Compiler
+ * 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 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 = ExpressionStatement.class.getMethod("getExpression")
+var rhsMethod = UnaryNode.class.getMethod("rhs")
+var lhsMethod = BinaryNode.class.getMethod("lhs")
+var binaryRhsMethod = BinaryNode.class.getMethod("rhs")
+var debugIdMethod = Debug.class.getMethod("id", java.lang.Object.class)
+
+// These are method names of methods in FunctionNode class
+var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'needsSelfSymbol', 'isSplit', 'hasEval', 'allVarsInScope', 'isStrict']
+
+// corresponding Method objects of FunctionNode class
+var functionNodeMethods = {};
+// initialize FunctionNode methods
+(function() {
+    for (var f in allAssertionList) {
+        var method = allAssertionList[f];
+        functionNodeMethods[method] = FunctionNode.class.getMethod(method);
+    }
+})();
+
+// returns functionNode.getBody().getStatements().get(0)
+function getFirstFunction(functionNode) {
+    var f = findFunction(getBodyMethod.invoke(functionNode))
+    if (f == null) {
+        throw new Error();
+    }
+    return f;
+}
+
+function findFunction(node) {
+    if(node instanceof Block) {
+        var stmts = getStatementsMethod.invoke(node)
+        for(var i = 0; i < stmts.size(); ++i) {
+            var retval = findFunction(stmts.get(i))
+            if(retval != null) {
+                return retval;
+            }
+        }
+    } else if(node instanceof VarNode) {
+        return findFunction(getInitMethod.invoke(node))
+    } else if(node instanceof UnaryNode) {
+        return findFunction(rhsMethod.invoke(node))
+    } else if(node instanceof BinaryNode) {
+        return findFunction(lhsMethod.invoke(node)) || findFunction(binaryRhsMethod.invoke(node))
+	} else if(node instanceof ExpressionStatement) {
+		return findFunction(getExpressionMethod.invoke(node))
+    } else if(node instanceof FunctionNode) {
+        return node
+    }
+}
+
+var getContextMethod = Context.class.getMethod("getContext")
+var getEnvMethod = Context.class.getMethod("getEnv")
+
+// compile(script) -- compiles a script specified as a string with its 
+// source code, returns a jdk.nashorn.internal.ir.FunctionNode object 
+// representing it.
+function compile(source) {
+    var source   = new Source("<no name>", source);
+
+    var env = getEnvMethod.invoke(getContextMethod.invoke(null))
+
+    var parser   = new Parser(env, source, new ThrowErrorManager());
+    var func     = parseMethod.invoke(parser);
+
+    var compiler = new Compiler(env);
+
+    return compileMethod.invoke(compiler, func);
+};
+
+var allAssertions = (function() {
+    var allAssertions = {}
+    for(var assertion in allAssertionList) {
+        allAssertions[allAssertionList[assertion]] = true
+    }
+    return allAssertions;
+})();
+
+
+// test(f[, assertions...]) tests whether all the specified assertions on the
+// passed function node are true.
+function test(f) {
+    var assertions = {}
+    for(var i = 1; i < arguments.length; ++i) {
+        var assertion = arguments[i]
+        if(!allAssertions[assertion]) {
+            throw "Unknown assertion " + assertion + " for " + f;
+        }
+        assertions[assertion] = true
+    }
+    for(var assertion in allAssertions) {
+        var expectedValue = !!assertions[assertion]
+        var actualValue = functionNodeMethods[assertion].invoke(f)
+        if(actualValue !== expectedValue) {
+            throw "Expected " + assertion + " === " + expectedValue + ", got " + actualValue + " for " + f + ":" + debugIdMethod.invoke(null, f);
+        }
+    }
+}
+
+// testFirstFn(script[, assertions...] tests whether all the specified
+// assertions are true in the first function in the given script; "script"
+// is a string with the source text of the script.
+function testFirstFn(script) {
+    arguments[0] = getFirstFunction(compile(script))
+    test.apply(null, arguments)
+}
+
+// ---------------------------------- ACTUAL TESTS START HERE --------------
+
+// The simplest possible functions have no attributes set
+testFirstFn("function f() { }")
+testFirstFn("function f(x) { x }")
+
+// A function referencing a global needs parent scope, and it needs callee
+// (because parent scope is passed through callee)
+testFirstFn("function f() { x }", 'needsCallee', 'needsParentScope')
+
+// A function referencing "arguments" will have to be vararg. It also needs
+// the callee, as it needs to fill out "arguments.callee".
+testFirstFn("function f() { arguments }", 'needsCallee', 'isVarArg')
+
+// A function referencing "arguments" will have to be vararg. If it is
+// strict, it will not have to have a callee, though.
+testFirstFn("function f() {'use strict'; arguments }", 'isVarArg', 'isStrict')
+
+// A function defining "arguments" as a parameter will not be vararg.
+testFirstFn("function f(arguments) { arguments }")
+
+// A function defining "arguments" as a nested function will not be vararg.
+testFirstFn("function f() { function arguments() {}; arguments; }")
+
+// A function defining "arguments" as a local variable will be vararg.
+testFirstFn("function f() { var arguments; arguments; }", 'isVarArg', 'needsCallee')
+
+// A self-referencing function defined as a statement doesn't need a self 
+// symbol, as it'll rather obtain itself from the parent scope.
+testFirstFn("function f() { f() }", 'needsCallee', 'needsParentScope')
+
+// A self-referencing function defined as an expression needs a self symbol,
+// as it can't obtain itself from the parent scope.
+testFirstFn("(function f() { f() })", 'needsCallee', 'needsSelfSymbol')
+
+// A child function accessing parent's variable triggers the need for scope
+// in parent
+testFirstFn("(function f() { var x; function g() { x } })", 'hasScopeBlock')
+
+// A child function accessing parent's parameter triggers the need for scope
+// in parent
+testFirstFn("(function f(x) { function g() { x } })", 'hasScopeBlock')
+
+// A child function accessing a global variable triggers the need for parent
+// scope in parent
+testFirstFn("(function f() { function g() { x } })", 'needsParentScope', 'needsCallee')
+
+// A child function redefining a local variable from its parent should not 
+// affect the parent function in any way
+testFirstFn("(function f() { var x; function g() { var x; x } })")
+
+// Using "with" on its own doesn't do much.
+testFirstFn("(function f() { var o; with(o) {} })")
+
+// "with" referencing a local variable triggers scoping.
+testFirstFn("(function f() { var x; var y; with(x) { y } })", 'hasScopeBlock')
+
+// "with" referencing a non-local variable triggers parent scope.
+testFirstFn("(function f() { var x; with(x) { y } })", 'needsCallee', 'needsParentScope')
+
+// Nested function using "with" is pretty much the same as the parent
+// function needing with.
+testFirstFn("(function f() { function g() { var o; with(o) {} } })")
+
+// Nested function using "with" referencing a local variable.
+testFirstFn("(function f() { var x; function g() { var o; with(o) { x } } })", 'hasScopeBlock')
+
+// Using "eval" triggers pretty much everything. The function even needs to be
+// vararg, 'cause we don't know if eval will be using "arguments".
+testFirstFn("(function f() { eval() })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'hasEval', 'isVarArg', 'allVarsInScope')
+
+// Nested function using "eval" is almost the same as parent function using
+// eval, but at least the parent doesn't have to be vararg.
+testFirstFn("(function f() { function g() { eval() } })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'allVarsInScope')
+
+// Function with 250 named parameters is ordinary
+testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250) { p250 = p249 }")
+
+// Function with 251 named parameters is variable arguments
+testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250, p251) { p250 = p251 }", 'isVarArg')
--- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Fri Jul 12 20:12:29 2013 +0530
@@ -36,6 +36,7 @@
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.Callable;
 import javax.script.Bindings;
 import javax.script.Compilable;
@@ -345,6 +346,23 @@
     }
 
     @Test
+    /**
+     * Try passing non-interface Class object for interface implementation.
+     */
+    public void getNonInterfaceGetInterfaceTest() {
+        final ScriptEngineManager manager = new ScriptEngineManager();
+        final ScriptEngine engine = manager.getEngineByName("nashorn");
+        try {
+            log(Objects.toString(((Invocable)engine).getInterface(Object.class)));
+            fail("Should have thrown IllegalArgumentException");
+        } catch (final Exception exp) {
+            if (! (exp instanceof IllegalArgumentException)) {
+                fail("IllegalArgumentException expected, got " + exp);
+            }
+        }
+    }
+
+    @Test
     public void accessGlobalTest() {
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
@@ -927,4 +945,35 @@
         Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]");
         Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]");
     }
+
+    @Test
+    /**
+     * Check that script can't implement sensitive package interfaces.
+     */
+    public void checkSensitiveInterfaceImplTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final Object[] holder = new Object[1];
+        e.put("holder", holder);
+        // put an empty script object into array
+        e.eval("holder[0] = {}");
+        // holder[0] is an object of some subclass of ScriptObject
+        Class ScriptObjectClass = holder[0].getClass().getSuperclass();
+        Class PropertyAccessClass = ScriptObjectClass.getInterfaces()[0];
+        // implementation methods for PropertyAccess class
+        e.eval("function set() {}; function get() {}; function getInt(){} " +
+               "function getDouble(){}; function getLong() {}; " +
+               "this.delete = function () {}; function has() {}; " +
+               "function hasOwnProperty() {}");
+
+        // get implementation of a restricted package interface
+        try {
+            log(Objects.toString(((Invocable)e).getInterface((Class<?>)PropertyAccessClass)));
+            fail("should have thrown SecurityException");
+        } catch (final Exception exp) {
+            if (! (exp instanceof SecurityException)) {
+                fail("SecurityException expected, got " + exp);
+            }
+        }
+    }
 }
--- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java	Mon Jul 08 18:43:41 2013 +0530
+++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java	Fri Jul 12 20:12:29 2013 +0530
@@ -145,4 +145,55 @@
 
         fail("Cannot find nashorn factory!");
     }
+
+    @Test
+    /**
+     * Test repeated evals with --loader-per-compile=false
+     * We used to get "class redefinition error".
+     */
+    public void noLoaderPerCompilerTest() {
+        final ScriptEngineManager sm = new ScriptEngineManager();
+        for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+            if (fac instanceof NashornScriptEngineFactory) {
+                final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
+                final String[] options = new String[] { "--loader-per-compile=false" };
+                final ScriptEngine e = nfac.getScriptEngine(options);
+                try {
+                    e.eval("2 + 3");
+                    e.eval("4 + 4");
+                } catch (final ScriptException se) {
+                    se.printStackTrace();
+                    fail(se.getMessage());
+                }
+                return;
+            }
+        }
+        fail("Cannot find nashorn factory!");
+    }
+
+    @Test
+    /**
+     * Test that we can use same script name in repeated evals with --loader-per-compile=false
+     * We used to get "class redefinition error" as name was derived from script name.
+     */
+    public void noLoaderPerCompilerWithSameNameTest() {
+        final ScriptEngineManager sm = new ScriptEngineManager();
+        for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+            if (fac instanceof NashornScriptEngineFactory) {
+                final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
+                final String[] options = new String[] { "--loader-per-compile=false" };
+                final ScriptEngine e = nfac.getScriptEngine(options);
+                e.put(ScriptEngine.FILENAME, "test.js");
+                try {
+                    e.eval("2 + 3");
+                    e.eval("4 + 4");
+                } catch (final ScriptException se) {
+                    se.printStackTrace();
+                    fail(se.getMessage());
+                }
+                return;
+            }
+        }
+        fail("Cannot find nashorn factory!");
+    }
 }