changeset 1036:4af4491477eb

Merge
author asaha
date Tue, 16 Sep 2014 13:59:37 -0700
parents 0bcc64d0d193 (current diff) 1196f17cf7bc (diff)
children 83e53aa5acf2
files bin/fixorphantests.sh bin/fixwhitespace.sh bin/jjsdebug.sh bin/rm-non-tracked.sh bin/run_octane.sh test/script/basic/JDK-8048079_1.js test/script/basic/JDK-8048079_1.js.EXPECTED test/script/basic/JDK-8048079_2.js test/script/basic/JDK-8048079_2.js.EXPECTED
diffstat 146 files changed, 4099 insertions(+), 845 deletions(-) [+]
line wrap: on
line diff
--- a/bin/fixorphantests.sh	Thu Sep 11 15:34:13 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-#!/bin/sh
-#
-# 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.
-#
-
-#ensure that all tests tagged with @test are also tagged with @run
-
-for f in $(find test/script/basic/*.js); do 
-    grep @test $f >/dev/null
-    TEST=$?
-    grep @run $f >/dev/null
-    RUN=$?    
-
-    if [ $TEST -eq 0 ] && [ ! $RUN -eq 0 ]; then		
-	echo "repairing ${f}..."
-	TEMP=$(mktemp /tmp/scratch.XXXXXX)
-
-	#IFS='', -raw flag to preserve white space
-	while IFS='' read -r line; do 	    
-	    echo $line | grep @test >/dev/null
-	    TEST=$?
-	    printf "%s\n" "$line" 
-	    if [ $TEST -eq 0 ]; then
-		printf "%s\n" "$line" | sed s/@test/@run/g 
-	    fi	   
-	done < $f >$TEMP
-
-	cp $TEMP $f
-
-	rm -fr $TEMP
-    fi
-
-done
--- a/bin/fixwhitespace.sh	Thu Sep 11 15:34:13 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-#!/bin/bash
-#
-# 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.
-#
-
-fix() {
-    #convert tabs to spaces
-    find . -name $1 -exec sed -i "" 's/	/    /g' {} \;
-    #remove trailing whitespace
-    find . -name $1 -exec sed -i "" 's/[ 	]*$//' \{} \;
-}
-
-if [ ! -z $1 ]; then 
-    fix $1;
-else
-    fix "*.java"
-    fix "*.js"
-fi
--- a/bin/jjsdebug.sh	Thu Sep 11 15:34:13 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2014, 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.
-#
-
-$JAVA_HOME/bin/jjs -J-Djava.ext.dirs=`dirname $0`/../dist -J-agentlib:jdwp=transport=dt_socket,address=localhost:9009,server=y,suspend=y $*
--- a/bin/rm-non-tracked.sh	Thu Sep 11 15:34:13 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-#!/bin/bash
-#
-# 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.
-#
-hg status|grep ^\?|awk '{print $2}'|xargs rm
--- a/bin/run_octane.sh	Thu Sep 11 15:34:13 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2010, 2014, 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.
-#
-
-LOG="./octane_$(date|sed "s/ /_/g"|sed "s/:/_/g").log"
-
-run_one() {
-    sh ../bin/runopt.sh -scripting ../test/script/basic/run-octane.js -- $1 --verbose --iterations 25 | tee -a $LOG
-}
-
-if [ -z $1 ]; then 
-
-    run_one "box2d"
-    run_one "code-load"
-    run_one "crypto"
-    run_one "deltablue"
-    run_one "earley-boyer"
-    run_one "gbemu"
-    run_one "mandreel"
-    run_one "navier-stokes"
-    run_one "pdfjs"
-    run_one "raytrace"
-    run_one "regexp"
-    run_one "richards"
-    run_one "splay"
-    run_one "typescript"
-    run_one "zlib"
-
-else
-    run_one $1
-fi
--- a/make/build.xml	Thu Sep 11 15:34:13 2014 -0700
+++ b/make/build.xml	Tue Sep 16 13:59:37 2014 -0700
@@ -340,6 +340,13 @@
     permission java.util.PropertyPermission "nashorn.test.*", "read";
 };
 
+grant codeBase "file:/${basedir}/test/script/basic/es6/*" {
+    permission java.io.FilePermission "${basedir}/test/script/-", "read";
+    permission java.io.FilePermission "$${user.dir}", "read";
+    permission java.util.PropertyPermission "user.dir", "read";
+    permission java.util.PropertyPermission "nashorn.test.*", "read";
+};
+
 grant codeBase "file:/${basedir}/test/script/basic/JDK-8010946-privileged.js" {
     permission java.util.PropertyPermission "java.security.policy", "read";
 };
--- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Tue Sep 16 13:59:37 2014 -0700
@@ -36,6 +36,7 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
 import static jdk.nashorn.internal.ir.Symbol.HAS_OBJECT_VALUE;
+import static jdk.nashorn.internal.ir.Symbol.IS_CONST;
 import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF;
 import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL;
 import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
@@ -83,11 +84,13 @@
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.Property;
-import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.ErrorManager;
+import jdk.nashorn.internal.runtime.JSErrorType;
+import jdk.nashorn.internal.runtime.ParserException;
+import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
@@ -101,7 +104,7 @@
  * visitor.
  */
 @Logger(name="symbols")
-final class AssignSymbols extends NodeOperatorVisitor<LexicalContext> implements Loggable {
+final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggable {
     private final DebugLogger log;
     private final boolean     debug;
 
@@ -190,22 +193,21 @@
      * @param body the body of the FunctionNode we are entering
      */
     private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
-        // This visitor will assign symbol to all declared variables, except function declarations (which are taken care
-        // in a separate step above) and "var" declarations in for loop initializers.
-        //
+        // This visitor will assign symbol to all declared variables, except "var" declarations in for loop initializers.
         body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
-            public boolean enterFunctionNode(final FunctionNode nestedFn) {
-                // Don't descend into nested functions
-                return false;
+            protected boolean enterDefault(final Node node) {
+                // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
+                // This will also prevent visiting nested functions (as FunctionNode is an expression).
+                return !(node instanceof Expression);
             }
 
             @Override
             public Node leaveVarNode(final VarNode varNode) {
                 if (varNode.isStatement()) {
                     final IdentNode ident  = varNode.getName();
-                    final Symbol    symbol = defineSymbol(body, ident.getName(), IS_VAR);
-                    functionNode.addDeclaredSymbol(symbol);
+                    final Block block = varNode.isBlockScoped() ? getLexicalContext().getCurrentBlock() : body;
+                    final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
                     if (varNode.isFunctionDeclaration()) {
                         symbol.setIsFunctionDeclaration();
                     }
@@ -303,23 +305,31 @@
         return functionNode.setBody(lc, body.setStatements(lc, newStatements));
     }
 
-    private Symbol defineGlobalSymbol(final Block block, final String name) {
-        return defineSymbol(block, name, IS_GLOBAL);
-    }
-
     /**
      * Defines a new symbol in the given block.
      *
      * @param block        the block in which to define the symbol
      * @param name         name of symbol.
+     * @param origin       origin node
      * @param symbolFlags  Symbol flags.
      *
      * @return Symbol for given name or null for redefinition.
      */
-    private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) {
+    private Symbol defineSymbol(final Block block, final String name, final Node origin, final int symbolFlags) {
         int    flags  = symbolFlags;
-        Symbol symbol = findSymbol(block, name); // Locate symbol.
-        final boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL;
+        final boolean isBlockScope = (flags & IS_LET) != 0 || (flags & IS_CONST) != 0;
+        final boolean isGlobal     = (flags & KINDMASK) == IS_GLOBAL;
+
+        Symbol symbol;
+        final FunctionNode function;
+        if (isBlockScope) {
+            // block scoped variables always live in current block, no need to look for existing symbols in parent blocks.
+            symbol = block.getExistingSymbol(name);
+            function = lc.getCurrentFunction();
+        } else {
+            symbol = findSymbol(block, name);
+            function = lc.getFunction(block);
+        }
 
         // Global variables are implicitly always scope variables too.
         if (isGlobal) {
@@ -333,7 +343,6 @@
         final boolean isParam = (flags & KINDMASK) == IS_PARAM;
         final boolean isVar =   (flags & KINDMASK) == IS_VAR;
 
-        final FunctionNode function = lc.getFunction(block);
         if (symbol != null) {
             // Symbol was already defined. Check if it needs to be redefined.
             if (isParam) {
@@ -345,10 +354,21 @@
                     throw new AssertionError("duplicate parameter");
                 }
             } else if (isVar) {
-                if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET) {
+                if (isBlockScope) {
+                    // Check redeclaration in same block
+                    if (symbol.hasBeenDeclared()) {
+                        throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
+                    } else {
+                        symbol.setHasBeenDeclared();
+                    }
+                } else if ((flags & IS_INTERNAL) != 0) {
                     // Always create a new definition.
                     symbol = null;
                 } else {
+                    // Found LET or CONST in parent scope of same function - s SyntaxError
+                    if (symbol.isBlockScoped() && isLocal(lc.getCurrentFunction(), symbol)) {
+                        throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
+                    }
                     // Not defined in this function. Create a new definition.
                     if (!isLocal(function, symbol) || symbol.less(IS_VAR)) {
                         symbol = null;
@@ -359,10 +379,10 @@
 
         if (symbol == null) {
             // If not found, then create a new one.
-            Block symbolBlock;
+            final Block symbolBlock;
 
             // Determine where to create it.
-            if (isVar && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) {
+            if (isVar && ((flags & IS_INTERNAL) != 0 || isBlockScope)) {
                 symbolBlock = block; //internal vars are always defined in the block closest to them
             } else if (isGlobal) {
                 symbolBlock = lc.getOutermostFunction().getBody();
@@ -420,15 +440,30 @@
     @Override
     public boolean enterBlock(final Block block) {
         start(block);
-        block.clearSymbols();
 
         if (lc.isFunctionBody()) {
+            block.clearSymbols();
+            final FunctionNode fn = lc.getCurrentFunction();
+            if (isUnparsedFunction(fn)) {
+                // It's a skipped nested function. Just mark the symbols being used by it as being in use.
+                for(final String name: compiler.getScriptFunctionData(fn.getId()).getExternalSymbolNames()) {
+                    nameIsUsed(name, null);
+                }
+                // Don't bother descending into it, it must be empty anyway.
+                assert block.getStatements().isEmpty();
+                return false;
+            }
+
             enterFunctionBody();
         }
 
         return true;
     }
 
+    private boolean isUnparsedFunction(final FunctionNode fn) {
+        return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction();
+    }
+
     @Override
     public boolean enterCatchNode(final CatchNode catchNode) {
         final IdentNode exception = catchNode.getException();
@@ -441,7 +476,10 @@
         // If the name of the exception starts with ":e", this is a synthetic catch block, likely a catch-all. Its
         // symbol is naturally internal, and should be treated as such.
         final boolean isInternal = exname.startsWith(EXCEPTION_PREFIX.symbolName());
-        defineSymbol(block, exname, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE);
+        // IS_LET flag is required to make sure symbol is not visible outside catch block. However, we need to
+        // clear the IS_LET flag after creation to allow redefinition of symbol inside the catch block.
+        final Symbol symbol = defineSymbol(block, exname, catchNode, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE);
+        symbol.clearFlag(IS_LET);
 
         return true;
     }
@@ -452,15 +490,13 @@
 
         initFunctionWideVariables(functionNode, body);
 
-        if (functionNode.isProgram()) {
-            initGlobalSymbols(body);
-        } else if (!functionNode.isDeclared() && !functionNode.isAnonymous()) {
+        if (!functionNode.isProgram() && !functionNode.isDeclared() && !functionNode.isAnonymous()) {
             // It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's
             // anonymous.
             final String name = functionNode.getIdent().getName();
             assert name != null;
             assert body.getExistingSymbol(name) == null;
-            defineSymbol(body, name, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
+            defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
             if(functionNode.allVarsInScope()) { // basically, has deep eval
                 lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
             }
@@ -471,41 +507,48 @@
 
     @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
-        // TODO: once we have information on symbols used by nested functions, we can stop descending into nested
-        // functions with on-demand compilation, e.g. add
-        // if(!thisProperties.isEmpty() && env.isOnDemandCompilation()) {
-        //    return false;
-        // }
         start(functionNode, false);
 
         thisProperties.push(new HashSet<String>());
 
-        //an outermost function in our lexical context that is not a program
-        //is possible - it is a function being compiled lazily
         if (functionNode.isDeclared()) {
+            // Can't use lc.getCurrentBlock() as we can have an outermost function in our lexical context that
+            // is not a program - it is a function being compiled on-demand.
             final Iterator<Block> blocks = lc.getBlocks();
             if (blocks.hasNext()) {
-                defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0));
+                final IdentNode ident = functionNode.getIdent();
+                defineSymbol(blocks.next(), ident.getName(), ident, IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0));
             }
         }
 
+        // Every function has a body, even the ones skipped on reparse (they have an empty one). We're
+        // asserting this as even for those, enterBlock() must be invoked to correctly process symbols that
+        // are used in them.
+        assert functionNode.getBody() != null;
+
         return true;
     }
 
     @Override
     public boolean enterVarNode(final VarNode varNode) {
         start(varNode);
-        defineSymbol(lc.getCurrentBlock(), varNode.getName().getName(), IS_VAR | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0));
         return true;
     }
 
+    @Override
+    public Node leaveVarNode(final VarNode varNode) {
+        final IdentNode ident = varNode.getName();
+        defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0));
+        return super.leaveVarNode(varNode);
+    }
+
     private Symbol exceptionSymbol() {
         return newObjectInternal(EXCEPTION_PREFIX);
     }
 
     /**
      * This has to run before fix assignment types, store any type specializations for
-     * paramters, then turn then to objects for the generic version of this method
+     * parameters, then turn them into objects for the generic version of this method.
      *
      * @param functionNode functionNode
      */
@@ -597,7 +640,7 @@
     }
 
     private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) {
-        defineSymbol(block, cc.symbolName(), flags).setNeedsSlot(true);
+        defineSymbol(block, cc.symbolName(), null, flags).setNeedsSlot(true);
     }
 
     private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) {
@@ -608,7 +651,7 @@
             initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE);
             if (functionNode.needsArguments()) {
                 initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE);
-                defineSymbol(body, ARGUMENTS_VAR.symbolName(), IS_VAR | HAS_OBJECT_VALUE);
+                defineSymbol(body, ARGUMENTS_VAR.symbolName(), null, IS_VAR | HAS_OBJECT_VALUE);
             }
         }
 
@@ -617,20 +660,6 @@
         initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL);
     }
 
-
-    /**
-     * Move any properties from the global map into the scope of this function (which must be a program function).
-     * @param block the function node body for which to init scope vars
-     */
-    private void initGlobalSymbols(final Block block) {
-        final PropertyMap map = Context.getGlobalMap();
-
-        for (final Property property : map.getProperties()) {
-            final Symbol symbol = defineGlobalSymbol(block, property.getKey());
-            log.info("Added global symbol from property map ", symbol);
-        }
-    }
-
     /**
      * Initialize parameters for function node.
      * @param functionNode the function node
@@ -639,7 +668,7 @@
         final boolean isVarArg = functionNode.isVarArg();
         final boolean scopeParams = functionNode.allVarsInScope() || isVarArg;
         for (final IdentNode param : functionNode.getParameters()) {
-            final Symbol symbol = defineSymbol(body, param.getName(), IS_PARAM);
+            final Symbol symbol = defineSymbol(body, param.getName(), param, IS_PARAM);
             if(scopeParams) {
                 // NOTE: this "set is scope" is a poor substitute for clear expression of where the symbol is stored.
                 // It will force creation of scopes where they would otherwise not necessarily be needed (functions
@@ -665,10 +694,29 @@
         return definingFn == function;
     }
 
+    private void checkConstAssignment(final IdentNode ident) {
+        // Check for reassignment of constant
+        final Symbol symbol = ident.getSymbol();
+        if (symbol.isConst()) {
+            throwParserException(ECMAErrors.getMessage("syntax.error.assign.constant", symbol.getName()), ident);
+        }
+    }
+
     @Override
-    public Node leaveASSIGN(final BinaryNode binaryNode) {
+    public Node leaveBinaryNode(final BinaryNode binaryNode) {
+        if (binaryNode.isAssignment() && binaryNode.lhs() instanceof IdentNode) {
+            checkConstAssignment((IdentNode) binaryNode.lhs());
+        }
+        switch (binaryNode.tokenType()) {
+        case ASSIGN:
+            return leaveASSIGN(binaryNode);
+        default:
+            return super.leaveBinaryNode(binaryNode);
+        }
+    }
+
+    private Node leaveASSIGN(final BinaryNode binaryNode) {
         // If we're assigning a property of the this object ("this.foo = ..."), record it.
-
         final Expression lhs = binaryNode.lhs();
         if (lhs instanceof AccessNode) {
             final AccessNode accessNode = (AccessNode) lhs;
@@ -684,23 +732,43 @@
     }
 
     @Override
+    public Node leaveUnaryNode(final UnaryNode unaryNode) {
+        if (unaryNode.isAssignment() && unaryNode.getExpression() instanceof IdentNode) {
+            checkConstAssignment((IdentNode) unaryNode.getExpression());
+        }
+        switch (unaryNode.tokenType()) {
+        case DELETE:
+            return leaveDELETE(unaryNode);
+        case TYPEOF:
+            return leaveTYPEOF(unaryNode);
+        default:
+            return super.leaveUnaryNode(unaryNode);
+        }
+    }
+
+    @Override
     public Node leaveBlock(final Block block) {
-        // It's not necessary to guard the marking of symbols as locals with this "if"condition for correctness, it's
-        // just an optimization -- runtime type calculation is not used when the compilation is not an on-demand
-        // optimistic compilation, so we can skip locals marking then.
+        // It's not necessary to guard the marking of symbols as locals with this "if" condition for
+        // correctness, it's just an optimization -- runtime type calculation is not used when the compilation
+        // is not an on-demand optimistic compilation, so we can skip locals marking then.
         if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) {
-            for (final Symbol symbol: block.getSymbols()) {
-                if (!symbol.isScope()) {
-                    assert symbol.isVar() || symbol.isParam();
-                    compiler.declareLocalSymbol(symbol.getName());
+            // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand
+            // compilation, and we're skipping parsing the function bodies for nested functions, this
+            // basically only means their parameters. It'd be enough to mistakenly declare to be a local a
+            // symbol in the outer function named the same as one of the parameters, though.
+            if (lc.getFunction(block) == lc.getOutermostFunction()) {
+                for (final Symbol symbol: block.getSymbols()) {
+                    if (!symbol.isScope()) {
+                        assert symbol.isVar() || symbol.isParam();
+                        compiler.declareLocalSymbol(symbol.getName());
+                    }
                 }
             }
         }
         return block;
     }
 
-    @Override
-    public Node leaveDELETE(final UnaryNode unaryNode) {
+    private Node leaveDELETE(final UnaryNode unaryNode) {
         final FunctionNode currentFunctionNode = lc.getCurrentFunction();
         final boolean      strictMode          = currentFunctionNode.isStrict();
         final Expression   rhs                 = unaryNode.getExpression();
@@ -764,24 +832,45 @@
 
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
-
-        return markProgramBlock(
+        final FunctionNode finalizedFunction;
+        if (isUnparsedFunction(functionNode)) {
+            finalizedFunction = functionNode;
+        } else {
+            finalizedFunction =
+               markProgramBlock(
                removeUnusedSlots(
                createSyntheticInitializers(
                finalizeParameters(
                        lc.applyTopFlags(functionNode))))
-                       .setThisProperties(lc, thisProperties.pop().size())
-                       .setState(lc, CompilationState.SYMBOLS_ASSIGNED));
+                       .setThisProperties(lc, thisProperties.pop().size()));
+        }
+        return finalizedFunction.setState(lc, CompilationState.SYMBOLS_ASSIGNED);
     }
 
     @Override
     public Node leaveIdentNode(final IdentNode identNode) {
-        final String name = identNode.getName();
-
         if (identNode.isPropertyName()) {
             return identNode;
         }
 
+        final Symbol symbol = nameIsUsed(identNode.getName(), identNode);
+
+        if (!identNode.isInitializedHere()) {
+            symbol.increaseUseCount();
+        }
+
+        IdentNode newIdentNode = identNode.setSymbol(symbol);
+
+        // If a block-scoped var is used before its declaration mark it as dead.
+        // We can only statically detect this for local vars, cross-function symbols require runtime checks.
+        if (symbol.isBlockScoped() && !symbol.hasBeenDeclared() && !identNode.isDeclaredHere() && isLocal(lc.getCurrentFunction(), symbol)) {
+            newIdentNode = newIdentNode.markDead();
+        }
+
+        return end(newIdentNode);
+    }
+
+    private Symbol nameIsUsed(final String name, final IdentNode origin) {
         final Block block = lc.getCurrentBlock();
 
         Symbol symbol = findSymbol(block, name);
@@ -799,18 +888,12 @@
             // if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already)
             maybeForceScope(symbol);
         } else {
-            log.info("No symbol exists. Declare as global: ", symbol);
-            symbol = defineGlobalSymbol(block, name);
-            Symbol.setSymbolIsScope(lc, symbol);
+            log.info("No symbol exists. Declare as global: ", name);
+            symbol = defineSymbol(block, name, origin, IS_GLOBAL | IS_SCOPE);
         }
 
         functionUsesSymbol(symbol);
-
-        if (!identNode.isInitializedHere()) {
-            symbol.increaseUseCount();
-        }
-
-        return end(identNode.setSymbol(symbol));
+        return symbol;
     }
 
     @Override
@@ -834,8 +917,7 @@
         return tryNode;
     }
 
-    @Override
-    public Node leaveTYPEOF(final UnaryNode unaryNode) {
+    private Node leaveTYPEOF(final UnaryNode unaryNode) {
         final Expression rhs = unaryNode.getExpression();
 
         final List<Expression> args = new ArrayList<>();
@@ -859,7 +941,6 @@
             return functionNode;
         }
 
-        assert functionNode.getId() == 1;
         return functionNode.setBody(lc, functionNode.getBody().setFlag(lc, Block.IS_GLOBAL_SCOPE));
     }
 
@@ -875,7 +956,7 @@
     }
 
     private Symbol newInternal(final CompilerConstants cc, final int flags) {
-        return defineSymbol(lc.getCurrentBlock(), lc.getCurrentFunction().uniqueName(cc.symbolName()), IS_VAR | IS_INTERNAL | flags); //NASHORN-73
+        return defineSymbol(lc.getCurrentBlock(), lc.getCurrentFunction().uniqueName(cc.symbolName()), null, IS_VAR | IS_INTERNAL | flags); //NASHORN-73
     }
 
     private Symbol newObjectInternal(final CompilerConstants cc) {
@@ -915,7 +996,8 @@
             return false;
         }
 
-        if (lc.getCurrentFunction().allVarsInScope()) {
+        final FunctionNode func = lc.getCurrentFunction();
+        if ( func.allVarsInScope() || (!symbol.isBlockScoped() && func.isProgram())) {
             return true;
         }
 
@@ -955,4 +1037,16 @@
         final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits();
         return !(units == null || units.isEmpty());
     }
+
+    private void throwParserException(final String message, final Node origin) {
+        if (origin == null) {
+            throw new ParserException(message);
+        }
+        final Source source = compiler.getSource();
+        final long token = origin.getToken();
+        final int line = source.getLine(origin.getStart());
+        final int column = source.getColumn(origin.getStart());
+        final String formatted = ErrorManager.format(message, source, line, column, token);
+        throw new ParserException(JSErrorType.SYNTAX_ERROR, formatted, source, line, column, token);
+    }
 }
--- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java	Tue Sep 16 13:59:37 2014 -0700
@@ -59,6 +59,7 @@
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Set;
+
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.util.TraceClassVisitor;
@@ -135,6 +136,16 @@
     /** Set of constants access methods required. */
     private Set<Class<?>> constantMethodNeeded;
 
+    private int methodCount;
+
+    private int initCount;
+
+    private int clinitCount;
+
+    private int fieldCount;
+
+    private final Set<String> methodNames;
+
     /**
      * Constructor - only used internally in this class as it breaks
      * abstraction towards ASM or other code generator below
@@ -146,6 +157,11 @@
         this.context        = context;
         this.cw             = cw;
         this.methodsStarted = new HashSet<>();
+        this.methodNames    = new HashSet<>();
+    }
+
+    public Set<String> getMethodNames() {
+        return methodNames;
     }
 
     /**
@@ -209,6 +225,38 @@
     }
 
     /**
+     * Get the method count, including init and clinit methods
+     * @return method count
+     */
+    public int getMethodCount() {
+        return methodCount;
+    }
+
+    /**
+     * Get the clinit count
+     * @return clinit count
+     */
+    public int getClinitCount() {
+        return clinitCount;
+    }
+
+    /**
+     * Get the init count
+     * @return init count
+     */
+    public int getInitCount() {
+        return initCount;
+    }
+
+    /**
+     * Get the field count
+     * @return field count
+     */
+    public int getFieldCount() {
+        return fieldCount;
+    }
+
+    /**
      * Convert a binary name to a package/class name.
      *
      * @param name Binary name.
@@ -359,9 +407,16 @@
      */
     @Override
     public void end() {
-        assert classStarted;
+        assert classStarted : "class not started for " + unitClassName;
 
         if (unitClassName != null) {
+            final MethodEmitter initMethod = init(EnumSet.of(Flag.PRIVATE));
+            initMethod.begin();
+            initMethod.load(Type.OBJECT, 0);
+            initMethod.newInstance(jdk.nashorn.internal.scripts.JS.class);
+            initMethod.returnVoid();
+            initMethod.end();
+
             defineCommonUtilities();
         }
 
@@ -419,6 +474,8 @@
     }
 
     SplitMethodEmitter method(final SplitNode splitNode, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
+        methodCount++;
+        methodNames.add(methodName);
         return new SplitMethodEmitter(this, methodVisitor(EnumSet.of(Flag.PUBLIC, Flag.STATIC), methodName, rtype, ptypes), splitNode);
     }
 
@@ -446,6 +503,8 @@
      * @return method emitter to use for weaving this method
      */
     MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
+        methodCount++;
+        methodNames.add(methodName);
         return new MethodEmitter(this, methodVisitor(methodFlags, methodName, rtype, ptypes));
     }
 
@@ -471,6 +530,8 @@
      * @return method emitter to use for weaving this method
      */
     MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final String descriptor) {
+        methodCount++;
+        methodNames.add(methodName);
         return new MethodEmitter(this, cw.visitMethod(Flag.getValue(methodFlags), methodName, descriptor, null, null));
     }
 
@@ -481,6 +542,8 @@
      * @return method emitter to use for weaving this method
      */
     MethodEmitter method(final FunctionNode functionNode) {
+        methodCount++;
+        methodNames.add(functionNode.getName());
         final FunctionSignature signature = new FunctionSignature(functionNode);
         final MethodVisitor mv = cw.visitMethod(
             ACC_PUBLIC | ACC_STATIC | (functionNode.isVarArg() ? ACC_VARARGS : 0),
@@ -499,6 +562,8 @@
      * @return method emitter to use for weaving this method
      */
     MethodEmitter restOfMethod(final FunctionNode functionNode) {
+        methodCount++;
+        methodNames.add(functionNode.getName());
         final MethodVisitor mv = cw.visitMethod(
             ACC_PUBLIC | ACC_STATIC,
             functionNode.getName(),
@@ -516,6 +581,7 @@
      * @return method emitter to use for weaving <clinit>
      */
     MethodEmitter clinit() {
+        clinitCount++;
         return method(EnumSet.of(Flag.STATIC), CLINIT.symbolName(), void.class);
     }
 
@@ -525,6 +591,7 @@
      * @return method emitter to use for weaving <init>()V
      */
     MethodEmitter init() {
+        initCount++;
         return method(INIT.symbolName(), void.class);
     }
 
@@ -535,6 +602,7 @@
      * @return method emitter to use for weaving <init>()V
      */
     MethodEmitter init(final Class<?>... ptypes) {
+        initCount++;
         return method(INIT.symbolName(), void.class, ptypes);
     }
 
@@ -547,6 +615,7 @@
      * @return method emitter to use for weaving <init>(...)V
      */
     MethodEmitter init(final EnumSet<Flag> flags, final Class<?>... ptypes) {
+        initCount++;
         return method(flags, INIT.symbolName(), void.class, ptypes);
     }
 
@@ -561,6 +630,7 @@
      * @see ClassEmitter.Flag
      */
     final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType, final Object value) {
+        fieldCount++;
         cw.visitField(Flag.getValue(fieldFlags), fieldName, typeDescriptor(fieldType), null, value).visitEnd();
     }
 
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Tue Sep 16 13:59:37 2014 -0700
@@ -52,6 +52,7 @@
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_APPLY_TO_CALL;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_DECLARE;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
@@ -302,6 +303,7 @@
      * @return the method generator used
      */
     private MethodEmitter loadIdent(final IdentNode identNode, final TypeBounds resultBounds) {
+        checkTemporalDeadZone(identNode);
         final Symbol symbol = identNode.getSymbol();
 
         if (!symbol.isScope()) {
@@ -334,6 +336,15 @@
         return method;
     }
 
+    // Any access to LET and CONST variables before their declaration must throw ReferenceError.
+    // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a
+    private void checkTemporalDeadZone(final IdentNode identNode) {
+        if (identNode.isDead()) {
+            method.load(identNode.getSymbol().getName());
+            method.invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
+        }
+    }
+
     private boolean isRestOf() {
         return continuationEntryPoints != null;
     }
@@ -1611,9 +1622,18 @@
 
             @Override
             protected void evaluate() {
-                method.load(ITERATOR_TYPE, iterSlot);
-                // TODO: optimistic for-in iteration
-                method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
+                new OptimisticOperation((Optimistic)forNode.getInit(), TypeBounds.UNBOUNDED) {
+                    @Override
+                    void loadStack() {
+                        method.load(ITERATOR_TYPE, iterSlot);
+                    }
+
+                    @Override
+                    void consumeStack() {
+                        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
+                        convertOptimisticReturnValue();
+                    }
+                }.emit();
             }
         }.store();
         body.accept(this);
@@ -3216,27 +3236,34 @@
             return false;
         }
         final Expression init = varNode.getInit();
+        final IdentNode identNode = varNode.getName();
+        final Symbol identSymbol = identNode.getSymbol();
+        assert identSymbol != null : "variable node " + varNode + " requires a name with a symbol";
+        final boolean needsScope = identSymbol.isScope();
 
         if (init == null) {
+            if (needsScope && varNode.isBlockScoped()) {
+                // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
+                method.loadCompilerConstant(SCOPE);
+                method.loadUndefined(Type.OBJECT);
+                final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
+                assert isFastScope(identSymbol);
+                storeFastScopeVar(identSymbol, flags);
+            }
             return false;
         }
 
         enterStatement(varNode);
-
-        final IdentNode identNode = varNode.getName();
-        final Symbol identSymbol = identNode.getSymbol();
-        assert identSymbol != null : "variable node " + varNode + " requires a name with a symbol";
-
         assert method != null;
 
-        final boolean needsScope = identSymbol.isScope();
         if (needsScope) {
             method.loadCompilerConstant(SCOPE);
         }
 
         if (needsScope) {
             loadExpressionUnbounded(init);
-            final int flags = CALLSITE_SCOPE | getCallSiteFlags();
+            // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
+            final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
             if (isFastScope(identSymbol)) {
                 storeFastScopeVar(identSymbol, flags);
             } else {
@@ -4343,6 +4370,9 @@
         protected abstract void evaluate();
 
         void store() {
+            if (target instanceof IdentNode) {
+                checkTemporalDeadZone((IdentNode)target);
+            }
             prologue();
             evaluate(); // leaves an operation of whatever the operationType was on the stack
             storeNonDiscard();
--- a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java	Tue Sep 16 13:59:37 2014 -0700
@@ -31,6 +31,7 @@
 import java.util.Deque;
 import java.util.HashMap;
 import java.util.Map;
+
 import jdk.nashorn.internal.IntDeque;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.Block;
@@ -158,7 +159,9 @@
 
     CompileUnit popCompileUnit(final CompileUnit oldUnit) {
         assert compileUnits.peek() == oldUnit;
-        compileUnits.pop();
+        final CompileUnit unit = compileUnits.pop();
+        assert unit.hasCode() : "compile unit popped without code";
+        unit.setUsed();
         return compileUnits.isEmpty() ? null : compileUnits.peek();
     }
 
--- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Tue Sep 16 13:59:37 2014 -0700
@@ -48,6 +48,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+
 import jdk.nashorn.internal.AssertsEnabled;
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.ir.FunctionNode;
@@ -300,6 +301,7 @@
         }
     },
 
+
     /**
      * Reuse compile units, if they are already present. We are using the same compiler
      * to recompile stuff
@@ -334,6 +336,8 @@
                 if (phases.isRestOfCompilation()) {
                     sb.append("$restOf");
                 }
+                //it's ok to not copy the initCount, methodCount and clinitCount here, as codegen is what
+                //fills those out anyway. Thus no need for a copy constructor
                 final CompileUnit newUnit = compiler.createCompileUnit(sb.toString(), oldUnit.getWeight());
                 log.fine("Creating new compile unit ", oldUnit, " => ", newUnit);
                 map.put(oldUnit, newUnit);
@@ -430,8 +434,14 @@
 
             FunctionNode newFunctionNode = fn;
 
+            //root class is special, as it is bootstrapped from createProgramFunction, thus it's skipped
+            //in CodeGeneration - the rest can be used as a working "is compile unit used" metric
+            fn.getCompileUnit().setUsed();
+
             compiler.getLogger().fine("Starting bytecode generation for ", quote(fn.getName()), " - restOf=", phases.isRestOfCompilation());
+
             final CodeGenerator codegen = new CodeGenerator(compiler, phases.isRestOfCompilation() ? compiler.getContinuationEntryPoints() : null);
+
             try {
                 // Explicitly set BYTECODE_GENERATED here; it can not be set in case of skipping codegen for :program
                 // in the lazy + optimistic world. See CodeGenerator.skipFunction().
@@ -455,12 +465,18 @@
                 final ClassEmitter classEmitter = compileUnit.getClassEmitter();
                 classEmitter.end();
 
+                if (!compileUnit.isUsed()) {
+                    compiler.getLogger().fine("Skipping unused compile unit ", compileUnit);
+                    continue;
+                }
+
                 final byte[] bytecode = classEmitter.toByteArray();
                 assert bytecode != null;
 
                 final String className = compileUnit.getUnitClassName();
+                compiler.addClass(className, bytecode); //classes are only added to the bytecode map if compile unit is used
 
-                compiler.addClass(className, bytecode);
+                CompileUnit.increaseEmitCount();
 
                 // should we verify the generated code?
                 if (senv._verify_code) {
@@ -536,6 +552,9 @@
 
             // initialize function in the compile units
             for (final CompileUnit unit : compiler.getCompileUnits()) {
+                if (!unit.isUsed()) {
+                    continue;
+                }
                 unit.setCode(installedClasses.get(unit.getUnitClassName()));
             }
 
--- a/src/jdk/nashorn/internal/codegen/CompileUnit.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java	Tue Sep 16 13:59:37 2014 -0700
@@ -42,6 +42,10 @@
 
     private Class<?> clazz;
 
+    private boolean isUsed;
+
+    private static int emittedUnitCount;
+
     CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) {
         this.className    = className;
         this.weight       = initialWeight;
@@ -52,6 +56,33 @@
         return new TreeSet<>();
     }
 
+    static void increaseEmitCount() {
+        emittedUnitCount++;
+    }
+
+    public static int getEmittedUnitCount() {
+        return emittedUnitCount;
+    }
+
+    /**
+     * Check if this compile unit is used
+     * @return true if tagged as in use - i.e active code that needs to be generated
+     */
+    public boolean isUsed() {
+        return isUsed;
+    }
+
+    public boolean hasCode() {
+        return (classEmitter.getMethodCount() - classEmitter.getInitCount() - classEmitter.getClinitCount()) > 0;
+    }
+
+    /**
+     * Tag this compile unit as used
+     */
+    public void setUsed() {
+        this.isUsed = true;
+    }
+
     /**
      * Return the class that contains the code for this unit, null if not
      * generated yet
@@ -121,7 +152,8 @@
 
     @Override
     public String toString() {
-        return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + ']';
+        final String methods = classEmitter != null ? classEmitter.getMethodNames().toString() : "<anon>";
+        return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + " hasCode=" + methods + ']';
     }
 
     @Override
--- a/src/jdk/nashorn/internal/codegen/Compiler.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Tue Sep 16 13:59:37 2014 -0700
@@ -38,7 +38,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -51,18 +50,21 @@
 import java.util.function.Consumer;
 import java.util.logging.Level;
 import jdk.internal.dynalink.support.NameCodec;
-import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.Optimistic;
 import jdk.nashorn.internal.ir.debug.ClassHistogramElement;
 import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
 import jdk.nashorn.internal.runtime.CodeInstaller;
 import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ErrorManager;
 import jdk.nashorn.internal.runtime.FunctionInitializer;
+import jdk.nashorn.internal.runtime.ParserException;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
@@ -89,6 +91,8 @@
 
     private final String sourceName;
 
+    private final ErrorManager errors;
+
     private final boolean optimistic;
 
     private final Map<String, byte[]> bytecode;
@@ -244,6 +248,15 @@
             return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
         }
 
+        @SuppressWarnings("unused") //TODO I'll use this soon
+        private CompilationPhases replace(final CompilationPhase phase, final CompilationPhase newPhase) {
+            final LinkedList<CompilationPhase> list = new LinkedList<>();
+            for (final CompilationPhase p : phases) {
+                list.add(p == phase ? newPhase : p);
+            }
+            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
+        }
+
         private CompilationPhases addAfter(final CompilationPhase phase, final CompilationPhase newPhase) {
             final LinkedList<CompilationPhase> list = new LinkedList<>();
             for (final CompilationPhase p : phases) {
@@ -311,6 +324,7 @@
      * @param env       script environment
      * @param installer code installer
      * @param source    source to compile
+     * @param errors    error manager
      * @param isStrict  is this a strict compilation
      */
     public Compiler(
@@ -318,8 +332,9 @@
             final ScriptEnvironment env,
             final CodeInstaller<ScriptEnvironment> installer,
             final Source source,
+            final ErrorManager errors,
             final boolean isStrict) {
-        this(context, env, installer, source, isStrict, false, null, null, null, null, null, null);
+        this(context, env, installer, source, errors, isStrict, false, null, null, null, null, null, null);
     }
 
     /**
@@ -329,6 +344,7 @@
      * @param env                      script environment
      * @param installer                code installer
      * @param source                   source to compile
+     * @param errors                   error manager
      * @param isStrict                 is this a strict compilation
      * @param isOnDemand               is this an on demand compilation
      * @param compiledFunction         compiled function, if any
@@ -343,6 +359,7 @@
             final ScriptEnvironment env,
             final CodeInstaller<ScriptEnvironment> installer,
             final Source source,
+            final ErrorManager errors,
             final boolean isStrict,
             final boolean isOnDemand,
             final RecompilableScriptFunctionData compiledFunction,
@@ -359,6 +376,7 @@
         this.bytecode                 = new LinkedHashMap<>();
         this.log                      = initLogger(context);
         this.source                   = source;
+        this.errors                   = errors;
         this.sourceName               = FunctionNode.getSourceName(source);
         this.onDemand                 = isOnDemand;
         this.compiledFunction         = compiledFunction;
@@ -464,6 +482,19 @@
         return typeEvaluator.getOptimisticType(node);
     }
 
+    /**
+     * Returns true if the expression can be safely evaluated, and its value is an object known to always use
+     * String as the type of its property names retrieved through
+     * {@link ScriptRuntime#toPropertyIterator(Object)}. It is used to avoid optimistic assumptions about its
+     * property name types.
+     * @param expr the expression to test
+     * @return true if the expression can be safely evaluated, and its value is an object known to always use
+     * String as the type of its property iterators.
+     */
+    boolean hasStringPropertyIterator(final Expression expr) {
+        return typeEvaluator.hasStringPropertyIterator(expr);
+    }
+
     void addInvalidatedProgramPoint(final int programPoint, final Type type) {
         invalidatedProgramPoints.put(programPoint, type);
     }
@@ -524,7 +555,17 @@
 
         for (final CompilationPhase phase : phases) {
             log.fine(phase, " starting for ", quote(name));
-            newFunctionNode = phase.apply(this, phases, newFunctionNode);
+
+            try {
+                newFunctionNode = phase.apply(this, phases, newFunctionNode);
+            } catch (final ParserException error) {
+                errors.error(error);
+                if (env._dump_on_error) {
+                    error.printStackTrace(env.getErr());
+                }
+                return null;
+            }
+
             log.fine(phase, " done for function ", quote(name));
 
             if (env._print_mem_usage) {
@@ -656,16 +697,8 @@
     CompileUnit createCompileUnit(final String unitClassName, final long initialWeight) {
         final ClassEmitter classEmitter = new ClassEmitter(context, sourceName, unitClassName, isStrict());
         final CompileUnit  compileUnit  = new CompileUnit(unitClassName, classEmitter, initialWeight);
-
         classEmitter.begin();
 
-        final MethodEmitter initMethod = classEmitter.init(EnumSet.of(Flag.PRIVATE));
-        initMethod.begin();
-        initMethod.load(Type.OBJECT, 0);
-        initMethod.newInstance(jdk.nashorn.internal.scripts.JS.class);
-        initMethod.returnVoid();
-        initMethod.end();
-
         return compileUnit;
     }
 
@@ -703,13 +736,6 @@
         return name.replace('/', '.');
     }
 
-    RecompilableScriptFunctionData getProgram() {
-        if (compiledFunction == null) {
-            return null;
-        }
-        return compiledFunction.getProgram();
-    }
-
     RecompilableScriptFunctionData getScriptFunctionData(final int functionId) {
         return compiledFunction == null ? null : compiledFunction.getScriptFunctionData(functionId);
     }
--- a/src/jdk/nashorn/internal/codegen/DumpBytecode.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/DumpBytecode.java	Tue Sep 16 13:59:37 2014 -0700
@@ -89,7 +89,7 @@
 
 
             // should code be dumped to disk - only valid in compile_only mode?
-            if (env._dest_dir != null && env._compile_only) {
+            if (env._dest_dir != null) {
                 final String fileName = className.replace('.', File.separatorChar) + ".class";
                 final int    index    = fileName.lastIndexOf(File.separatorChar);
 
--- a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java	Tue Sep 16 13:59:37 2014 -0700
@@ -69,9 +69,7 @@
      * Constructor
      *
      * @param codegen  code generator
-     * @param keys     keys for fields in object
-     * @param symbols  symbols for fields in object
-     * @param values   list of values corresponding to keys
+     * @param tuples   tuples for fields in object
      */
     FieldObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples) {
         this(codegen, tuples, false, false);
@@ -81,9 +79,7 @@
      * Constructor
      *
      * @param codegen      code generator
-     * @param keys         keys for fields in object
-     * @param symbols      symbols for fields in object
-     * @param values       values (or null where no value) to be written to the fields
+     * @param tuples       tuples for fields in object
      * @param isScope      is this a scope object
      * @param hasArguments does the created object have an "arguments" property
      */
@@ -165,7 +161,7 @@
      * @param method      Script method.
      * @param key         Property key.
      * @param fieldIndex  Field number.
-     * @param value       Value to store.
+     * @param tuple       Tuple to store.
      */
     private void putField(final MethodEmitter method, final String key, final int fieldIndex, final MapTuple<T> tuple) {
         method.dup();
@@ -188,7 +184,7 @@
      *
      * @param method Script method.
      * @param index  Slot index.
-     * @param value  Value to store.
+     * @param tuple  Tuple to store.
      */
     private void putSlot(final MethodEmitter method, final long index, final MapTuple<T> tuple) {
         method.dup();
--- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Tue Sep 16 13:59:37 2014 -0700
@@ -25,8 +25,6 @@
 
 package jdk.nashorn.internal.codegen;
 
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getClassName;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getPaddedFieldCount;
 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
 
 import java.util.HashMap;
@@ -34,6 +32,7 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
@@ -44,7 +43,6 @@
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
@@ -208,14 +206,10 @@
 
         assert nestedFunctions != null;
         // Generate the object class and property map in case this function is ever used as constructor
-        final int         fieldCount         = getPaddedFieldCount(newFunctionNode.getThisProperties());
-        final String      allocatorClassName = Compiler.binaryName(getClassName(fieldCount));
-        final PropertyMap allocatorMap       = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0);
         final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData(
                 newFunctionNode,
                 compiler.getCodeInstaller(),
-                allocatorClassName,
-                allocatorMap,
+                new AllocatorDescriptor(newFunctionNode.getThisProperties()),
                 nestedFunctions,
                 externalSymbolDepths.get(fnId),
                 internalSymbols.get(fnId)
--- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Tue Sep 16 13:59:37 2014 -0700
@@ -551,13 +551,19 @@
 
         final Expression init = forNode.getInit();
         if(forNode.isForIn()) {
-            forNode.getModify().accept(this);
-            enterTestFirstLoop(forNode, null, init);
+            final JoinPredecessorExpression iterable = forNode.getModify();
+            iterable.accept(this);
+            enterTestFirstLoop(forNode, null, init,
+                    // If we're iterating over property names, and we can discern from the runtime environment
+                    // of the compilation that the object being iterated over must use strings for property
+                    // names (e.g., it is a native JS object or array), then we'll not bother trying to treat
+                    // the property names optimistically.
+                    !forNode.isForEach() && compiler.hasStringPropertyIterator(iterable.getExpression()));
         } else {
             if(init != null) {
                 init.accept(this);
             }
-            enterTestFirstLoop(forNode, forNode.getModify(), null);
+            enterTestFirstLoop(forNode, forNode.getModify(), null, false);
         }
         return false;
     }
@@ -792,7 +798,8 @@
         return false;
     }
 
-    private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify, final Expression iteratorValues) {
+    private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify,
+            final Expression iteratorValues, final boolean iteratorValuesAreObject) {
         final JoinPredecessorExpression test = loopNode.getTest();
         if(isAlwaysFalse(test)) {
             test.accept(this);
@@ -814,8 +821,12 @@
                 jumpToLabel(test, breakLabel);
             }
             if(iteratorValues instanceof IdentNode) {
-                // Receives iterator values; they're currently all objects (JDK-8034954).
-                onAssignment((IdentNode)iteratorValues, LvarType.OBJECT);
+                final IdentNode ident = (IdentNode)iteratorValues;
+                // Receives iterator values; the optimistic type of the iterator values is tracked on the
+                // identifier, but we override optimism if it's known that the object being iterated over will
+                // never have primitive property names.
+                onAssignment(ident, iteratorValuesAreObject ? LvarType.OBJECT :
+                    toLvarType(compiler.getOptimisticType(ident)));
             }
             final Block body = loopNode.getBody();
             body.accept(this);
@@ -955,7 +966,7 @@
         if(whileNode.isDoWhile()) {
             enterDoWhileLoop(whileNode);
         } else {
-            enterTestFirstLoop(whileNode, null, null);
+            enterTestFirstLoop(whileNode, null, null, false);
         }
         return false;
     }
--- a/src/jdk/nashorn/internal/codegen/Lower.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/Lower.java	Tue Sep 16 13:59:37 2014 -0700
@@ -71,7 +71,6 @@
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.CodeInstaller;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.Source;
@@ -93,9 +92,6 @@
 
     private final DebugLogger log;
 
-    // needed only to get unique eval id
-    private final CodeInstaller<?> installer;
-
     /**
      * Constructor.
      */
@@ -143,7 +139,6 @@
             }
         });
 
-        this.installer = compiler.getCodeInstaller();
         this.log       = initLogger(compiler.getContext());
     }
 
@@ -566,16 +561,13 @@
     private String evalLocation(final IdentNode node) {
         final Source source = lc.getCurrentFunction().getSource();
         final int pos = node.position();
-        // Code installer is null when running with --compile-only, use 0 as id in that case
-        final long id = installer == null ? 0 : installer.getUniqueEvalId();
         return new StringBuilder().
             append(source.getName()).
             append('#').
             append(source.getLine(pos)).
             append(':').
             append(source.getColumn(pos)).
-            append("<eval>@").
-            append(id).
+            append("<eval>").
             toString();
     }
 
--- a/src/jdk/nashorn/internal/codegen/MapCreator.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/MapCreator.java	Tue Sep 16 13:59:37 2014 -0700
@@ -52,8 +52,7 @@
      * Constructor
      *
      * @param structure structure to generate map for (a JO subclass)
-     * @param keys      list of keys for map
-     * @param symbols   list of symbols for map
+     * @param tuples    list of tuples for map
      */
     MapCreator(final Class<? extends ScriptObject> structure, final List<MapTuple<T>> tuples) {
         this.structure = structure;
@@ -149,6 +148,15 @@
             flags |= Property.IS_FUNCTION_DECLARATION;
         }
 
+        if (symbol.isConst()) {
+            flags |= Property.NOT_WRITABLE;
+        }
+
+        // Mark symbol as needing declaration. Access before declaration will throw a ReferenceError.
+        if (symbol.isBlockScoped() && symbol.isScope()) {
+            flags |= Property.NEEDS_DECLARATION;
+        }
+
         return flags;
     }
 }
--- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Tue Sep 16 13:59:37 2014 -0700
@@ -2233,9 +2233,8 @@
     /**
      * Generate dynamic setter. Pop receiver and property from stack.
      *
-     * @param valueType the type of the value to set
-     * @param name      name of property
-     * @param flags     call site flags
+     * @param name  name of property
+     * @param flags call site flags
      */
      void dynamicSet(final String name, final int flags) {
          assert !isOptimistic(flags);
@@ -2462,7 +2461,6 @@
      * Register line number at a label
      *
      * @param line  line number
-     * @param label label
      */
     void lineNumber(final int line) {
         if (context.getEnv()._debug_lines) {
--- a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Tue Sep 16 13:59:37 2014 -0700
@@ -308,7 +308,7 @@
         newEmptyInit(className, classEmitter);
         newAllocate(className, classEmitter);
 
-        return toByteArray(classEmitter);
+        return toByteArray(className, classEmitter);
     }
 
     /**
@@ -341,7 +341,7 @@
         initWithArguments.returnVoid();
         initWithArguments.end();
 
-        return toByteArray(classEmitter);
+        return toByteArray(className, classEmitter);
     }
 
     /**
@@ -484,15 +484,13 @@
      * @param classEmitter Open class emitter.
      * @return Byte codes for the class.
      */
-    private byte[] toByteArray(final ClassEmitter classEmitter) {
+    private byte[] toByteArray(final String className, final ClassEmitter classEmitter) {
         classEmitter.end();
 
         final byte[] code = classEmitter.toByteArray();
         final ScriptEnvironment env = context.getEnv();
 
-        if (env._print_code && env._print_code_dir == null) {
-            env.getErr().println(ClassEmitter.disassemble(code));
-        }
+        DumpBytecode.dumpBytecode(env, log, code, className);
 
         if (env._verify_code) {
             context.verify(code);
@@ -827,5 +825,45 @@
         return MH.findStatic(MethodHandles.lookup(), ObjectClassGenerator.class, name, MH.type(rtype, types));
     }
 
+    /**
+     * Describes the allocator class name and property map for a constructor function with the specified
+     * number of "this" properties that it initializes.
+     *
+     */
+    public static class AllocatorDescriptor {
+        private final String allocatorClassName;
+        private final PropertyMap allocatorMap;
 
+        /**
+         * Creates a new allocator descriptor
+         * @param thisProperties the number of "this" properties that the function initializes
+         */
+        public AllocatorDescriptor(final int thisProperties) {
+            final int paddedFieldCount = getPaddedFieldCount(thisProperties);
+            this.allocatorClassName = Compiler.binaryName(getClassName(paddedFieldCount));
+            this.allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, paddedFieldCount, 0);
+        }
+
+        /**
+         * Returns the name of the class that the function allocates
+         * @return the name of the class that the function allocates
+         */
+        public String getAllocatorClassName() {
+            return allocatorClassName;
+        }
+
+        /**
+         * Returns the allocator map for the function.
+         * @return the allocator map for the function.
+         */
+        public PropertyMap getAllocatorMap() {
+            return allocatorMap;
+        }
+
+        @Override
+        public String toString() {
+            return "AllocatorDescriptor[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" +
+                    allocatorMap.size() + "]";
+        }
+    }
 }
--- a/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java	Tue Sep 16 13:59:37 2014 -0700
@@ -31,9 +31,11 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.security.AccessController;
 import java.security.MessageDigest;
 import java.security.PrivilegedAction;
@@ -41,6 +43,14 @@
 import java.util.Base64;
 import java.util.Date;
 import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
@@ -49,30 +59,66 @@
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
- * Static utility that encapsulates persistence of decompilation information for functions. Normally, the type info
- * persistence feature is enabled and operates in an operating-system specific per-user cache directory. You can
- * override the directory by specifying it in the {@code nashorn.typeInfo.cacheDir} directory. Also, you can disable the
- * type info persistence altogether by specifying the {@code nashorn.typeInfo.disabled} system property.
+ * Static utility that encapsulates persistence of type information for functions compiled with optimistic
+ * typing. With this feature enabled, when a JavaScript function is recompiled because it gets deoptimized,
+ * the type information for deoptimization is stored in a cache file. If the same function is compiled in a
+ * subsequent JVM invocation, the type information is used for initial compilation, thus allowing the system
+ * to skip a lot of intermediate recompilations and immediately emit a version of the code that has its
+ * optimistic types at (or near) the steady state.
+ * </p><p>
+ * Normally, the type info persistence feature is disabled. When the {@code nashorn.typeInfo.maxFiles} system
+ * property is specified with a value greater than 0, it is enabled and operates in an operating-system
+ * specific per-user cache directory. You can override the directory by specifying it in the
+ * {@code nashorn.typeInfo.cacheDir} directory. The maximum number of files is softly enforced by a task that
+ * cleans up the directory periodically on a separate thread. It is run after some delay after a new file is
+ * added to the cache. The default delay is 20 seconds, and can be set using the
+ * {@code nashorn.typeInfo.cleanupDelaySeconds} system property. You can also specify the word
+ * {@code unlimited} as the value for {@code nashorn.typeInfo.maxFiles} in which case the type info cache is
+ * allowed to grow without limits.
  */
 public final class OptimisticTypesPersistence {
+    // Default is 0, for disabling the feature when not specified. A reasonable default when enabled is
+    // dependent on the application; setting it to e.g. 20000 is probably good enough for most uses and will
+    // usually cap the cache directory to about 80MB presuming a 4kB filesystem allocation unit. There is one
+    // file per JavaScript function.
+    private static final int DEFAULT_MAX_FILES = 0;
+    // Constants for signifying that the cache should not be limited
+    private static final int UNLIMITED_FILES = -1;
+    // Maximum number of files that should be cached on disk. The maximum will be softly enforced.
+    private static final int MAX_FILES = getMaxFiles();
+    // Number of seconds to wait between adding a new file to the cache and running a cleanup process
+    private static final int DEFAULT_CLEANUP_DELAY = 20;
+    private static final int CLEANUP_DELAY = Math.max(0, Options.getIntProperty(
+            "nashorn.typeInfo.cleanupDelaySeconds", DEFAULT_CLEANUP_DELAY));
     // The name of the default subdirectory within the system cache directory where we store type info.
     private static final String DEFAULT_CACHE_SUBDIR_NAME = "com.oracle.java.NashornTypeInfo";
     // The directory where we cache type info
-    private static final File cacheDir = createCacheDir();
+    private static final File baseCacheDir = createBaseCacheDir();
+    private static final File cacheDir = createCacheDir(baseCacheDir);
     // In-process locks to make sure we don't have a cross-thread race condition manipulating any file.
     private static final Object[] locks = cacheDir == null ? null : createLockArray();
-
     // Only report one read/write error every minute
     private static final long ERROR_REPORT_THRESHOLD = 60000L;
 
     private static volatile long lastReportedError;
-
+    private static final AtomicBoolean scheduledCleanup;
+    private static final Timer cleanupTimer;
+    static {
+        if (baseCacheDir == null || MAX_FILES == UNLIMITED_FILES) {
+            scheduledCleanup = null;
+            cleanupTimer = null;
+        } else {
+            scheduledCleanup = new AtomicBoolean();
+            cleanupTimer = new Timer(true);
+        }
+    }
     /**
-     * Retrieves an opaque descriptor for the persistence location for a given function. It should be passed to
-     * {@link #load(Object)} and {@link #store(Object, Map)} methods.
+     * Retrieves an opaque descriptor for the persistence location for a given function. It should be passed
+     * to {@link #load(Object)} and {@link #store(Object, Map)} methods.
      * @param source the source where the function comes from
      * @param functionId the unique ID number of the function within the source
-     * @param paramTypes the types of the function parameters (as persistence is per parameter type specialization).
+     * @param paramTypes the types of the function parameters (as persistence is per parameter type
+     * specialization).
      * @return an opaque descriptor for the persistence location. Can be null if persistence is disabled.
      */
     public static Object getLocationDescriptor(final Source source, final int functionId, final Type[] paramTypes) {
@@ -82,7 +128,8 @@
         final StringBuilder b = new StringBuilder(48);
         // Base64-encode the digest of the source, and append the function id.
         b.append(source.getDigest()).append('-').append(functionId);
-        // Finally, if this is a parameter-type specialized version of the function, add the parameter types to the file name.
+        // Finally, if this is a parameter-type specialized version of the function, add the parameter types
+        // to the file name.
         if(paramTypes != null && paramTypes.length > 0) {
             b.append('-');
             for(final Type t: paramTypes) {
@@ -118,6 +165,11 @@
             @Override
             public Void run() {
                 synchronized(getFileLock(file)) {
+                    if (!file.exists()) {
+                        // If the file already exists, we aren't increasing the number of cached files, so
+                        // don't schedule cleanup.
+                        scheduleCleanup();
+                    }
                     try (final FileOutputStream out = new FileOutputStream(file)) {
                         out.getChannel().lock(); // lock exclusive
                         final DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(out));
@@ -174,19 +226,19 @@
         }
     }
 
-    private static File createCacheDir() {
-        if(Options.getBooleanProperty("nashorn.typeInfo.disabled")) {
+    private static File createBaseCacheDir() {
+        if(MAX_FILES == 0 || Options.getBooleanProperty("nashorn.typeInfo.disabled")) {
             return null;
         }
         try {
-            return createCacheDirPrivileged();
+            return createBaseCacheDirPrivileged();
         } catch(final Exception e) {
             getLogger().warning("Failed to create cache dir", e);
             return null;
         }
     }
 
-    private static File createCacheDirPrivileged() {
+    private static File createBaseCacheDirPrivileged() {
         return AccessController.doPrivileged(new PrivilegedAction<File>() {
             @Override
             public File run() {
@@ -195,14 +247,35 @@
                 if(explicitDir != null) {
                     dir = new File(explicitDir);
                 } else {
-                    // When no directory is explicitly specified, get an operating system specific cache directory,
-                    // and create "com.oracle.java.NashornTypeInfo" in it.
+                    // When no directory is explicitly specified, get an operating system specific cache
+                    // directory, and create "com.oracle.java.NashornTypeInfo" in it.
                     final File systemCacheDir = getSystemCacheDir();
                     dir = new File(systemCacheDir, DEFAULT_CACHE_SUBDIR_NAME);
                     if (isSymbolicLink(dir)) {
                         return null;
                     }
                 }
+                return dir;
+            }
+        });
+    }
+
+    private static File createCacheDir(final File baseDir) {
+        if (baseDir == null) {
+            return null;
+        }
+        try {
+            return createCacheDirPrivileged(baseDir);
+        } catch(final Exception e) {
+            getLogger().warning("Failed to create cache dir", e);
+            return null;
+        }
+    }
+
+    private static File createCacheDirPrivileged(final File baseDir) {
+        return AccessController.doPrivileged(new PrivilegedAction<File>() {
+            @Override
+            public File run() {
                 final String versionDirName;
                 try {
                     versionDirName = getVersionDirName();
@@ -210,12 +283,12 @@
                     getLogger().warning("Failed to calculate version dir name", e);
                     return null;
                 }
-                final File versionDir = new File(dir, versionDirName);
+                final File versionDir = new File(baseDir, versionDirName);
                 if (isSymbolicLink(versionDir)) {
                     return null;
                 }
                 versionDir.mkdirs();
-                if(versionDir.isDirectory()) {
+                if (versionDir.isDirectory()) {
                     getLogger().info("Optimistic type persistence directory is " + versionDir);
                     return versionDir;
                 }
@@ -235,12 +308,12 @@
             // Mac OS X stores caches in ~/Library/Caches
             return new File(new File(System.getProperty("user.home"), "Library"), "Caches");
         } else if(os.startsWith("Windows")) {
-            // On Windows, temp directory is the best approximation of a cache directory, as its contents persist across
-            // reboots and various cleanup utilities know about it. java.io.tmpdir normally points to a user-specific
-            // temp directory, %HOME%\LocalSettings\Temp.
+            // On Windows, temp directory is the best approximation of a cache directory, as its contents
+            // persist across reboots and various cleanup utilities know about it. java.io.tmpdir normally
+            // points to a user-specific temp directory, %HOME%\LocalSettings\Temp.
             return new File(System.getProperty("java.io.tmpdir"));
         } else {
-            // In all other cases we're presumably dealing with a UNIX flavor (Linux, Solaris, etc.); "~/.cache"
+            // In other cases we're presumably dealing with a UNIX flavor (Linux, Solaris, etc.); "~/.cache"
             return new File(System.getProperty("user.home"), ".cache");
         }
     }
@@ -278,7 +351,8 @@
             final int packageNameLen = className.lastIndexOf('.');
             final String dirStr = fileStr.substring(0, fileStr.length() - packageNameLen - 1);
             final File dir = new File(dirStr);
-            return "dev-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(getLastModifiedClassFile(dir, 0L)));
+            return "dev-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(getLastModifiedClassFile(
+                    dir, 0L)));
         } else {
             throw new AssertionError();
         }
@@ -335,4 +409,108 @@
             return DebugLogger.DISABLED_LOGGER;
         }
     }
+
+    private static void scheduleCleanup() {
+        if (MAX_FILES != UNLIMITED_FILES && scheduledCleanup.compareAndSet(false, true)) {
+            cleanupTimer.schedule(new TimerTask() {
+                @Override
+                public void run() {
+                    scheduledCleanup.set(false);
+                    try {
+                        doCleanup();
+                    } catch (final IOException e) {
+                        // Ignore it. While this is unfortunate, we don't have good facility for reporting
+                        // this, as we're running in a thread that has no access to Context, so we can't grab
+                        // a DebugLogger.
+                    }
+                }
+            }, TimeUnit.SECONDS.toMillis(CLEANUP_DELAY));
+        }
+    }
+
+    private static void doCleanup() throws IOException {
+        final long start = System.nanoTime();
+        final Path[] files = getAllRegularFilesInLastModifiedOrder();
+        final int nFiles = files.length;
+        final int filesToDelete = Math.max(0, nFiles - MAX_FILES);
+        int filesDeleted = 0;
+        for (int i = 0; i < nFiles && filesDeleted < filesToDelete; ++i) {
+            try {
+                Files.deleteIfExists(files[i]);
+                // Even if it didn't exist, we increment filesDeleted; it existed a moment earlier; something
+                // else deleted it for us; that's okay with us.
+                filesDeleted++;
+            } catch (final Exception e) {
+                // does not increase filesDeleted
+            }
+            files[i] = null; // gc eligible
+        };
+        final long duration = System.nanoTime() - start;
+    }
+
+    private static Path[] getAllRegularFilesInLastModifiedOrder() throws IOException {
+        try (final Stream<Path> filesStream = Files.walk(baseCacheDir.toPath())) {
+            // TODO: rewrite below once we can use JDK8 syntactic constructs
+            return filesStream
+            .filter(new Predicate<Path>() {
+                @Override
+                public boolean test(final Path path) {
+                    return !Files.isDirectory(path);
+                };
+            })
+            .map(new Function<Path, PathAndTime>() {
+                @Override
+                public PathAndTime apply(final Path path) {
+                    return new PathAndTime(path);
+                }
+            })
+            .sorted()
+            .map(new Function<PathAndTime, Path>() {
+                @Override
+                public Path apply(final PathAndTime pathAndTime) {
+                    return pathAndTime.path;
+                }
+            })
+            .toArray(new IntFunction<Path[]>() { // Replace with Path::new
+                @Override
+                public Path[] apply(final int length) {
+                    return new Path[length];
+                }
+            });
+        }
+    }
+
+    private static class PathAndTime implements Comparable<PathAndTime> {
+        private final Path path;
+        private final long time;
+
+        PathAndTime(final Path path) {
+            this.path = path;
+            this.time = getTime(path);
+        }
+
+        @Override
+        public int compareTo(final PathAndTime other) {
+            return Long.compare(time, other.time);
+        }
+
+        private static long getTime(final Path path) {
+            try {
+                return Files.getLastModifiedTime(path).toMillis();
+            } catch (IOException e) {
+                // All files for which we can't retrieve the last modified date will be considered oldest.
+                return -1L;
+            }
+        }
+    }
+
+    private static int getMaxFiles() {
+        final String str = Options.getStringProperty("nashorn.typeInfo.maxFiles", null);
+        if (str == null) {
+            return DEFAULT_MAX_FILES;
+        } else if ("unlimited".equals(str)) {
+            return UNLIMITED_FILES;
+        }
+        return Math.max(0, Integer.parseInt(str));
+    }
 }
--- a/src/jdk/nashorn/internal/codegen/TypeEvaluator.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/TypeEvaluator.java	Tue Sep 16 13:59:37 2014 -0700
@@ -55,6 +55,19 @@
         this.runtimeScope = runtimeScope;
     }
 
+    /**
+     * Returns true if the expression can be safely evaluated, and its value is an object known to always use
+     * String as the type of its property names retrieved through
+     * {@link ScriptRuntime#toPropertyIterator(Object)}. It is used to avoid optimistic assumptions about its
+     * property name types.
+     * @param expr the expression to test
+     * @return true if the expression can be safely evaluated, and its value is an object known to always use
+     * String as the type of its property iterators.
+     */
+    boolean hasStringPropertyIterator(final Expression expr) {
+        return evaluateSafely(expr) instanceof ScriptObject;
+    }
+
     Type getOptimisticType(final Optimistic node) {
         assert compiler.useOptimisticTypes();
 
@@ -108,7 +121,7 @@
 
         // Safely evaluate the property, and return the narrowest type for the actual value (e.g. Type.INT for a boxed
         // integer).
-        final Object value = property.getObjectValue(owner, owner);
+        final Object value = property.needsDeclaration() ? ScriptRuntime.UNDEFINED : property.getObjectValue(owner, owner);
         if (value == ScriptRuntime.UNDEFINED) {
             return null;
         }
--- a/src/jdk/nashorn/internal/codegen/types/Type.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/codegen/types/Type.java	Tue Sep 16 13:59:37 2014 -0700
@@ -333,7 +333,7 @@
      */
     public static Map<Integer, Type> readTypeMap(final DataInput input) throws IOException {
         final int size = input.readInt();
-        if (size == 0) {
+        if (size <= 0) {
             return null;
         }
         final Map<Integer, Type> map = new TreeMap<>();
@@ -345,7 +345,7 @@
                 case 'L': type = Type.OBJECT; break;
                 case 'D': type = Type.NUMBER; break;
                 case 'J': type = Type.LONG; break;
-                default: throw new AssertionError();
+                default: continue;
             }
             map.put(pp, type);
         }
--- a/src/jdk/nashorn/internal/ir/Block.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/ir/Block.java	Tue Sep 16 13:59:37 2014 -0700
@@ -277,6 +277,14 @@
     }
 
     /**
+     * Returns the number of statements in the block.
+     * @return the number of statements in the block.
+     */
+    public int getStatementCount() {
+        return statements.size();
+    }
+
+    /**
      * Returns the line number of the first statement in the block.
      * @return the line number of the first statement in the block, or -1 if the block has no statements.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/ir/CompileUnitHolder.java	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,40 @@
+/*
+ * 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.CompileUnit;
+
+/**
+ * Marker interface for things in the IR that can hold compile units.
+ * {@link CompileUnit}
+ */
+public interface CompileUnitHolder {
+    /**
+     * Return the compile unit held by this instance
+     * @return compile unit
+     */
+    public CompileUnit getCompileUnit();
+}
--- a/src/jdk/nashorn/internal/ir/FunctionNode.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/ir/FunctionNode.java	Tue Sep 16 13:59:37 2014 -0700
@@ -34,10 +34,8 @@
 
 import java.util.Collections;
 import java.util.EnumSet;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Set;
 import java.util.function.Function;
 import jdk.nashorn.internal.AssertsEnabled;
 import jdk.nashorn.internal.codegen.CompileUnit;
@@ -48,6 +46,7 @@
 import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.UserAccessorProperty;
@@ -57,7 +56,7 @@
  * IR representation for function (or script.)
  */
 @Immutable
-public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode> {
+public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
     /** Type used for all FunctionNodes */
     public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
 
@@ -110,8 +109,11 @@
     /** Source of entity. */
     private final Source source;
 
-    /** Unique ID used for recompilation among other things */
-    private final int id;
+    /**
+     * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
+     * to skip parsing inner functions.
+     */
+    private final Object endParserState;
 
     /** External function identifier. */
     @Ignore
@@ -138,10 +140,6 @@
     /** Last token of function. **/
     private final long lastToken;
 
-    /** Declared symbols in this function node */
-    @Ignore
-    private final Set<Symbol> declaredSymbols;
-
     /** Method's namespace. */
     private final Namespace namespace;
 
@@ -260,6 +258,14 @@
     /** trace callsite values in this function? */
     public static final int IS_TRACE_VALUES    = 1 << 26;
 
+    /**
+     * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
+     * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
+     * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
+     * will, however, cache the value of this flag.
+     */
+    public static final int NEEDS_CALLEE       = 1 << 27;
+
     /** extension callsite flags mask */
     public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
         IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
@@ -275,16 +281,9 @@
     /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
     private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
 
-    /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval.
-     *  We also pessimistically need a parent scope if we have lazy children that have not yet been compiled */
+    /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval. */
     private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL;
 
-    /** Used to signify "null", e.g. if someone asks for the parent of the program node */
-    public static final int NO_FUNCTION_ID = 0;
-
-    /** Where to start assigning global and unique function node ids */
-    public static final int FIRST_FUNCTION_ID = NO_FUNCTION_ID + 1;
-
     /** What is the return type of this function? */
     private Type returnType = Type.UNKNOWN;
 
@@ -292,11 +291,10 @@
      * Constructor
      *
      * @param source     the source
-     * @param id         unique id
      * @param lineNumber line number
      * @param token      token
      * @param finish     finish
-     * @param firstToken first token of the funtion node (including the function declaration)
+     * @param firstToken first token of the function node (including the function declaration)
      * @param namespace  the namespace
      * @param ident      the identifier
      * @param name       the name of the function
@@ -306,7 +304,6 @@
      */
     public FunctionNode(
         final Source source,
-        final int id,
         final int lineNumber,
         final long token,
         final int finish,
@@ -320,7 +317,6 @@
         super(token, finish);
 
         this.source           = source;
-        this.id               = id;
         this.lineNumber       = lineNumber;
         this.ident            = ident;
         this.name             = name;
@@ -330,17 +326,18 @@
         this.lastToken        = token;
         this.namespace        = namespace;
         this.compilationState = EnumSet.of(CompilationState.INITIALIZED);
-        this.declaredSymbols  = new HashSet<>();
         this.flags            = flags;
         this.compileUnit      = null;
         this.body             = null;
         this.thisProperties   = 0;
         this.rootClass        = null;
+        this.endParserState    = null;
     }
 
     private FunctionNode(
         final FunctionNode functionNode,
         final long lastToken,
+        Object endParserState,
         final int flags,
         final String name,
         final Type returnType,
@@ -352,6 +349,7 @@
         final Class<?> rootClass) {
         super(functionNode);
 
+        this.endParserState    = endParserState;
         this.lineNumber       = functionNode.lineNumber;
         this.flags            = flags;
         this.name             = name;
@@ -366,10 +364,8 @@
 
         // the fields below never change - they are final and assigned in constructor
         this.source          = functionNode.source;
-        this.id              = functionNode.id;
         this.ident           = functionNode.ident;
         this.namespace       = functionNode.namespace;
-        this.declaredSymbols = functionNode.declaredSymbols;
         this.kind            = functionNode.kind;
         this.firstToken      = functionNode.firstToken;
     }
@@ -435,11 +431,11 @@
     }
 
     /**
-     * Get the unique ID for this function
+     * Get the unique ID for this function within the script file.
      * @return the id
      */
     public int getId() {
-        return id;
+        return position();
     }
 
     /**
@@ -541,6 +537,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -612,6 +609,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -650,15 +648,24 @@
     }
 
     /**
-     * Check if the {@code eval} keyword is used in this function
+     * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
      *
-     * @return true if {@code eval} is used
+     * @return true if {@code eval} is called.
      */
     public boolean hasEval() {
         return getFlag(HAS_EVAL);
     }
 
     /**
+     * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}.
+     *
+     * @return true if a nested function calls {@code eval}.
+     */
+    public boolean hasNestedEval() {
+        return getFlag(HAS_NESTED_EVAL);
+    }
+
+    /**
      * Get the first token for this function
      * @return the first token
      */
@@ -724,24 +731,6 @@
     }
 
     /**
-     * Return a set of symbols declared in this function node. This
-     * is only relevant after Attr, otherwise it will be an empty
-     * set as no symbols have been introduced
-     * @return set of declared symbols in function
-     */
-    public Set<Symbol> getDeclaredSymbols() {
-        return Collections.unmodifiableSet(declaredSymbols);
-    }
-
-    /**
-     * Add a declared symbol to this function node
-     * @param symbol symbol that is declared
-     */
-    public void addDeclaredSymbol(final Symbol symbol) {
-        declaredSymbols.add(symbol);
-    }
-
-    /**
      * Get the function body
      * @return the function body
      */
@@ -765,6 +754,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags |
                             (body.needsScope() ?
                                     FunctionNode.HAS_SCOPE_BLOCK :
@@ -863,6 +853,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -923,6 +914,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -935,6 +927,41 @@
     }
 
     /**
+     * Returns the end parser state for this function.
+     * @return the end parser state for this function.
+     */
+    public Object getEndParserState() {
+        return endParserState;
+    }
+
+    /**
+     * Set the end parser state for this function.
+     * @param lc lexical context
+     * @param endParserState the parser state to set
+     * @return function node or a new one if state was changed
+     */
+    public FunctionNode setEndParserState(final LexicalContext lc, final Object endParserState) {
+        if (this.endParserState == endParserState) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        endParserState,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties, rootClass));
+    }
+
+    /**
      * Get the name of this function
      * @return the name
      */
@@ -958,6 +985,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -970,13 +998,13 @@
     }
 
     /**
-     * Check if this function should have all its variables in its own scope. Scripts, split sub-functions, and
+     * Check if this function should have all its variables in its own scope. Split sub-functions, and
      * functions having with and/or eval blocks are such.
      *
      * @return true if all variables should be in scope
      */
     public boolean allVarsInScope() {
-        return isProgram() || getFlag(HAS_ALL_VARS_IN_SCOPE);
+        return getFlag(HAS_ALL_VARS_IN_SCOPE);
     }
 
     /**
@@ -1023,6 +1051,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -1101,6 +1130,7 @@
             new FunctionNode(
                 this,
                 lastToken,
+                endParserState,
                 flags,
                 name,
                 type,
@@ -1126,6 +1156,7 @@
      * @see Compiler
      * @return the compile unit
      */
+    @Override
     public CompileUnit getCompileUnit() {
         return compileUnit;
     }
@@ -1147,6 +1178,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
@@ -1202,6 +1234,7 @@
                 new FunctionNode(
                         this,
                         lastToken,
+                        endParserState,
                         flags,
                         name,
                         returnType,
--- a/src/jdk/nashorn/internal/ir/IdentNode.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/ir/IdentNode.java	Tue Sep 16 13:59:37 2014 -0700
@@ -46,6 +46,8 @@
     private static final int INITIALIZED_HERE  = 1 << 1;
     private static final int FUNCTION          = 1 << 2;
     private static final int FUTURESTRICT_NAME = 1 << 3;
+    private static final int IS_DECLARED_HERE  = 1 << 4;
+    private static final int IS_DEAD           = 1 << 5;
 
     /** Identifier. */
     private final String name;
@@ -247,6 +249,45 @@
     }
 
     /**
+     * Is this a LET or CONST identifier used before its declaration?
+     *
+     * @return true if identifier is dead
+     */
+    public boolean isDead() {
+        return (flags & IS_DEAD) != 0;
+    }
+
+    /**
+     * Flag this IdentNode as a LET or CONST identifier used before its declaration.
+     *
+     * @return a new IdentNode equivalent to this but marked as dead.
+     */
+    public IdentNode markDead() {
+        return new IdentNode(this, name, type, flags | IS_DEAD, programPoint, conversion);
+    }
+
+    /**
+     * Is this IdentNode declared here?
+     *
+     * @return true if identifier is declared here
+     */
+    public boolean isDeclaredHere() {
+        return (flags & IS_DECLARED_HERE) != 0;
+    }
+
+    /**
+     * Flag this IdentNode as being declared here.
+     *
+     * @return a new IdentNode equivalent to this but marked as declared here.
+     */
+    public IdentNode setIsDeclaredHere() {
+        if (isDeclaredHere()) {
+            return this;
+        }
+        return new IdentNode(this, name, type, flags | IS_DECLARED_HERE, programPoint, conversion);
+    }
+
+    /**
      * Check if the name of this IdentNode is same as that of a compile-time property (currently __DIR__, __FILE__, and
      * __LINE__).
      *
--- a/src/jdk/nashorn/internal/ir/LexicalContext.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/ir/LexicalContext.java	Tue Sep 16 13:59:37 2014 -0700
@@ -351,8 +351,7 @@
     }
 
     /**
-     * Get the function for this block. If the block is itself a function
-     * this returns identity
+     * Get the function for this block.
      * @param block block for which to get function
      * @return function for block
      */
--- a/src/jdk/nashorn/internal/ir/LiteralNode.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/ir/LiteralNode.java	Tue Sep 16 13:59:37 2014 -0700
@@ -603,7 +603,7 @@
          * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can
          * be split if they are too large, for bytecode generation reasons
          */
-        public static final class ArrayUnit {
+        public static final class ArrayUnit implements CompileUnitHolder {
             /** Compile unit associated with the postsets range. */
             private final CompileUnit compileUnit;
 
@@ -642,6 +642,7 @@
              * The array compile unit
              * @return array compile unit
              */
+            @Override
             public CompileUnit getCompileUnit() {
                 return compileUnit;
             }
--- a/src/jdk/nashorn/internal/ir/SplitNode.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/ir/SplitNode.java	Tue Sep 16 13:59:37 2014 -0700
@@ -39,7 +39,7 @@
  * Node indicating code is split across classes.
  */
 @Immutable
-public class SplitNode extends LexicalContextStatement implements Labels {
+public class SplitNode extends LexicalContextStatement implements Labels, CompileUnitHolder {
     /** Split node method name. */
     private final String name;
 
@@ -116,6 +116,7 @@
      * Get the compile unit for this split node
      * @return compile unit
      */
+    @Override
     public CompileUnit getCompileUnit() {
         return compileUnit;
     }
--- a/src/jdk/nashorn/internal/ir/Symbol.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/ir/Symbol.java	Tue Sep 16 13:59:37 2014 -0700
@@ -54,17 +54,17 @@
     public static final int IS_VAR      = 2;
     /** Is this a parameter */
     public static final int IS_PARAM    = 3;
-    /** Is this a constant */
-    public static final int IS_CONSTANT = 4;
     /** Mask for kind flags */
-    public static final int KINDMASK = (1 << 3) - 1; // Kinds are represented by lower three bits
+    public static final int KINDMASK = (1 << 2) - 1; // Kinds are represented by lower two bits
 
     /** Is this symbol in scope */
-    public static final int IS_SCOPE                = 1 <<  3;
+    public static final int IS_SCOPE                = 1 <<  2;
     /** Is this a this symbol */
-    public static final int IS_THIS                 = 1 <<  4;
+    public static final int IS_THIS                 = 1 <<  3;
     /** Is this a let */
-    public static final int IS_LET                  = 1 <<  5;
+    public static final int IS_LET                  = 1 <<  4;
+    /** Is this a const */
+    public static final int IS_CONST                = 1 <<  5;
     /** Is this an internal symbol, never represented explicitly in source code */
     public static final int IS_INTERNAL             = 1 <<  6;
     /** Is this a function self-reference symbol */
@@ -83,6 +83,8 @@
     public static final int HAS_DOUBLE_VALUE        = 1 << 13;
     /** Is this symbol known to store an object value ? */
     public static final int HAS_OBJECT_VALUE        = 1 << 14;
+    /** Is this symbol seen a declaration? Used for block scoped LET and CONST symbols only. */
+    public static final int HAS_BEEN_DECLARED       = 1 << 15;
 
     /** Null or name identifying symbol. */
     private final String name;
@@ -184,14 +186,17 @@
             sb.append(" global");
             break;
         case IS_VAR:
-            sb.append(" var");
+            if (isConst()) {
+                sb.append(" const");
+            } else if (isLet()) {
+                sb.append(" let");
+            } else {
+                sb.append(" var");
+            }
             break;
         case IS_PARAM:
             sb.append(" param");
             break;
-        case IS_CONSTANT:
-            sb.append(" const");
-            break;
         default:
             break;
         }
@@ -204,10 +209,6 @@
             sb.append(" internal");
         }
 
-        if (isLet()) {
-            sb.append(" let");
-        }
-
         if (isThis()) {
             sb.append(" this");
         }
@@ -410,8 +411,8 @@
      * Check if this symbol is a constant
      * @return true if a constant
      */
-    public boolean isConstant() {
-        return (flags & KINDMASK) == IS_CONSTANT;
+    public boolean isConst() {
+        return (flags & IS_CONST) != 0;
     }
 
     /**
@@ -440,15 +441,6 @@
     }
 
     /**
-     * Flag this symbol as a let
-     */
-    public void setIsLet() {
-        if (!isLet()) {
-            flags |= IS_LET;
-        }
-    }
-
-    /**
      * Flag this symbol as a function's self-referencing symbol.
      * @return true if this symbol as a function's self-referencing symbol.
      */
@@ -456,6 +448,20 @@
         return (flags & IS_FUNCTION_SELF) != 0;
     }
 
+    public boolean isBlockScoped() {
+        return isLet() || isConst();
+    }
+
+    public boolean hasBeenDeclared() {
+        return (flags & HAS_BEEN_DECLARED) != 0;
+    }
+
+    public void setHasBeenDeclared() {
+        if (!hasBeenDeclared()) {
+            flags |= HAS_BEEN_DECLARED;
+        }
+    }
+
     /**
      * Get the index of the field used to store this symbol, should it be an AccessorProperty
      * and get allocated in a JO-prefixed ScriptObject subclass.
--- a/src/jdk/nashorn/internal/ir/VarNode.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/ir/VarNode.java	Tue Sep 16 13:59:37 2014 -0700
@@ -27,6 +27,7 @@
 
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.Token;
 
 /**
  * Node represents a var/let declaration.
@@ -43,12 +44,18 @@
     private final int flags;
 
     /** Flag that determines if this function node is a statement */
-    public static final int IS_STATEMENT = 1 << 0;
+    public static final int IS_STATEMENT                 = 1 << 0;
+
+    /** Flag for ES6 LET declaration */
+    public static final int IS_LET                       = 1 << 1;
+
+    /** Flag for ES6 CONST declaration */
+    public static final int IS_CONST                     = 1 << 2;
 
     /** Flag that determines if this is the last function declaration in a function
      *  This is used to micro optimize the placement of return value assignments for
      *  a program node */
-    public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 1;
+    public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 3;
 
     /**
      * Constructor
@@ -109,6 +116,43 @@
     }
 
     /**
+     * Is this a VAR node block scoped? This returns true for ECMAScript 6 LET and CONST nodes.
+     * @return true if an ES6 LET or CONST node
+     */
+    public boolean isBlockScoped() {
+        return getFlag(IS_LET) || getFlag(IS_CONST);
+    }
+
+    /**
+     * Is this an ECMAScript 6 LET node?
+     * @return true if LET node
+     */
+    public boolean isLet() {
+        return getFlag(IS_LET);
+    }
+
+    /**
+     * Is this an ECMAScript 6 CONST node?
+     * @return true if CONST node
+     */
+    public boolean isConst() {
+        return getFlag(IS_CONST);
+    }
+
+    /**
+     * Return the flags to use for symbols for this declaration.
+     * @return the symbol flags
+     */
+    public int getSymbolFlags() {
+        if (isLet()) {
+            return Symbol.IS_VAR | Symbol.IS_LET;
+        } else if (isConst()) {
+            return Symbol.IS_VAR | Symbol.IS_CONST;
+        }
+        return Symbol.IS_VAR;
+    }
+
+    /**
      * Does this variable declaration have an init value
      * @return true if an init exists, false otherwise
      */
@@ -139,7 +183,7 @@
 
     @Override
     public void toString(final StringBuilder sb, final boolean printType) {
-        sb.append("var ");
+        sb.append(Token.descType(getToken()).getName()).append(' ');
         name.toString(sb, printType);
 
         if (init != null) {
--- a/src/jdk/nashorn/internal/objects/Global.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/objects/Global.java	Tue Sep 16 13:59:37 2014 -0700
@@ -631,6 +631,24 @@
     }
 
     /**
+     * Returns a method handle that creates a wrapper object for a JS primitive value.
+     *
+     * @param self receiver object
+     * @return method handle to create wrapper objects for primitive receiver
+     */
+    public static MethodHandle getPrimitiveWrapFilter(final Object self) {
+        if (self instanceof String || self instanceof ConsString) {
+            return NativeString.WRAPFILTER;
+        } else if (self instanceof Number) {
+            return NativeNumber.WRAPFILTER;
+        } else if (self instanceof Boolean) {
+            return NativeBoolean.WRAPFILTER;
+        }
+        throw new IllegalArgumentException("Unsupported primitive: " + self);
+    }
+
+
+    /**
      * Create a new empty script object
      *
      * @return the new ScriptObject
--- a/src/jdk/nashorn/internal/objects/NativeBoolean.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeBoolean.java	Tue Sep 16 13:59:37 2014 -0700
@@ -51,9 +51,9 @@
 public final class NativeBoolean extends ScriptObject {
     private final boolean value;
 
-    // Method handle to create an object wrapper for a primitive boolean
-    private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class));
-    // Method handle to retrieve the Boolean prototype object
+    /** Method handle to create an object wrapper for a primitive boolean. */
+    static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class));
+    /** Method handle to retrieve the Boolean prototype object. */
     private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
 
     // initialized by nasgen
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Tue Sep 16 13:59:37 2014 -0700
@@ -28,6 +28,7 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -697,7 +698,7 @@
                 if (methodHandle != null) {
                     return new GuardedInvocation(
                             methodHandle,
-                            testJSAdaptor(adaptee, findData.getGetter(Object.class, UnwarrantedOptimismException.INVALID_PROGRAM_POINT), findData.getOwner(), func),
+                            testJSAdaptor(adaptee, findData.getGetter(Object.class, INVALID_PROGRAM_POINT, null), findData.getOwner(), func),
                             adaptee.getProtoSwitchPoint(hook, findData.getOwner()));
                 }
              }
--- a/src/jdk/nashorn/internal/objects/NativeNumber.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeNumber.java	Tue Sep 16 13:59:37 2014 -0700
@@ -57,9 +57,9 @@
 @ScriptClass("Number")
 public final class NativeNumber extends ScriptObject {
 
-    // Method handle to create an object wrapper for a primitive number
-    private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class));
-    // Method handle to retrieve the Number prototype object
+    /** Method handle to create an object wrapper for a primitive number. */
+    static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class));
+    /** Method handle to retrieve the Number prototype object. */
     private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
 
     /** ECMA 15.7.3.2 largest positive finite value */
--- a/src/jdk/nashorn/internal/objects/NativeString.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeString.java	Tue Sep 16 13:59:37 2014 -0700
@@ -71,9 +71,9 @@
 
     private final CharSequence value;
 
-    // Method handle to create an object wrapper for a primitive string
-    private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class));
-    // Method handle to retrieve the String prototype object
+    /** Method handle to create an object wrapper for a primitive string */
+    static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class));
+    /** Method handle to retrieve the String prototype object */
     private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
 
     // initialized by nasgen
--- a/src/jdk/nashorn/internal/parser/AbstractParser.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/parser/AbstractParser.java	Tue Sep 16 13:59:37 2014 -0700
@@ -326,18 +326,28 @@
     }
 
     /**
-     * Check next token and advance.
+     * Check current token and advance to the next token.
      *
      * @param expected Expected tokenType.
      *
      * @throws ParserException on unexpected token type
      */
     protected final void expect(final TokenType expected) throws ParserException {
+        expectDontAdvance(expected);
+        next();
+    }
+
+    /**
+     * Check current token, but don't advance to the next token.
+     *
+     * @param expected Expected tokenType.
+     *
+     * @throws ParserException on unexpected token type
+     */
+    protected final void expectDontAdvance(final TokenType expected) throws ParserException {
         if (type != expected) {
             throw error(expectMessage(expected));
         }
-
-        next();
     }
 
     /**
--- a/src/jdk/nashorn/internal/parser/Lexer.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/parser/Lexer.java	Tue Sep 16 13:59:37 2014 -0700
@@ -35,6 +35,7 @@
 import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
 import static jdk.nashorn.internal.parser.TokenType.EXECSTRING;
 import static jdk.nashorn.internal.parser.TokenType.FLOATING;
+import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
 import static jdk.nashorn.internal.parser.TokenType.HEXADECIMAL;
 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
@@ -85,6 +86,9 @@
     /** Type of last token added. */
     private TokenType last;
 
+    private final boolean pauseOnFunctionBody;
+    private boolean pauseOnNextLeftBrace;
+
     private static final String SPACETAB = " \t";  // ASCII space and tab
     private static final String LFCR     = "\n\r"; // line feed and carriage return (ctrl-m)
 
@@ -182,20 +186,23 @@
      * @param scripting are we in scripting mode
      */
     public Lexer(final Source source, final TokenStream stream, final boolean scripting) {
-        this(source, 0, source.getLength(), stream, scripting);
+        this(source, 0, source.getLength(), stream, scripting, false);
     }
 
     /**
-     * Contructor
+     * Constructor
      *
      * @param source    the source
      * @param start     start position in source from which to start lexing
      * @param len       length of source segment to lex
      * @param stream    token stream to lex
      * @param scripting are we in scripting mode
+     * @param pauseOnFunctionBody if true, lexer will return from {@link #lexify()} when it encounters a
+     * function body. This is used with the feature where the parser is skipping nested function bodies to
+     * avoid reading ahead unnecessarily when we skip the function bodies.
      */
 
-    public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting) {
+    public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean pauseOnFunctionBody) {
         super(source.getContent(), 1, start, len);
         this.source      = source;
         this.stream      = stream;
@@ -203,6 +210,8 @@
         this.nested      = false;
         this.pendingLine = 1;
         this.last        = EOL;
+
+        this.pauseOnFunctionBody = pauseOnFunctionBody;
     }
 
     private Lexer(final Lexer lexer, final State state) {
@@ -216,6 +225,7 @@
         pendingLine = state.pendingLine;
         linePosition = state.linePosition;
         last = EOL;
+        pauseOnFunctionBody = false;
     }
 
     static class State extends Scanner.State {
@@ -810,6 +820,9 @@
         final int length = scanIdentifier();
         // Check to see if it is a keyword.
         final TokenType type = TokenLookup.lookupKeyword(content, start, length);
+        if (type == FUNCTION && pauseOnFunctionBody) {
+            pauseOnNextLeftBrace = true;
+        }
         // Add keyword or identifier token.
         add(type, start);
     }
@@ -1597,6 +1610,9 @@
                 // We break to let the parser decide what it is.
                 if (canStartLiteral(type)) {
                     break;
+                } else if (type == LBRACE && pauseOnNextLeftBrace) {
+                    pauseOnNextLeftBrace = false;
+                    break;
                 }
             } else if (Character.isJavaIdentifierStart(ch0) || ch0 == '\\' && ch1 == 'u') {
                 // Scan and add identifier or keyword.
--- a/src/jdk/nashorn/internal/parser/Parser.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/parser/Parser.java	Tue Sep 16 13:59:37 2014 -0700
@@ -45,6 +45,7 @@
 import static jdk.nashorn.internal.parser.TokenType.IF;
 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
+import static jdk.nashorn.internal.parser.TokenType.LET;
 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
 import static jdk.nashorn.internal.parser.TokenType.RBRACE;
 import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
@@ -147,7 +148,7 @@
     /** to receive line information from Lexer when scanning multine literals. */
     protected final Lexer.LineInfoReceiver lineInfoReceiver;
 
-    private int nextFunctionId;
+    private RecompilableScriptFunctionData reparsedFunction;
 
     /**
      * Constructor
@@ -170,7 +171,7 @@
      * @param log debug logger if one is needed
      */
     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
-        this(env, source, errors, strict, FunctionNode.FIRST_FUNCTION_ID, 0, log);
+        this(env, source, errors, strict, 0, log);
     }
 
     /**
@@ -180,15 +181,13 @@
      * @param source  source to parse
      * @param errors  error manager
      * @param strict  parser created with strict mode enabled.
-     * @param nextFunctionId  starting value for assigning new unique ids to function nodes
      * @param lineOffset line offset to start counting lines from
      * @param log debug logger if one is needed
      */
-    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int nextFunctionId, final int lineOffset, final DebugLogger log) {
+    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) {
         super(source, errors, strict, lineOffset);
         this.env = env;
         this.namespace = new Namespace(env.getNamespace());
-        this.nextFunctionId    = nextFunctionId;
         this.scripting = env._scripting;
         if (this.scripting) {
             this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
@@ -227,6 +226,16 @@
     }
 
     /**
+     * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this
+     * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation).
+     * This will trigger various special behaviors, such as skipping nested function bodies.
+     * @param reparsedFunction the function being reparsed.
+     */
+    public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) {
+        this.reparsedFunction = reparsedFunction;
+    }
+
+    /**
      * Execute parse and return the resulting function node.
      * Errors will be thrown and the error manager will contain information
      * if parsing should fail
@@ -263,7 +272,7 @@
 
         try {
             stream = new TokenStream();
-            lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions);
+            lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, reparsedFunction != null);
             lexer.line = lexer.pendingLine = lineOffset + 1;
             line = lineOffset;
 
@@ -471,7 +480,6 @@
         final FunctionNode functionNode =
             new FunctionNode(
                 source,
-                nextFunctionId++,
                 functionLine,
                 token,
                 Token.descPosition(token),
@@ -579,6 +587,10 @@
         }
     }
 
+    private boolean useBlockScope() {
+        return env._es6;
+    }
+
     private static boolean isArguments(final String name) {
         return ARGUMENTS_NAME.equals(name);
     }
@@ -694,9 +706,20 @@
             FunctionNode.Kind.SCRIPT,
             functionLine);
 
+        // If ES6 block scope is enabled add a per-script block for top-level LET and CONST declarations.
+        final int startLine = start;
+        Block outer = useBlockScope() ? newBlock() : null;
         functionDeclarations = new ArrayList<>();
-        sourceElements(allowPropertyFunction);
-        addFunctionDeclarations(script);
+
+        try {
+            sourceElements(allowPropertyFunction);
+            addFunctionDeclarations(script);
+        } finally {
+            if (outer != null) {
+                outer = restoreBlock(outer);
+                appendStatement(new BlockStatement(startLine, outer));
+            }
+        }
         functionDeclarations = null;
 
         expect(EOF);
@@ -868,7 +891,7 @@
             block();
             break;
         case VAR:
-            variableStatement(true);
+            variableStatement(type, true);
             break;
         case SEMICOLON:
             emptyStatement();
@@ -918,8 +941,12 @@
             expect(SEMICOLON);
             break;
         default:
+            if (useBlockScope() && (type == LET || type == CONST)) {
+                variableStatement(type, true);
+                break;
+            }
             if (env._const_as_var && type == CONST) {
-                variableStatement(true);
+                variableStatement(TokenType.VAR, true);
                 break;
             }
 
@@ -1035,11 +1062,17 @@
      * Parse a VAR statement.
      * @param isStatement True if a statement (not used in a FOR.)
      */
-    private List<VarNode> variableStatement(final boolean isStatement) {
+    private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
         // VAR tested in caller.
         next();
 
         final List<VarNode> vars = new ArrayList<>();
+        int varFlags = VarNode.IS_STATEMENT;
+        if (varType == LET) {
+            varFlags |= VarNode.IS_LET;
+        } else if (varType == CONST) {
+            varFlags |= VarNode.IS_CONST;
+        }
 
         while (true) {
             // Get starting token.
@@ -1063,10 +1096,12 @@
                 } finally {
                     defaultNames.pop();
                 }
+            } else if (varType == CONST) {
+                throw error(AbstractParser.message("missing.const.assignment", name.getName()));
             }
 
             // Allocate var node.
-            final VarNode var = new VarNode(varLine, varToken, finish, name, init);
+            final VarNode var = new VarNode(varLine, varToken, finish, name.setIsDeclaredHere(), init, varFlags);
             vars.add(var);
             appendStatement(var);
 
@@ -1180,9 +1215,12 @@
      * Parse a FOR statement.
      */
     private void forStatement() {
+        // When ES6 for-let is enabled we create a container block to capture the LET.
+        final int startLine = start;
+        Block outer = useBlockScope() ? newBlock() : null;
+
         // Create FOR node, capturing FOR token.
         ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, ForNode.IS_FOR);
-
         lc.push(forNode);
 
         try {
@@ -1203,14 +1241,19 @@
             switch (type) {
             case VAR:
                 // Var statements captured in for outer block.
-                vars = variableStatement(false);
+                vars = variableStatement(type, false);
                 break;
             case SEMICOLON:
                 break;
             default:
+                if (useBlockScope() && (type == LET || type == CONST)) {
+                    // LET/CONST captured in container block created above.
+                    vars = variableStatement(type, false);
+                    break;
+                }
                 if (env._const_as_var && type == CONST) {
                     // Var statements captured in for outer block.
-                    vars = variableStatement(false);
+                    vars = variableStatement(TokenType.VAR, false);
                     break;
                 }
 
@@ -1290,8 +1333,13 @@
             appendStatement(forNode);
         } finally {
             lc.pop(forNode);
+            if (outer != null) {
+                outer.setFinish(forNode.getFinish());
+                outer = restoreBlock(outer);
+                appendStatement(new BlockStatement(startLine, outer));
+            }
         }
-     }
+    }
 
     /**
      * ... IterationStatement :
@@ -1722,7 +1770,7 @@
         }
     }
 
-   /**
+    /**
      * ThrowStatement :
      *      throw Expression ; // [no LineTerminator here]
      *
@@ -2609,7 +2657,7 @@
         FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL, functionLine);
 
         if (isStatement) {
-            if (topLevel) {
+            if (topLevel || useBlockScope()) {
                 functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED);
             } else if (isStrictMode) {
                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
@@ -2661,9 +2709,16 @@
         }
 
         if (isStatement) {
-            final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, VarNode.IS_STATEMENT);
+            int varFlags = VarNode.IS_STATEMENT;
+            if (!topLevel && useBlockScope()) {
+                // mark ES6 block functions as lexically scoped
+                varFlags |= VarNode.IS_LET;
+            }
+            final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags);
             if (topLevel) {
                 functionDeclarations.add(varNode);
+            } else if (useBlockScope()) {
+                prependStatement(varNode); // Hoist to beginning of current block
             } else {
                 appendStatement(varNode);
             }
@@ -2780,10 +2835,14 @@
         FunctionNode functionNode = null;
         long lastToken = 0L;
 
+        final boolean parseBody;
+        Object endParserState = null;
         try {
             // Create a new function block.
             functionNode = newFunctionNode(firstToken, ident, parameters, kind, functionLine);
-
+            assert functionNode != null;
+            final int functionId = functionNode.getId();
+            parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
             // Nashorn extension: expression closures
             if (!env._no_syntax_extensions && type != LBRACE) {
                 /*
@@ -2799,34 +2858,143 @@
                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
                 // EOL uses length field to store the line number
                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
-                final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
-                appendStatement(returnNode);
+                // Only create the return node if we aren't skipping nested functions. Note that we aren't
+                // skipping parsing of these extended functions; they're considered to be small anyway. Also,
+                // they don't end with a single well known token, so it'd be very hard to get correctly (see
+                // the note below for reasoning on skipping happening before instead of after RBRACE for
+                // details).
+                if (parseBody) {
+                    final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
+                    appendStatement(returnNode);
+                }
                 functionNode.setFinish(lastFinish);
-
             } else {
-                expect(LBRACE);
-
-                // Gather the function elements.
-                final List<Statement> prevFunctionDecls = functionDeclarations;
-                functionDeclarations = new ArrayList<>();
-                try {
-                    sourceElements(false);
-                    addFunctionDeclarations(functionNode);
-                } finally {
-                    functionDeclarations = prevFunctionDecls;
+                expectDontAdvance(LBRACE);
+                if (parseBody || !skipFunctionBody(functionNode)) {
+                    next();
+                    // Gather the function elements.
+                    final List<Statement> prevFunctionDecls = functionDeclarations;
+                    functionDeclarations = new ArrayList<>();
+                    try {
+                        sourceElements(false);
+                        addFunctionDeclarations(functionNode);
+                    } finally {
+                        functionDeclarations = prevFunctionDecls;
+                    }
+
+                    lastToken = token;
+                    if (parseBody) {
+                        // Since the lexer can read ahead and lexify some number of tokens in advance and have
+                        // them buffered in the TokenStream, we need to produce a lexer state as it was just
+                        // before it lexified RBRACE, and not whatever is its current (quite possibly well read
+                        // ahead) state.
+                        endParserState = new ParserState(Token.descPosition(token), line, linePosition);
+
+                        // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
+                        // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
+                        // state after it. The reason is that RBRACE is a well-known token that we can expect and
+                        // will never involve us getting into a weird lexer state, and as such is a great reparse
+                        // point. Typical example of a weird lexer state after RBRACE would be:
+                        //     function this_is_skipped() { ... } "use strict";
+                        // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
+                        // of compensating for the possibility of a string literal (or similar) after RBRACE,
+                        // we'll rather just restart parsing from this well-known, friendly token instead.
+                    }
                 }
-
-                lastToken = token;
                 expect(RBRACE);
                 functionNode.setFinish(finish);
             }
         } finally {
             functionNode = restoreFunctionNode(functionNode, lastToken);
         }
+
+        // NOTE: we can only do alterations to the function node after restoreFunctionNode.
+
+        if (parseBody) {
+            functionNode = functionNode.setEndParserState(lc, endParserState);
+        } else if (functionNode.getBody().getStatementCount() > 0){
+            // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
+            // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
+            // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
+            // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
+            // nested bodies early if we were supposed to skip 'em.
+            functionNode = functionNode.setBody(null, functionNode.getBody().setStatements(null,
+                    Collections.<Statement>emptyList()));
+        }
+
+        if (reparsedFunction != null) {
+            // We restore the flags stored in the function's ScriptFunctionData that we got when we first
+            // eagerly parsed the code. We're doing it because some flags would be set based on the
+            // content of the function, or even content of its nested functions, most of which are normally
+            // skipped during an on-demand compilation.
+            final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
+            if (data != null) {
+                // Data can be null if when we originally parsed the file, we removed the function declaration
+                // as it was dead code.
+                functionNode = functionNode.setFlags(lc, data.getFunctionFlags());
+                // This compensates for missing markEval() in case the function contains an inner function
+                // that contains eval(), that now we didn't discover since we skipped the inner function.
+                if (functionNode.hasNestedEval()) {
+                    assert functionNode.hasScopeBlock();
+                    functionNode = functionNode.setBody(lc, functionNode.getBody().setNeedsScope(null));
+                }
+            }
+        }
         printAST(functionNode);
         return functionNode;
     }
 
+    private boolean skipFunctionBody(final FunctionNode functionNode) {
+        if (reparsedFunction == null) {
+            // Not reparsing, so don't skip any function body.
+            return false;
+        }
+        // Skip to the RBRACE of this function, and continue parsing from there.
+        final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
+        if (data == null) {
+            // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
+            // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
+            // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
+            return false;
+        }
+        final ParserState parserState = (ParserState)data.getEndParserState();
+        assert parserState != null;
+
+        stream.reset();
+        lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions);
+        line = parserState.line;
+        linePosition = parserState.linePosition;
+        // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
+        // the RBRACE.
+        type = SEMICOLON;
+        k = -1;
+        next();
+
+        return true;
+    }
+
+    /**
+     * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
+     * for resuming parsing after skipping a function body.
+     */
+    private static class ParserState {
+        private final int position;
+        private final int line;
+        private final int linePosition;
+
+        ParserState(final int position, final int line, final int linePosition) {
+            this.position = position;
+            this.line = line;
+            this.linePosition = linePosition;
+        }
+
+        Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) {
+            final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true);
+            newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
+            return newLexer;
+        }
+    }
+
     private void printAST(final FunctionNode functionNode) {
         if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
             env.getErr().println(new ASTWriter(functionNode));
@@ -2838,7 +3006,6 @@
     }
 
     private void addFunctionDeclarations(final FunctionNode functionNode) {
-        assert lc.peek() == lc.getFunctionBody(functionNode);
         VarNode lastDecl = null;
         for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
             Statement decl = functionDeclarations.get(i);
@@ -3200,6 +3367,9 @@
             } else {
                 lc.setFlag(fn, FunctionNode.HAS_NESTED_EVAL);
             }
+            // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
+            // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
+            // this method when the parser skips a nested function.
             lc.setBlockNeedsScope(lc.getFunctionBody(fn));
         }
     }
--- a/src/jdk/nashorn/internal/parser/TokenStream.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/parser/TokenStream.java	Tue Sep 16 13:59:37 2014 -0700
@@ -209,4 +209,8 @@
         in = count;
         buffer = newBuffer;
     }
+
+    void reset() {
+        in = out = count = base = 0;
+    }
 }
--- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Tue Sep 16 13:59:37 2014 -0700
@@ -549,6 +549,8 @@
                 type == Object.class :
                 "invalid getter type " + type + " for " + getKey();
 
+        checkUndeclared();
+
         //all this does is add a return value filter for object fields only
         final MethodHandle[] getterCache = GETTER_CACHE;
         final MethodHandle cachedGetter = getterCache[i];
@@ -579,6 +581,8 @@
             return getOptimisticPrimitiveGetter(type, programPoint);
         }
 
+        checkUndeclared();
+
         return debug(
             createGetter(
                 getCurrentType(),
@@ -608,6 +612,13 @@
         return newMap;
     }
 
+    private void checkUndeclared() {
+        if ((getFlags() & NEEDS_DECLARATION) != 0) {
+            // a lexically defined variable that hasn't seen its declaration - throw ReferenceError
+            throw ECMAErrors.referenceError("not.defined", getKey());
+        }
+    }
+
     // the final three arguments are for debug printout purposes only
     @SuppressWarnings("unused")
     private static Object replaceMap(final Object sobj, final PropertyMap newMap) {
@@ -635,13 +646,14 @@
 
     @Override
     public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
-        final int      i       = getAccessorTypeIndex(type);
-        final int      ci      = isUndefined() ? -1 : getAccessorTypeIndex(getCurrentType());
-        final Class<?> forType = isUndefined() ? type : getCurrentType();
+        checkUndeclared();
+
+        final int typeIndex        = getAccessorTypeIndex(type);
+        final int currentTypeIndex = getAccessorTypeIndex(getCurrentType());
 
         //if we are asking for an object setter, but are still a primitive type, we might try to box it
         MethodHandle mh;
-        if (needsInvalidator(i, ci)) {
+        if (needsInvalidator(typeIndex, currentTypeIndex)) {
             final Property     newProperty = getWiderProperty(type);
             final PropertyMap  newMap      = getWiderMap(currentMap, newProperty);
 
@@ -652,6 +664,7 @@
                  mh = ObjectClassGenerator.createGuardBoxedPrimitiveSetter(ct, generateSetter(ct, ct), mh);
             }
         } else {
+            final Class<?> forType = isUndefined() ? type : getCurrentType();
             mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type);
         }
 
@@ -692,11 +705,12 @@
         if (OBJECT_FIELDS_ONLY) {
             return false;
         }
-        return getCurrentType() != Object.class && (isConfigurable() || isWritable());
+        // Return true for currently undefined even if non-writable/configurable to allow initialization of ES6 CONST.
+        return getCurrentType() == null || (getCurrentType() != Object.class && (isConfigurable() || isWritable()));
     }
 
-    private boolean needsInvalidator(final int ti, final int fti) {
-        return canChangeType() && ti > fti;
+    private boolean needsInvalidator(final int typeIndex, final int currentTypeIndex) {
+        return canChangeType() && typeIndex > currentTypeIndex;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014, 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.runtime;
+
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
+
+/**
+ * Encapsulates the allocation strategy for a function when used as a constructor. Basically the same as
+ * {@link AllocatorDescriptor}, but with an additionally cached resolved method handle. There is also a
+ * canonical default allocation strategy for functions that don't assign any "this" properties (vast majority
+ * of all functions), therefore saving some storage space in {@link RecompilableScriptFunctionData} that would
+ * otherwise be lost to identical tuples of (map, className, handle) fields.
+ */
+final class AllocationStrategy implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+    private static final AllocationStrategy DEFAULT_STRATEGY = new AllocationStrategy(new AllocatorDescriptor(0));
+
+    /** Allocator map from allocator descriptor */
+    private final PropertyMap allocatorMap;
+
+    /** Name of class where allocator function resides */
+    private final String allocatorClassName;
+
+    /** lazily generated allocator */
+    private transient MethodHandle allocator;
+
+    private AllocationStrategy(final AllocatorDescriptor desc) {
+        this.allocatorMap = desc.getAllocatorMap();
+        // These classes get loaded, so an interned variant of their name is most likely around anyway.
+        this.allocatorClassName = desc.getAllocatorClassName().intern();
+    }
+
+    private boolean matches(final AllocatorDescriptor desc) {
+        return desc.getAllocatorMap().size() == allocatorMap.size() &&
+                desc.getAllocatorClassName().equals(allocatorClassName);
+    }
+
+    static AllocationStrategy get(final AllocatorDescriptor desc) {
+        return DEFAULT_STRATEGY.matches(desc) ? DEFAULT_STRATEGY : new AllocationStrategy(desc);
+    }
+
+    PropertyMap getAllocatorMap() {
+        return allocatorMap;
+    }
+
+    ScriptObject allocate(final PropertyMap map) {
+        try {
+            if (allocator == null) {
+                allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName),
+                        CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class));
+            }
+            return (ScriptObject)allocator.invokeExact(map);
+        } catch (final RuntimeException | Error e) {
+            throw e;
+        } catch (final Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    private Object readResolve() {
+        if(allocatorMap.size() == DEFAULT_STRATEGY.allocatorMap.size() &&
+                allocatorClassName.equals(DEFAULT_STRATEGY.allocatorClassName)) {
+            return DEFAULT_STRATEGY;
+        }
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return "AllocationStrategy[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" +
+                allocatorMap.size() + "]";
+    }
+}
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Tue Sep 16 13:59:37 2014 -0700
@@ -80,12 +80,6 @@
     public long getUniqueScriptId();
 
     /**
-     * Get next unique eval id
-     * @return unique eval id
-     */
-    public long getUniqueEvalId();
-
-    /**
      * Store a compiled script for later reuse
      * @param source the script source
      * @param mainClassName the main class name
--- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Tue Sep 16 13:59:37 2014 -0700
@@ -27,7 +27,6 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
-
 import java.lang.invoke.CallSite;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -39,6 +38,7 @@
 import java.util.TreeMap;
 import java.util.function.Supplier;
 import java.util.logging.Level;
+
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
--- a/src/jdk/nashorn/internal/runtime/Context.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/Context.java	Tue Sep 16 13:59:37 2014 -0700
@@ -196,16 +196,11 @@
         }
 
         @Override
-        public long getUniqueEvalId() {
-            return context.getUniqueEvalId();
-        }
-
-        @Override
-        public void storeScript(final String classInfoFile, final Source source, final String mainClassName,
+        public void storeScript(final String cacheKey, final Source source, final String mainClassName,
                                 final Map<String,byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers,
                                 final Object[] constants, final int compilationId) {
             if (context.codeStore != null) {
-                context.codeStore.storeScript(classInfoFile, source, mainClassName, classBytes, initializers, constants, compilationId);
+                context.codeStore.storeScript(cacheKey, source, mainClassName, classBytes, initializers, constants, compilationId);
             }
         }
 
@@ -334,9 +329,6 @@
     /** Unique id for script. Used only when --loader-per-compile=false */
     private final AtomicLong uniqueScriptId;
 
-    /** Unique id for 'eval' */
-    private final AtomicLong uniqueEvalId;
-
     /** Optional class filter to use for Java classes. Can be null. */
     private final ClassFilter classFilter;
 
@@ -450,7 +442,6 @@
             this.uniqueScriptId = new AtomicLong();
         }
         this.errors    = errors;
-        this.uniqueEvalId = new AtomicLong();
 
         // if user passed -classpath option, make a class loader with that and set it as
         // thread context class loader so that script can access classes from that path.
@@ -1132,7 +1123,7 @@
         if (storedScript == null) {
             functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse();
 
-            if (errors.hasErrors()) {
+            if (errMan.hasErrors()) {
                 return null;
             }
 
@@ -1162,9 +1153,13 @@
                     env,
                     installer,
                     source,
+                    errMan,
                     strict | functionNode.isStrict());
 
             final FunctionNode compiledFunction = compiler.compile(functionNode, phases);
+            if (errMan.hasErrors()) {
+                return null;
+            }
             script = compiledFunction.getRootClass();
             compiler.persistClassInfo(cacheKey, compiledFunction);
         } else {
@@ -1186,10 +1181,6 @@
              }, CREATE_LOADER_ACC_CTXT);
     }
 
-    private long getUniqueEvalId() {
-        return uniqueEvalId.getAndIncrement();
-    }
-
     private long getUniqueScriptId() {
         return uniqueScriptId.getAndIncrement();
     }
--- a/src/jdk/nashorn/internal/runtime/FindProperty.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/FindProperty.java	Tue Sep 16 13:59:37 2014 -0700
@@ -29,7 +29,9 @@
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
 
 import java.lang.invoke.MethodHandle;
+import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.objects.Global;
 
 /**
  * This class represents the result from a find property search.
@@ -58,6 +60,18 @@
     }
 
     /**
+     * Return a copy of this FindProperty with a different property.
+     *
+     * @param newProperty the new property
+     * @return the new FindProperty instance
+     */
+    public FindProperty replaceProperty(final Property newProperty) {
+        assert this.property.getKey().equals(newProperty.getKey());
+        assert this.property.getSlot() == newProperty.getSlot();
+        return new FindProperty(self, prototype, newProperty);
+    }
+
+    /**
      * Ask for a getter that returns the given type. The type has nothing to do with the
      * internal representation of the property. It may be an Object (boxing primitives) or
      * a primitive (primitive fields with -Dnashorn.fields.dual=true)
@@ -67,25 +81,17 @@
      * @param programPoint program point, or INVALID_PROGRAM_POINT if pessimistic
      * @return method handle for the getter
      */
-    public MethodHandle getGetter(final Class<?> type, final int programPoint) {
+    public MethodHandle getGetter(final Class<?> type, final int programPoint, final LinkRequest request) {
         final MethodHandle getter;
         if (isValid(programPoint)) {
             getter = property.getOptimisticGetter(type, programPoint);
         } else {
             getter = property.getGetter(type);
         }
-        return getGetterInner(getter);
-    }
-
-    private MethodHandle getGetterInner(final MethodHandle getter) {
         if (property instanceof UserAccessorProperty) {
-            final UserAccessorProperty uc        = (UserAccessorProperty)property;
-            final ScriptObject         owner     = getOwner();
-            final ScriptObject         container = (owner != null) ? owner : self;
-            return MH.insertArguments(getter, 0, uc.getAccessors(container));
+            return insertAccessorsGetter((UserAccessorProperty) property, request, getter);
         }
         return getter;
-
     }
 
     /**
@@ -99,18 +105,31 @@
      *
      * @return method handle for the getter
      */
-    public MethodHandle getSetter(final Class<?> type, final boolean strict) {
-        final MethodHandle setter = property.getSetter(type, getOwner().getMap());
+    public MethodHandle getSetter(final Class<?> type, final boolean strict, final LinkRequest request) {
+        MethodHandle setter = property.getSetter(type, getOwner().getMap());
         if (property instanceof UserAccessorProperty) {
-            final UserAccessorProperty uc        = (UserAccessorProperty)property;
-            final ScriptObject         owner     = getOwner();
-            final ScriptObject         container = (owner != null) ? owner : self;
-            return MH.insertArguments(setter, 0, uc.getAccessors(container), strict ? property.getKey() : null);
+            setter =  MH.insertArguments(setter, 1, strict ? property.getKey() : null);
+            return insertAccessorsGetter((UserAccessorProperty) property, request, setter);
         }
 
         return setter;
     }
 
+    // Fold an accessor getter into the method handle of a user accessor property.
+    private MethodHandle insertAccessorsGetter(final UserAccessorProperty uap, final LinkRequest request, final MethodHandle mh) {
+        MethodHandle superGetter = uap.getAccessorsGetter();
+        if (isInherited()) {
+            superGetter = ScriptObject.addProtoFilter(superGetter, getProtoChainLength());
+        }
+        if (request != null && !(request.getReceiver() instanceof ScriptObject)) {
+            final MethodHandle wrapFilter = Global.getPrimitiveWrapFilter(request.getReceiver());
+            superGetter = MH.filterArguments(superGetter, 0, wrapFilter.asType(wrapFilter.type().changeReturnType(superGetter.type().parameterType(0))));
+        }
+        superGetter = MH.asType(superGetter, superGetter.type().changeParameterType(0, Object.class));
+
+        return MH.foldArguments(mh, superGetter);
+    }
+
     /**
      * Return the {@code ScriptObject} owning of the property:  this means the prototype.
      * @return owner of property
@@ -124,7 +143,7 @@
      * @return appropriate receiver
      */
     public ScriptObject getGetterReceiver() {
-        return property != null && property.hasGetterFunction(prototype) ? self : prototype;
+        return property != null && property instanceof UserAccessorProperty ? self : prototype;
     }
 
     /**
--- a/src/jdk/nashorn/internal/runtime/GlobalConstants.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java	Tue Sep 16 13:59:37 2014 -0700
@@ -28,6 +28,8 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.getProgramPoint;
 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
 
 import java.lang.invoke.MethodHandle;
@@ -370,22 +372,19 @@
      * @param find      property lookup
      * @param receiver  receiver
      * @param desc      callsite descriptor
-     * @param request   link request
-     * @param operator  operator
      *
      * @return resulting getter, or null if failed to create constant
      */
-    synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
-        if (GLOBAL_ONLY && !find.getOwner().isGlobal()) {
+    synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) {
+        // Also return null if property may have side effects
+        if ((GLOBAL_ONLY && !find.getOwner().isGlobal()) || find.getProperty() instanceof UserAccessorProperty) {
             return null;
         }
 
-        final int programPoint         = NashornCallSiteDescriptor.isOptimistic(desc) ?
-            NashornCallSiteDescriptor.getProgramPoint(desc) :
-            UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
-        final boolean     isOptimistic = programPoint != UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
-        final Class<?>    retType      = desc.getMethodType().returnType();
-        final String      name         = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        final boolean  isOptimistic = NashornCallSiteDescriptor.isOptimistic(desc);
+        final int      programPoint = isOptimistic ? getProgramPoint(desc) : INVALID_PROGRAM_POINT;
+        final Class<?> retType      = desc.getMethodType().returnType();
+        final String   name         = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
 
         final Access acc = getOrCreateSwitchPoint(name);
 
--- a/src/jdk/nashorn/internal/runtime/JSType.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/JSType.java	Tue Sep 16 13:59:37 2014 -0700
@@ -938,11 +938,8 @@
      * @return double
      */
     public static int toInt32Optimistic(final Object obj, final int programPoint) {
-        if (obj != null) {
-            final Class<?> clz = obj.getClass();
-            if (clz == Integer.class) {
-                return ((Integer)obj).intValue();
-            }
+        if (obj != null && obj.getClass() == Integer.class) {
+            return ((Integer)obj).intValue();
         }
         throw new UnwarrantedOptimismException(obj, programPoint);
     }
--- a/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java	Tue Sep 16 13:59:37 2014 -0700
@@ -191,19 +191,20 @@
     }
 
     /**
-     * Returns the argument value as an int. If the argument is not a Number object that can be exactly represented as
-     * an int, throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code
-     * can use it. See {code CodeGenerator.ENSURE_INT}.
+     * Returns the argument value as an int. If the argument is not a wrapper for a primitive numeric type
+     * with a value that can be exactly represented as an int, throw an {@link UnwarrantedOptimismException}.
+     * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_INT}.
      * @param arg the original argument.
      * @param programPoint the program point used in the exception
      * @return the value of the argument as an int.
-     * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as an int.
+     * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with
+     * a value that can be exactly represented as an int.
      */
     public static int ensureInt(final Object arg, final int programPoint) {
         // NOTE: this doesn't delegate to ensureInt(double, int) as in that case if arg were a Long, it would throw a
         // (potentially imprecise) Double in the UnwarrantedOptimismException. This way, it will put the correct valued
         // Long into the exception.
-        if (arg instanceof Number) {
+        if (isPrimitiveNumberWrapper(arg)) {
             final double d = ((Number)arg).doubleValue();
             if (JSType.isRepresentableAsInt(d) && !JSType.isNegativeZero(d)) {
                 return (int)d;
@@ -212,6 +213,15 @@
         throw new UnwarrantedOptimismException(arg, programPoint);
     }
 
+    private static boolean isPrimitiveNumberWrapper(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        final Class<?> c = obj.getClass();
+        return c == Integer.class || c == Double.class || c == Long.class ||
+               c ==   Float.class || c ==  Short.class || c == Byte.class;
+    }
+
     @SuppressWarnings("unused")
     private static int ensureInt(final boolean arg, final int programPoint) {
         throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT);
@@ -236,35 +246,40 @@
     }
 
     /**
-     * Returns the argument value as a long. If the argument is not a Number object that can be exactly represented as
-     * a long, throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code
-     * can use it. See {code CodeGenerator.ENSURE_LONG}.
+     * Returns the argument value as a long. If the argument is not a wrapper for a primitive numeric type
+     * with a value that can be exactly represented as a long, throw an {@link UnwarrantedOptimismException}.
+     * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_LONG}.
      * @param arg the original argument.
      * @param programPoint the program point used in the exception
      * @return the value of the argument as a long.
-     * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as a long.
+     * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with
+     * a value that can be exactly represented as a long
      */
     public static long ensureLong(final Object arg, final int programPoint) {
-        if (arg instanceof Long) {
-            // Must check for Long separately, as Long.doubleValue() isn't precise.
-            return ((Long)arg).longValue();
-        } else if (arg instanceof Number) {
-            return ensureLong(((Number)arg).doubleValue(), programPoint);
+        if (arg != null) {
+            final Class<?> c = arg.getClass();
+            if (c == Long.class) {
+                // Must check for Long separately, as Long.doubleValue() isn't precise.
+                return ((Long)arg).longValue();
+            } else if (c == Integer.class || c == Double.class || c == Float.class || c == Short.class ||
+                    c == Byte.class) {
+                return ensureLong(((Number)arg).doubleValue(), programPoint);
+            }
         }
         throw new UnwarrantedOptimismException(arg, programPoint);
     }
 
     /**
-     * Returns the argument value as a double. If the argument is not a Number object, throw an
-     * {@link UnwarrantedOptimismException}.This method is only public so that generated script code can use it. See
-     * {code CodeGenerator.ENSURE_NUMBER}.
+     * Returns the argument value as a double. If the argument is not a a wrapper for a primitive numeric type
+     * throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code
+     * can use it. See {code CodeGenerator.ENSURE_NUMBER}.
      * @param arg the original argument.
      * @param programPoint the program point used in the exception
      * @return the value of the argument as a double.
-     * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as a long.
+     * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type.
      */
     public static double ensureNumber(final Object arg, final int programPoint) {
-        if (arg instanceof Number) { // arg == null -> false
+        if (isPrimitiveNumberWrapper(arg)) {
             return ((Number)arg).doubleValue();
         }
         throw new UnwarrantedOptimismException(arg, programPoint);
--- a/src/jdk/nashorn/internal/runtime/Property.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/Property.java	Tue Sep 16 13:59:37 2014 -0700
@@ -82,11 +82,14 @@
      * is narrower than object, e.g. Math.PI which is declared
      * as a double
      */
-    public static final int IS_NASGEN_PRIMITIVE = 1 << 6;
+    public static final int IS_NASGEN_PRIMITIVE     = 1 << 6;
 
     /** Is this property bound to a receiver? This means get/set operations will be delegated to
      *  a statically defined object instead of the object passed as callsite parameter. */
-    public static final int IS_BOUND = 1 << 8;
+    public static final int IS_BOUND                = 1 << 7;
+
+    /** Is this a lexically scoped LET or CONST variable that is dead until it is declared. */
+    public static final int NEEDS_DECLARATION       = 1 << 8;
 
     /** Property key. */
     private final String key;
@@ -287,6 +290,15 @@
     }
 
     /**
+     * Is this a LET or CONST property that needs to see its declaration before being usable?
+     *
+     * @return true if this is a block-scoped variable
+     */
+    public boolean needsDeclaration() {
+        return (flags & NEEDS_DECLARATION) == NEEDS_DECLARATION;
+    }
+
+    /**
      * Add more property flags to the property. Properties are immutable here,
      * so any property change that results in a larger flag set results in the
      * property being cloned. Use only the return value
--- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Tue Sep 16 13:59:37 2014 -0700
@@ -42,6 +42,7 @@
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.codegen.FunctionSignature;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
 import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
 import jdk.nashorn.internal.codegen.TypeMap;
 import jdk.nashorn.internal.codegen.types.Type;
@@ -55,7 +56,6 @@
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
-
 /**
  * This is a subclass that represents a script function that may be regenerated,
  * for example with specialization based on call site types, or lazily generated.
@@ -81,26 +81,29 @@
     /** Token of this function within the source. */
     private final long token;
 
-    /** Allocator map from makeMap() */
-    private final PropertyMap allocatorMap;
+    /**
+     * Represents the allocation strategy (property map, script object class, and method handle) for when
+     * this function is used as a constructor. Note that majority of functions (those not setting any this.*
+     * properties) will share a single canonical "default strategy" instance.
+     */
+    private final AllocationStrategy allocationStrategy;
+
+    /**
+     * Opaque object representing parser state at the end of the function. Used when reparsing outer function
+     * to help with skipping parsing inner functions.
+     */
+    private final Object endParserState;
 
     /** Code installer used for all further recompilation/specialization of this ScriptFunction */
     private transient CodeInstaller<ScriptEnvironment> installer;
 
-    /** Name of class where allocator function resides */
-    private final String allocatorClassName;
-
-    /** lazily generated allocator */
-    private transient MethodHandle allocator;
-
     private final Map<Integer, RecompilableScriptFunctionData> nestedFunctions;
 
     /** Id to parent function if one exists */
     private RecompilableScriptFunctionData parent;
 
-    private final boolean isDeclared;
-    private final boolean isAnonymous;
-    private final boolean needsCallee;
+    /** Copy of the {@link FunctionNode} flags. */
+    private final int functionFlags;
 
     private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
 
@@ -119,8 +122,7 @@
      *
      * @param functionNode        functionNode that represents this function code
      * @param installer           installer for code regeneration versions of this function
-     * @param allocatorClassName  name of our allocator class, will be looked up dynamically if used as a constructor
-     * @param allocatorMap        allocator map to seed instances with, when constructing
+     * @param allocationDescriptor descriptor for the allocation behavior when this function is used as a constructor
      * @param nestedFunctions     nested function map
      * @param externalScopeDepths external scope depths
      * @param internalSymbols     internal symbols to method, defined in its scope
@@ -128,30 +130,27 @@
     public RecompilableScriptFunctionData(
         final FunctionNode functionNode,
         final CodeInstaller<ScriptEnvironment> installer,
-        final String allocatorClassName,
-        final PropertyMap allocatorMap,
+        final AllocatorDescriptor allocationDescriptor,
         final Map<Integer, RecompilableScriptFunctionData> nestedFunctions,
         final Map<String, Integer> externalScopeDepths,
         final Set<String> internalSymbols) {
 
         super(functionName(functionNode),
               Math.min(functionNode.getParameters().size(), MAX_ARITY),
-              getFlags(functionNode));
+              getDataFlags(functionNode));
 
         this.functionName        = functionNode.getName();
         this.lineNumber          = functionNode.getLineNumber();
-        this.isDeclared          = functionNode.isDeclared();
-        this.needsCallee         = functionNode.needsCallee();
-        this.isAnonymous         = functionNode.isAnonymous();
+        this.functionFlags       = functionNode.getFlags() | (functionNode.needsCallee() ? FunctionNode.NEEDS_CALLEE : 0);
         this.functionNodeId      = functionNode.getId();
         this.source              = functionNode.getSource();
+        this.endParserState      = functionNode.getEndParserState();
         this.token               = tokenFor(functionNode);
         this.installer           = installer;
-        this.allocatorClassName  = allocatorClassName;
-        this.allocatorMap        = allocatorMap;
-        this.nestedFunctions     = nestedFunctions;
-        this.externalScopeDepths = externalScopeDepths;
-        this.internalSymbols     = new HashSet<>(internalSymbols);
+        this.allocationStrategy  = AllocationStrategy.get(allocationDescriptor);
+        this.nestedFunctions     = smallMap(nestedFunctions);
+        this.externalScopeDepths = smallMap(externalScopeDepths);
+        this.internalSymbols     = smallSet(new HashSet<>(internalSymbols));
 
         for (final RecompilableScriptFunctionData nfn : nestedFunctions.values()) {
             assert nfn.getParent() == null;
@@ -161,6 +160,27 @@
         createLogger();
     }
 
+    private static <K, V> Map<K, V> smallMap(final Map<K, V> map) {
+        if (map == null || map.isEmpty()) {
+            return Collections.emptyMap();
+        } else if (map.size() == 1) {
+            final Map.Entry<K, V> entry = map.entrySet().iterator().next();
+            return Collections.singletonMap(entry.getKey(), entry.getValue());
+        } else {
+            return map;
+        }
+    }
+
+    private static <T> Set<T> smallSet(final Set<T> set) {
+        if (set == null || set.isEmpty()) {
+            return Collections.emptySet();
+        } else if (set.size() == 1) {
+            return Collections.singleton(set.iterator().next());
+        } else {
+            return set;
+        }
+    }
+
     @Override
     public DebugLogger getLogger() {
         return log;
@@ -190,11 +210,7 @@
      * @return the external symbol table with proto depths
      */
     public int getExternalSymbolDepth(final String symbolName) {
-        final Map<String, Integer> map = externalScopeDepths;
-        if (map == null) {
-            return -1;
-        }
-        final Integer depth = map.get(symbolName);
+        final Integer depth = externalScopeDepths.get(symbolName);
         if (depth == null) {
             return -1;
         }
@@ -202,6 +218,23 @@
     }
 
     /**
+     * Returns the names of all external symbols this function uses.
+     * @return the names of all external symbols this function uses.
+     */
+    public Set<String> getExternalSymbolNames() {
+        return Collections.unmodifiableSet(externalScopeDepths.keySet());
+    }
+
+    /**
+     * Returns the opaque object representing the parser state at the end of this function's body, used to
+     * skip parsing this function when reparsing its containing outer function.
+     * @return the object representing the end parser state
+     */
+    public Object getEndParserState() {
+        return endParserState;
+    }
+
+    /**
      * Get the parent of this RecompilableScriptFunctionData. If we are
      * a nested function, we have a parent. Note that "null" return value
      * can also mean that we have a parent but it is unknown, so this can
@@ -269,7 +302,7 @@
 
     @Override
     public boolean inDynamicContext() {
-        return (flags & IN_DYNAMIC_CONTEXT) != 0;
+        return getFunctionFlag(FunctionNode.IN_DYNAMIC_CONTEXT);
     }
 
     private static String functionName(final FunctionNode fn) {
@@ -293,7 +326,7 @@
         return Token.toDesc(TokenType.FUNCTION, position, length);
     }
 
-    private static int getFlags(final FunctionNode functionNode) {
+    private static int getDataFlags(final FunctionNode functionNode) {
         int flags = IS_CONSTRUCTOR;
         if (functionNode.isStrict()) {
             flags |= IS_STRICT;
@@ -307,37 +340,20 @@
         if (functionNode.isVarArg()) {
             flags |= IS_VARIABLE_ARITY;
         }
-        if (functionNode.inDynamicContext()) {
-            flags |= IN_DYNAMIC_CONTEXT;
-        }
         return flags;
     }
 
     @Override
     PropertyMap getAllocatorMap() {
-        return allocatorMap;
+        return allocationStrategy.getAllocatorMap();
     }
 
     @Override
     ScriptObject allocate(final PropertyMap map) {
-        try {
-            ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try
-            return allocator == null ? null : (ScriptObject)allocator.invokeExact(map);
-        } catch (final RuntimeException | Error e) {
-            throw e;
-        } catch (final Throwable t) {
-            throw new RuntimeException(t);
-        }
-    }
-
-    private void ensureHasAllocator() throws ClassNotFoundException {
-        if (allocator == null && allocatorClassName != null) {
-            this.allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName), CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class));
-        }
+        return allocationStrategy.allocate(map);
     }
 
     FunctionNode reparse() {
-        final boolean isProgram = functionNodeId == FunctionNode.FIRST_FUNCTION_ID;
         // NOTE: If we aren't recompiling the top-level program, we decrease functionNodeId 'cause we'll have a synthetic program node
         final int descPosition = Token.descPosition(token);
         final Context context = Context.getContextTrusted();
@@ -346,18 +362,27 @@
             source,
             new Context.ThrowErrorManager(),
             isStrict(),
-            functionNodeId - (isProgram ? 0 : 1),
             lineNumber - 1,
             context.getLogger(Parser.class)); // source starts at line 0, so even though lineNumber is the correct declaration line, back off one to make it exclusive
 
-        if (isAnonymous) {
+        if (getFunctionFlag(FunctionNode.IS_ANONYMOUS)) {
             parser.setFunctionName(functionName);
         }
+        parser.setReparsedFunction(this);
 
-        final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition, Token.descLength(token), true);
-        // Parser generates a program AST even if we're recompiling a single function, so when we are only recompiling a
-        // single function, extract it from the program.
-        return (isProgram ? program : extractFunctionFromScript(program)).setName(null, functionName);
+        final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition,
+                Token.descLength(token), true);
+        // Parser generates a program AST even if we're recompiling a single function, so when we are only
+        // recompiling a single function, extract it from the program.
+        return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName);
+    }
+
+    private boolean getFunctionFlag(final int flag) {
+        return (functionFlags & flag) != 0;
+    }
+
+    private boolean isProgram() {
+        return getFunctionFlag(FunctionNode.IS_PROGRAM);
     }
 
     TypeMap typeMap(final MethodType fnCallSiteType) {
@@ -394,6 +419,7 @@
                 context.getEnv(),
                 installer,
                 functionNode.getSource(),  // source
+                context.getErrorManager(),
                 isStrict() | functionNode.isStrict(), // is strict
                 true,       // is on demand
                 this,       // compiledFunction, i.e. this RecompilableScriptFunctionData
@@ -545,7 +571,7 @@
         assert fns.size() == 1 : "got back more than one method in recompilation";
         final FunctionNode f = fns.iterator().next();
         assert f.getId() == functionNodeId;
-        if (!isDeclared && f.isDeclared()) {
+        if (!getFunctionFlag(FunctionNode.IS_DECLARED) && f.isDeclared()) {
             return f.clearFlag(null, FunctionNode.IS_DECLARED);
         }
         return f;
@@ -668,7 +694,15 @@
 
     @Override
     public boolean needsCallee() {
-        return needsCallee;
+        return getFunctionFlag(FunctionNode.NEEDS_CALLEE);
+    }
+
+    /**
+     * Returns the {@link FunctionNode} flags associated with this function data.
+     * @return the {@link FunctionNode} flags associated with this function data.
+     */
+    public int getFunctionFlags() {
+        return functionFlags;
     }
 
     @Override
@@ -720,21 +754,6 @@
     }
 
     /**
-     * Get the uppermost parent, the program, for this data
-     * @return program
-     */
-    public RecompilableScriptFunctionData getProgram() {
-        RecompilableScriptFunctionData program = this;
-        while (true) {
-            final RecompilableScriptFunctionData p = program.getParent();
-            if (p == null) {
-                return program;
-            }
-            program = p;
-        }
-    }
-
-    /**
      * Check whether a certain name is a global symbol, i.e. only exists as defined
      * in outermost scope and not shadowed by being parameter or assignment in inner
      * scopes
--- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Tue Sep 16 13:59:37 2014 -0700
@@ -94,6 +94,9 @@
     /** Use single Global instance per jsr223 engine instance. */
     public final boolean _global_per_engine;
 
+    /** Enable experimental ECMAScript 6 features. */
+    public final boolean _es6;
+
     /** Argument passed to compile only if optimistic compilation should take place */
     public static final String COMPILE_ONLY_OPTIMISTIC_ARG = "optimistic";
 
@@ -258,6 +261,15 @@
         _version              = options.getBoolean("version");
         _verify_code          = options.getBoolean("verify.code");
 
+        final String language = options.getString("language");
+        if (language == null || language.equals("es5")) {
+            _es6 = false;
+        } else if (language.equals("es6")) {
+            _es6 = true;
+        } else {
+            throw new RuntimeException("Unsupported language: " + language);
+        }
+
         String dir = null;
         String func = null;
         final String pc = options.getString("print.code");
--- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Tue Sep 16 13:59:37 2014 -0700
@@ -36,6 +36,7 @@
 import java.lang.invoke.MethodType;
 import java.lang.invoke.SwitchPoint;
 import java.util.Collections;
+
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
@@ -44,6 +45,9 @@
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.objects.NativeFunction;
+import jdk.nashorn.internal.runtime.ScriptFunctionData;
+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.NashornCallSiteDescriptor;
 
@@ -621,6 +625,23 @@
             appliedType = appliedType.changeParameterType(1, Object.class);
         }
 
+        /*
+         * dropArgs is a synthetic method handle that contains any args that we need to
+         * get rid of that come after the arguments array in the apply case. We adapt
+         * the callsite to ask for 3 args only and then dropArguments on the method handle
+         * to make it fit the extraneous args.
+         */
+        MethodType dropArgs = MH.type(void.class);
+        if (isApply && !isFailedApplyToCall) {
+            final int pc = appliedType.parameterCount();
+            for (int i = 3; i < pc; i++) {
+                dropArgs = dropArgs.appendParameterTypes(appliedType.parameterType(i));
+            }
+            if (pc > 3) {
+                appliedType = appliedType.dropParameterTypes(3, pc);
+            }
+        }
+
         if (isApply || isFailedApplyToCall) {
             if (passesArgs) {
                 // R(this, args) => R(this, Object[])
@@ -702,6 +723,15 @@
         }
         inv = MH.dropArguments(inv, 0, applyFnType);
 
+        /*
+         * Dropargs can only be non-()V in the case of isApply && !isFailedApplyToCall, which
+         * is when we need to add arguments to the callsite to catch and ignore the synthetic
+         * extra args that someone has added to the command line.
+         */
+        for (int i = 0; i < dropArgs.parameterCount(); i++) {
+            inv = MH.dropArguments(inv, 4 + i, dropArgs.parameterType(i));
+        }
+
         MethodHandle guard = appliedInvocation.getGuard();
         // If the guard checks the value of "this" but we aren't passing thisArg, insert the default one
         if (!passesThis && guard.type().parameterCount() > 1) {
--- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Tue Sep 16 13:59:37 2014 -0700
@@ -90,8 +90,6 @@
     public static final int USES_THIS      = 1 << 4;
     /** Is this a variable arity function? */
     public static final int IS_VARIABLE_ARITY = 1 << 5;
-    /** Is this declared in a dynamic context */
-    public static final int IN_DYNAMIC_CONTEXT = 1 << 6;
 
     /** Flag for strict or built-in functions */
     public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Sep 16 13:59:37 2014 -0700
@@ -158,6 +158,7 @@
 
     static final MethodHandle MEGAMORPHIC_GET    = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class);
     static final MethodHandle GLOBALFILTER       = findOwnMH_S("globalFilter", Object.class, Object.class);
+    static final MethodHandle DECLARE_AND_SET    = findOwnMH_V("declareAndSet", void.class, String.class, Object.class);
 
     private static final MethodHandle TRUNCATINGFILTER   = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class);
     private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class);
@@ -1049,7 +1050,7 @@
     }
 
     private static int getIntValue(final FindProperty find, final int programPoint) {
-        final MethodHandle getter = find.getGetter(int.class, programPoint);
+        final MethodHandle getter = find.getGetter(int.class, programPoint, null);
         if (getter != null) {
             try {
                 return (int)getter.invokeExact((Object)find.getGetterReceiver());
@@ -1064,7 +1065,7 @@
     }
 
     private static long getLongValue(final FindProperty find, final int programPoint) {
-        final MethodHandle getter = find.getGetter(long.class, programPoint);
+        final MethodHandle getter = find.getGetter(long.class, programPoint, null);
         if (getter != null) {
             try {
                 return (long)getter.invokeExact((Object)find.getGetterReceiver());
@@ -1079,7 +1080,7 @@
     }
 
     private static double getDoubleValue(final FindProperty find, final int programPoint) {
-        final MethodHandle getter = find.getGetter(double.class, programPoint);
+        final MethodHandle getter = find.getGetter(double.class, programPoint, null);
         if (getter != null) {
             try {
                 return (double)getter.invokeExact((Object)find.getGetterReceiver());
@@ -1970,7 +1971,7 @@
             }
         }
 
-        final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc, request, operator);
+        final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc);
         if (cinv != null) {
             return cinv;
         }
@@ -1982,7 +1983,7 @@
                 NashornCallSiteDescriptor.getProgramPoint(desc) :
                 UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
-        mh = find.getGetter(returnType, programPoint);
+        mh = find.getGetter(returnType, programPoint, request);
         // Get the appropriate guard for this callsite and property.
         final MethodHandle guard = NashornGuards.getGuard(this, property, desc, explicitInstanceOfCheck);
         final ScriptObject owner = find.getOwner();
@@ -1994,8 +1995,9 @@
             mh = Lookup.emptyGetter(returnType);
             protoSwitchPoint = getProtoSwitchPoint(name, owner);
         } else if (!find.isSelf()) {
-            assert mh.type().returnType().equals(returnType) : "returntype mismatch for getter " + mh.type().returnType() + " != " + returnType;
-            if (!property.hasGetterFunction(owner)) {
+            assert mh.type().returnType().equals(returnType) :
+                    "return type mismatch for getter " + mh.type().returnType() + " != " + returnType;
+            if (!(property instanceof UserAccessorProperty)) {
                 // Add a filter that replaces the self object with the prototype owning the property.
                 mh = addProtoFilter(mh, find.getProtoChainLength());
             }
@@ -2027,6 +2029,22 @@
         return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
     }
 
+    // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST
+    @SuppressWarnings("unused")
+    private void declareAndSet(final String key, final Object value) {
+        final PropertyMap map = getMap();
+        final FindProperty find = findProperty(key, false);
+        assert find != null;
+
+        final Property property = find.getProperty();
+        assert property != null;
+        assert property.needsDeclaration();
+
+        final PropertyMap newMap = map.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION));
+        setMap(newMap);
+        set(key, value, true);
+    }
+
     /**
      * Find the appropriate GETINDEX method for an invoke dynamic call.
      *
@@ -2140,7 +2158,7 @@
         }
 
         if (find != null) {
-            if (!find.getProperty().isWritable()) {
+            if (!find.getProperty().isWritable() && !NashornCallSiteDescriptor.isDeclaration(desc)) {
                 // Existing, non-writable property
                 return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
             }
@@ -2150,7 +2168,7 @@
             }
         }
 
-        final GuardedInvocation inv = new SetMethodCreator(this, find, desc, explicitInstanceOfCheck).createGuardedInvocation();
+        final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation();
 
         final GuardedInvocation cinv = Global.getConstants().findSetMethod(find, this, inv, desc, request);
         if (cinv != null) {
@@ -2303,13 +2321,13 @@
                         find.isSelf()?
                             getKnownFunctionPropertyGuardSelf(
                                 getMap(),
-                                find.getGetter(Object.class, INVALID_PROGRAM_POINT),
+                                find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
                                 func)
                             :
                             //TODO this always does a scriptobject check
                             getKnownFunctionPropertyGuardProto(
                                 getMap(),
-                                find.getGetter(Object.class, INVALID_PROGRAM_POINT),
+                                find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
                                 find.getProtoChainLength(),
                                 func),
                         getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Tue Sep 16 13:59:37 2014 -0700
@@ -108,6 +108,11 @@
     public static final Call APPLY = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "apply", Object.class, ScriptFunction.class, Object.class, Object[].class);
 
     /**
+     * Throws a reference error for an undefined variable.
+     */
+    public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class);
+
+    /**
      * Converts a switch tag value to a simple integer. deflt value if it can't.
      *
      * @param tag   Switch statement tag value.
@@ -382,6 +387,15 @@
     }
 
     /**
+     * Throws a reference error for an undefined variable.
+     *
+     * @param name the variable name
+     */
+    public static void throwReferenceError(final String name) {
+        throw referenceError("not.defined", name);
+    }
+
+    /**
      * Call a script function as a constructor with given args.
      *
      * @param target ScriptFunction object.
--- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Tue Sep 16 13:59:37 2014 -0700
@@ -33,6 +33,7 @@
 import java.lang.invoke.SwitchPoint;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 import jdk.nashorn.internal.runtime.linker.NashornGuards;
 
@@ -48,7 +49,7 @@
     private final FindProperty       find;
     private final CallSiteDescriptor desc;
     private final Class<?>           type;
-    private final boolean            explicitInstanceOfCheck;
+    private final LinkRequest        request;
 
     /**
      * Creates a new property setter method creator.
@@ -56,14 +57,15 @@
      * @param find a result of a {@link ScriptObject#findProperty(String, boolean)} on the object for the property we
      * want to create a setter for. Can be null if the property does not yet exist on the object.
      * @param desc the descriptor of the call site that triggered the property setter lookup
+     * @param request the link request
      */
-    SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck) {
-        this.sobj = sobj;
-        this.map  = sobj.getMap();
-        this.find = find;
-        this.desc = desc;
-        this.type = desc.getMethodType().parameterType(1);
-        this.explicitInstanceOfCheck = explicitInstanceOfCheck;
+    SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc, final LinkRequest request) {
+        this.sobj    = sobj;
+        this.map     = sobj.getMap();
+        this.find    = find;
+        this.desc    = desc;
+        this.type    = desc.getMethodType().parameterType(1);
+        this.request = request;
 
     }
 
@@ -111,6 +113,7 @@
             // getGuard() and getException() either both return null, or neither does. The reason for that is that now
             // getGuard returns a map guard that casts its argument to ScriptObject, and if that fails, we need to
             // relink on ClassCastException.
+            final boolean explicitInstanceOfCheck = NashornGuards.explicitInstanceOfCheck(desc, request);
             return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc, explicitInstanceOfCheck),
                     (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
         }
@@ -140,13 +143,36 @@
 
     private SetMethod createExistingPropertySetter() {
         final Property property = find.getProperty();
-        final MethodHandle methodHandle = find.getSetter(type, NashornCallSiteDescriptor.isStrict(desc));
+        final boolean isStrict  = NashornCallSiteDescriptor.isStrict(desc);
+        final MethodHandle methodHandle;
+
+        if (NashornCallSiteDescriptor.isDeclaration(desc)) {
+            assert property.needsDeclaration();
+            // This is a LET or CONST being declared. The property is already there but flagged as needing declaration.
+            // We create a new PropertyMap with the flag removed. The map is installed with a fast compare-and-set
+            // method if the pre-callsite map is stable (which should be the case for function scopes except for
+            // non-strict functions containing eval() with var). Otherwise we have to use a slow setter that creates
+            // a new PropertyMap on the fly.
+            final PropertyMap oldMap = getMap();
+            final Property newProperty = property.removeFlags(Property.NEEDS_DECLARATION);
+            final PropertyMap newMap = oldMap.replaceProperty(property, newProperty);
+            final MethodHandle fastSetter = find.replaceProperty(newProperty).getSetter(type, isStrict, request);
+            final MethodHandle slowSetter = MH.insertArguments(ScriptObject.DECLARE_AND_SET, 1, getName()).asType(fastSetter.type());
+
+            // cas map used as guard, if true that means we can do the set fast
+            MethodHandle casMap = MH.insertArguments(ScriptObject.CAS_MAP, 1, oldMap, newMap);
+            casMap = MH.dropArguments(casMap, 1, type);
+            casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class));
+            methodHandle = MH.guardWithTest(casMap, fastSetter, slowSetter);
+        } else {
+            methodHandle = find.getSetter(type, isStrict, request);
+        }
 
         assert methodHandle != null;
         assert property     != null;
 
         final MethodHandle boundHandle;
-        if (!property.hasSetterFunction(find.getOwner()) && find.isInherited()) {
+        if (!(property instanceof UserAccessorProperty) && find.isInherited()) {
             boundHandle = ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength());
         } else {
             boundHandle = methodHandle;
--- a/src/jdk/nashorn/internal/runtime/Timing.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/Timing.java	Tue Sep 16 13:59:37 2014 -0700
@@ -33,6 +33,8 @@
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
+
+import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
@@ -189,7 +191,7 @@
             maxKeyLength++;
 
             final StringBuilder sb = new StringBuilder();
-            sb.append("Accumulated complation phase Timings:\n\n");
+            sb.append("Accumulated compilation phase timings:\n\n");
             for (final Map.Entry<String, Long> entry : timings.entrySet()) {
                 int len;
 
@@ -224,6 +226,9 @@
                 append((int)(knownTime * 100.0 / total)).
                 append("%])");
 
+            sb.append("\n\nEmitted compile units: ").
+                append(CompileUnit.getEmittedUnitCount());
+
             return sb.toString();
         }
 
--- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Tue Sep 16 13:59:37 2014 -0700
@@ -34,8 +34,8 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 import java.util.concurrent.Callable;
-import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
@@ -48,7 +48,7 @@
 
     private static final long serialVersionUID = -5928687246526840321L;
 
-    static class Accessors {
+    static final class Accessors {
         Object getter;
         Object setter;
 
@@ -67,20 +67,20 @@
         }
     }
 
+    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
     /** Getter method handle */
-    private final static CompilerConstants.Call USER_ACCESSOR_GETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
-            "userAccessorGetter", Object.class, Accessors.class, Object.class);
+    private final static MethodHandle INVOKE_GETTER_ACCESSOR = findOwnMH_S("invokeGetterAccessor", Object.class, Accessors.class, Object.class);
 
     /** Setter method handle */
-    private final static CompilerConstants.Call USER_ACCESSOR_SETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
-            "userAccessorSetter", void.class, Accessors.class, String.class, Object.class, Object.class);
+    private final static MethodHandle INVOKE_SETTER_ACCESSOR = findOwnMH_S("invokeSetterAccessor", void.class, Accessors.class, String.class, Object.class, Object.class);
 
     /** Dynamic invoker for getter */
-    private static final Object INVOKE_UA_GETTER = new Object();
+    private static final Object GETTER_INVOKER_KEY = new Object();
 
     private static MethodHandle getINVOKE_UA_GETTER() {
 
-        return Context.getGlobal().getDynamicInvoker(INVOKE_UA_GETTER,
+        return Context.getGlobal().getDynamicInvoker(GETTER_INVOKER_KEY,
                 new Callable<MethodHandle>() {
                     @Override
                     public MethodHandle call() {
@@ -91,10 +91,10 @@
     }
 
     /** Dynamic invoker for setter */
-    private static Object INVOKE_UA_SETTER = new Object();
+    private static Object SETTER_INVOKER_KEY = new Object();
 
     private static MethodHandle getINVOKE_UA_SETTER() {
-        return Context.getGlobal().getDynamicInvoker(INVOKE_UA_SETTER,
+        return Context.getGlobal().getDynamicInvoker(SETTER_INVOKER_KEY,
                 new Callable<MethodHandle>() {
                     @Override
                     public MethodHandle call() {
@@ -190,7 +190,7 @@
 
     @Override
     public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
-        return userAccessorGetter(getAccessors((owner != null) ? owner : self), self);
+        return invokeGetterAccessor(getAccessors((owner != null) ? owner : self), self);
     }
 
     @Override
@@ -210,13 +210,13 @@
 
     @Override
     public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
-        userAccessorSetter(getAccessors((owner != null) ? owner : self), strict ? getKey() : null, self, value);
+        invokeSetterAccessor(getAccessors((owner != null) ? owner : self), strict ? getKey() : null, self, value);
     }
 
     @Override
     public MethodHandle getGetter(final Class<?> type) {
         //this returns a getter on the format (Accessors, Object receiver)
-        return Lookup.filterReturnType(USER_ACCESSOR_GETTER.methodHandle(), type);
+        return Lookup.filterReturnType(INVOKE_GETTER_ACCESSOR, type);
     }
 
     @Override
@@ -260,7 +260,7 @@
 
     @Override
     public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
-        return USER_ACCESSOR_SETTER.methodHandle();
+        return INVOKE_SETTER_ACCESSOR;
     }
 
     @Override
@@ -269,11 +269,21 @@
         return (value instanceof ScriptFunction) ? (ScriptFunction)value : null;
     }
 
+    /**
+     * Get the getter for the {@code Accessors} object.
+     * This is the the super {@code Object} type getter with {@code Accessors} return type.
+     *
+     * @return The getter handle for the Accessors
+     */
+    MethodHandle getAccessorsGetter() {
+        return super.getGetter(Object.class).asType(MethodType.methodType(Accessors.class, Object.class));
+    }
+
     // User defined getter and setter are always called by "dyn:call". Note that the user
     // getter/setter may be inherited. If so, proto is bound during lookup. In either
     // inherited or self case, slot is also bound during lookup. Actual ScriptFunction
     // to be called is retrieved everytime and applied.
-    static Object userAccessorGetter(final Accessors gs, final Object self) {
+    private static Object invokeGetterAccessor(final Accessors gs, final Object self) {
         final Object func = gs.getter;
         if (func instanceof ScriptFunction) {
             try {
@@ -288,7 +298,7 @@
         return UNDEFINED;
     }
 
-    static void userAccessorSetter(final Accessors gs, final String name, final Object self, final Object value) {
+    private static void invokeSetterAccessor(final Accessors gs, final String name, final Object self, final Object value) {
         final Object func = gs.setter;
         if (func instanceof ScriptFunction) {
             try {
@@ -303,4 +313,8 @@
         }
     }
 
+    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(LOOKUP, UserAccessorProperty.class, name, MH.type(rtype, types));
+    }
+
 }
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Tue Sep 16 13:59:37 2014 -0700
@@ -628,18 +628,20 @@
         Class<?> widest = Integer.class;
 
         for (final Object item : items) {
-            final Class<?> itemClass = item == null ? null : item.getClass();
+            if (item == null) {
+                return Object.class;
+            }
+            final Class<?> itemClass = item.getClass();
             if (itemClass == Long.class) {
                 if (widest == Integer.class) {
                     widest = Long.class;
                 }
-            } else if (itemClass == Double.class) {
+            } else if (itemClass == Double.class || itemClass == Float.class) {
                 if (widest == Integer.class || widest == Long.class) {
                     widest = Double.class;
                 }
-            } else if (!(item instanceof Number)) {
-                widest = Object.class;
-                break;
+            } else if (itemClass != Integer.class && itemClass != Short.class && itemClass != Byte.class) {
+                return Object.class;
             }
         }
 
--- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Tue Sep 16 13:59:37 2014 -0700
@@ -54,23 +54,25 @@
     public static final int CALLSITE_OPTIMISTIC    = 1 << 3;
     /** Is this really an apply that we try to call as a call? */
     public static final int CALLSITE_APPLY_TO_CALL = 1 << 4;
+    /** Does this a callsite for a variable declaration? */
+    public static final int CALLSITE_DECLARE       = 1 << 5;
 
     /** Flags that the call site is profiled; Contexts that have {@code "profile.callsites"} boolean property set emit
      * code where call sites have this flag set. */
-    public static final int CALLSITE_PROFILE        = 1 << 5;
+    public static final int CALLSITE_PROFILE         = 1 << 6;
     /** Flags that the call site is traced; Contexts that have {@code "trace.callsites"} property set emit code where
      * call sites have this flag set. */
-    public static final int CALLSITE_TRACE          = 1 << 6;
+    public static final int CALLSITE_TRACE           = 1 << 7;
     /** Flags that the call site linkage miss (and thus, relinking) is traced; Contexts that have the keyword
      * {@code "miss"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */
-    public static final int CALLSITE_TRACE_MISSES   = 1 << 7;
+    public static final int CALLSITE_TRACE_MISSES    = 1 << 8;
     /** Flags that entry/exit to/from the method linked at call site are traced; Contexts that have the keyword
      * {@code "enterexit"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */
-    public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 8;
+    public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 9;
     /** Flags that values passed as arguments to and returned from the method linked at call site are traced; Contexts
      * that have the keyword {@code "values"} in their {@code "trace.callsites"} property emit code where call sites
      * have this flag set. */
-    public static final int CALLSITE_TRACE_VALUES   = 1 << 9;
+    public static final int CALLSITE_TRACE_VALUES    = 1 << 10;
 
     //we could have more tracing flags here, for example CALLSITE_TRACE_SCOPE, but bits are a bit precious
     //right now given the program points
@@ -82,10 +84,10 @@
      * TODO: rethink if we need the various profile/trace flags or the linker can use the Context instead to query its
      * trace/profile settings.
      */
-    public static final int CALLSITE_PROGRAM_POINT_SHIFT = 10;
+    public static final int CALLSITE_PROGRAM_POINT_SHIFT = 11;
 
     /**
-     * Maximum program point value. 22 bits should be enough for anyone
+     * Maximum program point value. 21 bits should be enough for anyone
      */
     public static final int MAX_PROGRAM_POINT_VALUE = (1 << 32 - CALLSITE_PROGRAM_POINT_SHIFT) - 1;
 
@@ -123,6 +125,9 @@
                 assert (flags & CALLSITE_FAST_SCOPE) == 0 : "can't be fastscope without scope";
                 sb.append("scope ");
             }
+            if ((flags & CALLSITE_DECLARE) != 0) {
+                sb.append("declare ");
+            }
         }
         if ((flags & CALLSITE_APPLY_TO_CALL) != 0) {
             sb.append("apply2call ");
@@ -329,6 +334,15 @@
     }
 
     /**
+     * Does this callsite contain a declaration for its target?
+     * @param desc descriptor
+     * @return true if contains declaration
+     */
+    public static boolean isDeclaration(final CallSiteDescriptor desc) {
+        return isFlag(desc, CALLSITE_DECLARE);
+    }
+
+    /**
      * Get a program point from a descriptor (must be optimistic)
      * @param desc descriptor
      * @return program point
--- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Tue Sep 16 13:59:37 2014 -0700
@@ -32,11 +32,10 @@
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
-import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
 import jdk.internal.dynalink.support.Guards;
-import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.runtime.FindProperty;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.UserAccessorProperty;
 
 /**
  * Implements lookup of methods to link for dynamic operations on JavaScript primitive values (booleans, strings, and
@@ -86,15 +85,6 @@
                                                     final ScriptObject wrappedReceiver, final MethodHandle wrapFilter,
                                                     final MethodHandle protoFilter) {
         final CallSiteDescriptor desc = request.getCallSiteDescriptor();
-        final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
-        if ("setProp".equals(operator) || "setElem".equals(operator)) {
-            final MethodType type = desc.getMethodType();
-            MethodHandle method = MH.asType(Lookup.EMPTY_SETTER, MH.type(void.class, Object.class, type.parameterType(1)));
-            if (type.parameterCount() == 3) {
-                method = MH.dropArguments(method, 2, type.parameterType(2));
-            }
-            return new GuardedInvocation(method, guard);
-        }
 
         if(desc.getNameTokenCount() > 2) {
             final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
@@ -102,7 +92,7 @@
             if(find == null) {
                 // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it.
                 return null;
-            } else if (find.isInherited() && !find.getProperty().hasGetterFunction(find.getOwner())) {
+            } else if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
                 // If property is found in the prototype object bind the method handle directly to
                 // the proto filter instead of going through wrapper instantiation below.
                 final ScriptObject proto = wrappedReceiver.getProto();
--- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Tue Sep 16 13:59:37 2014 -0700
@@ -58,6 +58,7 @@
 parser.error.regex.repeated.flag=Repeated RegExp flag: {0}
 parser.error.regex.syntax={0}
 parser.error.trailing.comma.in.json=Trailing comma is not allowed in JSON
+parser.error.missing.const.assignment=Missing assignment to constant "{0}"
 
 # strict mode error messages
 parser.error.strict.no.with="with" statement cannot be used in strict mode
@@ -162,6 +163,8 @@
 
 syntax.error.invalid.json=Invalid JSON: {0}
 syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode
+syntax.error.redeclare.variable=Variable "{0}" has already been declared
+syntax.error.assign.constant=Assignment to constant "{0}"
 
 io.error.cant.write=cannot write "{0}"
 config.error.no.dest=no destination directory supplied
--- a/src/jdk/nashorn/internal/runtime/resources/Options.properties	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties	Tue Sep 16 13:59:37 2014 -0700
@@ -329,6 +329,14 @@
     desc="Enable scripting features."   \
 }
 
+nashorn.option.language = {                      \
+    name="--language",                           \
+    type=String,                                 \
+    params=[es5|es6],                            \
+    default=es5,                                 \
+    desc="Specify ECMAScript language version."  \
+}
+
 nashorn.option.stdout = {                                                \
     name="--stdout",                                                     \
     is_undocumented=true,                                                \
--- a/src/jdk/nashorn/tools/Shell.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/src/jdk/nashorn/tools/Shell.java	Tue Sep 16 13:59:37 2014 -0700
@@ -246,12 +246,21 @@
 
             // For each file on the command line.
             for (final String fileName : files) {
-                final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors, env._strict, FunctionNode.FIRST_FUNCTION_ID, 0, context.getLogger(Parser.class)).parse();
+                final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors, env._strict, 0, context.getLogger(Parser.class)).parse();
 
                 if (errors.getNumberOfErrors() != 0) {
                     return COMPILATION_ERROR;
                 }
 
+                new Compiler(
+                       context,
+                       env,
+                       null, //null - pass no code installer - this is compile only
+                       functionNode.getSource(),
+                       context.getErrorManager(),
+                       env._strict | functionNode.isStrict()).
+                       compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL);
+
                 if (env._print_ast) {
                     context.getErr().println(new ASTWriter(functionNode));
                 }
@@ -260,14 +269,9 @@
                     context.getErr().println(new PrintVisitor(functionNode));
                 }
 
-                //null - pass no code installer - this is compile only
-                new Compiler(
-                       context,
-                       env,
-                       null,
-                       functionNode.getSource(),
-                       env._strict | functionNode.isStrict()).
-                       compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL);
+                if (errors.getNumberOfErrors() != 0) {
+                    return COMPILATION_ERROR;
+                }
             }
         } finally {
             env.getOut().flush();
--- a/test/script/basic/JDK-8030182_2.js	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/script/basic/JDK-8030182_2.js	Tue Sep 16 13:59:37 2014 -0700
@@ -41,6 +41,6 @@
 try {
     eval(str);
 } catch (e) {
-    print(e.stack.replace(/\\/g, '/').replace(/<eval>@[0-9]+/, '<eval>@<id>'));
+    print(e.stack.replace(/\\/g, '/'));
 }
 
--- a/test/script/basic/JDK-8030182_2.js.EXPECTED	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/script/basic/JDK-8030182_2.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -1,3 +1,3 @@
 ReferenceError: "g" is not defined
-	at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>@<id>:-1)
+	at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>:-1)
 	at <program> (test/script/basic/JDK-8030182_2.js:42)
--- a/test/script/basic/JDK-8048079_1.js	Thu Sep 11 15:34:13 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010, 2014, 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-8048079: Persistent code store is broken after optimistic types merge
- *
- * @test
- * @run
- * @option -pcc
- * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
- * @fork
- */
-
-load(__DIR__ + 'prototype.js');
-load(__DIR__ + 'yui.js');
--- a/test/script/basic/JDK-8048079_1.js.EXPECTED	Thu Sep 11 15:34:13 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-parsed and compiled ok prototype.js
-parsed and compiled ok yui-min.js
-parsed and compiled ok yui.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8048079_1a.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8048079: Persistent code store is broken after optimistic types merge
+ *
+ * @test
+ * @runif external.prototype
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'prototype.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8048079_1a.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,1 @@
+parsed and compiled ok prototype.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8048079_1b.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8048079: Persistent code store is broken after optimistic types merge
+ *
+ * @test
+ * @runif external.yui
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'yui.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8048079_1b.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
--- a/test/script/basic/JDK-8048079_2.js	Thu Sep 11 15:34:13 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010, 2014, 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-8048079: Persistent code store is broken after optimistic types merge
- *
- * @test
- * @run
- * @option -pcc
- * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
- * @fork
- */
-
-load(__DIR__ + 'prototype.js');
-load(__DIR__ + 'yui.js');
--- a/test/script/basic/JDK-8048079_2.js.EXPECTED	Thu Sep 11 15:34:13 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-parsed and compiled ok prototype.js
-parsed and compiled ok yui-min.js
-parsed and compiled ok yui.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8048079_2a.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8048079: Persistent code store is broken after optimistic types merge.
+ * Same script as JDK-8048079_1a.js to exercise code cache.
+ * @test
+ * @runif external.prototype
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'prototype.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8048079_2a.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,1 @@
+parsed and compiled ok prototype.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8048079_2b.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8048079: Persistent code store is broken after optimistic types merge
+ * Same script as JDK-8048079_1b.js to exercise code cache again.
+ * @test
+ * @runif external.yui
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'yui.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8048079_2b.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8056129.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8056129: AtomicInteger is treated as primitive number with optimistic compilation
+ *
+ * @test
+ * @run
+ */
+
+var AtomicInteger = java.util.concurrent.atomic.AtomicInteger;
+
+function getAtomic() { 
+   return new AtomicInteger() 
+} 
+var x = getAtomic() 
+print(x instanceof AtomicInteger)
+
+var a = []
+a.push(x)
+var y = a[0]
+print(y instanceof AtomicInteger)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8056129.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,2 @@
+true
+true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8057019-2.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+/**
+ * this apply with extra arguments
+ * (with apply to call enabled)
+ *
+ * @test
+ * @run
+ */
+
+load(__DIR__ + 'JDK-8057019-payload.js');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8057019-2.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,24 @@
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+TypeError: Function.prototype.apply expects an Array for second argument
+TypeError: Function.prototype.apply expects an Array for second argument
+TypeError: Function.prototype.apply expects an Array for second argument
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8057019-payload.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+/**
+ * this apply with extra arguments
+ *
+ * @subtest
+ */
+
+function func(x, y, z) {
+    print(x, y, z);
+}
+
+function g() {
+    func.apply(this, arguments);
+}
+function h() {
+    func.apply(this, arguments, 23);
+}
+function i() {
+    func.apply(this, arguments, 23, 4711);
+}
+function j() {
+    func.apply(this, arguments, 23, 4711, "apa", "dingo", "gorilla");
+}
+function k() {
+    func.apply(this, arguments, 23);
+}
+function l() {
+    func.apply(this, [23, "apa", "gorilla", "dingo"], 17);
+}
+function m() {
+    func.apply(this, [23, "apa", "gorilla", "dingo"]);
+}
+function n() {
+    func.apply(this, "significant");
+}
+
+g(1,2);
+g(1,2,3);
+g(1,2,3,4);
+
+h(1,2);
+h(1,2,3);
+h(1,2,3,4);
+
+i(1,2);
+i(1,2,3);
+i(1,2,3,4);
+
+j(1,2);
+j(1,2,3);
+j(1,2,3,4);
+
+k(1,2);
+k(1,2,3);
+k(1,2,3,4);
+
+l(1,2);
+l(1,2,3);
+l(1,2,3,4);
+
+m(1,2);
+m(1,2,3);
+m(1,2,3,4);
+
+try {
+    n(1,2);
+} catch (e) {
+    print(e);
+}
+try {
+    n(1,2,3);
+} catch (e) {
+    print(e);    
+}
+
+try {
+    n(1,2,3,4);
+} catch (e) {
+    print(e);   
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8057019.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+/**
+ * this apply with extra arguments
+ * (turning off apply to call)
+ *
+ * @fork
+ * @option -Dnashorn.apply2call=false
+ * @test
+ * @run
+ */
+
+load(__DIR__ + 'JDK-8057019-payload.js');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8057019.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,24 @@
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+TypeError: Function.prototype.apply expects an Array for second argument
+TypeError: Function.prototype.apply expects an Array for second argument
+TypeError: Function.prototype.apply expects an Array for second argument
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8058179.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 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-8058179: Global constants get in the way of self-modifying properties
+ *
+ * @test
+ * @run
+ */
+
+var global = this;
+
+Object.defineProperty(global, "value", {
+    get: function() {
+        print("getting value");
+        global["value"] = "value 2";
+        return "value 1";
+    },
+    set: function(value) {
+        print("setting value: " + value);
+        delete global["value"];
+        global["value"] = value;
+    },
+    configurable: true
+});
+
+print(value);
+print(value);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8058179.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,4 @@
+getting value
+setting value: value 2
+value 1
+value 2
--- a/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -15,8 +15,8 @@
 2.3
 3.4
 test 5 done
-a=object
-17
+a=number
+22
 undefined
 Now it's time for transforms
 19
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/block-function-decl.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+"use strict";
+
+{
+    // f is defined on block level
+    print(f);
+    f();
+    function f() {
+        print("in f");
+    }
+    print(f);
+    f();
+}
+
+try {
+    print(typeof f);
+    f();
+} catch (e) {
+    print(e);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/block-function-decl.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,10 @@
+function f() {
+        print("in f");
+    }
+in f
+function f() {
+        print("in f");
+    }
+in f
+undefined
+ReferenceError: "f" is not defined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-empty.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+try {
+    eval('"use strict";\n' +
+        'const x;\n');
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-empty.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,3 @@
+SyntaxError: test/script/basic/es6/const-empty.js#33:4<eval>:2:7 Missing assignment to constant "x"
+const x;
+       ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-reassign.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x = 1;\n');
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x++;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x--;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        '++x;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        '--x;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x += 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x *= 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x /= 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x %= 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x |= 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x &= 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x ^= 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x <<= 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x >>= 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'x >>>= 1;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
+
+try {
+    eval('"use strict";\n' +
+        'const x = 2;\n' +
+        'delete x;\n');
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e.name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-reassign.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,16 @@
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-redeclare-extra.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+
+function tryIt (code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+tryIt(<<CODE
+    "use strict";
+    const x = 2;
+    var x = {};
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    var x = 2;
+    const x = {};
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    function x () {}
+    const x = 5;
+CODE)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-redeclare-extra.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,9 @@
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:8 Variable "x" has already been declared
+    var x = {};
+        ^
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:8 Variable "x" has already been declared
+    var x = 2;
+        ^
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:13 Variable "x" has already been declared
+    function x () {}
+             ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-redeclare.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+try {
+    eval('"use strict";\n' +
+         'const x = 2;\n' +
+         'const x = 2;\n');
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-redeclare.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,3 @@
+SyntaxError: test/script/basic/es6/const-redeclare.js#33:4<eval>:2:6 Variable "x" has already been declared
+const x = 2;
+      ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-self.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+const a = 1, b = a;
+
+print(a, b);
+
+try {
+    eval('"use strict";\n' +
+         'const a = a;\n');
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-self.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,2 @@
+1 1
+ReferenceError: "a" is not defined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-tdz.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+{
+    print("test 1");
+
+    function f() {
+        try {
+            print(a);
+        } catch (a) {
+            print(a);
+        }
+    }
+
+    f();
+    const a = 1;
+    f();
+}
+
+{
+    print("test 2");
+
+    function f() {
+        try {
+            print(a);
+        } catch (a) {
+            print(a);
+        }
+    }
+
+    f();
+    const a = 2;
+    f();
+}
+
+{
+    print("test 3");
+    {
+        try {
+            print(a);
+        } catch (a) {
+            print(a);
+        }
+    }
+
+    const a = 3;
+
+    {
+        print(a);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const-tdz.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,9 @@
+test 1
+ReferenceError: "a" is not defined
+1
+test 2
+ReferenceError: "a" is not defined
+2
+test 3
+ReferenceError: "a" is not defined
+3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+"use strict";
+
+const a = 2;
+const c = 2;
+print(a, c);
+
+function f(x) {
+    const a = 5;
+    const c = 10;
+    print(a, c);
+    if (x) {
+        const a = 42;
+        const c = 43;
+        print(a, c);
+    }
+    print(a, c);
+
+    function inner() {
+        (function() {
+            print(a, c);
+        })();
+    }
+    inner();
+}
+
+f(true);
+f(false);
+
+(function() {
+    (function() {
+        print(a, c);
+    })();
+})();
+
+function outer() {
+    print(a, c);
+}
+outer();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/const.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,10 @@
+2 2
+5 10
+42 43
+5 10
+5 10
+5 10
+5 10
+5 10
+2 2
+2 2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/for-let.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+for (let i = 0; i < 10; i++) {
+    print(i);
+}
+
+try {
+    print(i);
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/for-let.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,11 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+ReferenceError: "i" is not defined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-eval.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+function f() {
+    var a;
+    let b;
+    const c = 0;
+
+    print(a, b, c);
+
+    try {
+        eval("x = 1; print('x: ' + x);");
+        print("assignment to x succeeded");
+    } catch (e) {
+        print(e);
+    }
+    try {
+        eval("'use strict'; let z = 1; print('z: ' + z);");
+        print("assignment to z succeeded");
+        eval("print('z: ' + z);");
+    } catch (e) {
+        print(e);
+    }
+
+    try {
+        eval("a = 1; print(a);");
+        print("assignment to a succeeded");
+    } catch (e) {
+        print(e);
+    }
+    print("a: " + a);
+
+    try {
+        eval("b = 1; print('b: ' + b);");
+        print("assignment to b succeeded");
+    } catch (e) {
+        print(e);
+    }
+    print("b: " + b);
+
+    try {
+        eval("c = 1; print('c: ' + c);");
+        print("assignment to c succeeded");
+    } catch (e) {
+        print(e);
+    }
+    print("c: " + c);
+
+    eval("a = 2; let b = 3;");
+
+    try {
+        print(a, b, c);
+    } catch (e) {
+        print(e);
+    }
+
+    let x;
+
+    try {
+        print(a, b, c, x);
+    } catch (e) {
+        print(e);
+    }
+
+}
+
+f();
+
+print(typeof a, typeof b, typeof c, typeof x, typeof z);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-eval.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,16 @@
+undefined undefined 0
+ReferenceError: "x" is not defined
+z: 1
+assignment to z succeeded
+ReferenceError: "z" is not defined
+1
+assignment to a succeeded
+a: 1
+b: 1
+assignment to b succeeded
+b: 1
+TypeError: "c" is not a writable property of [object Object]
+c: 0
+2 1 0
+2 1 0 undefined
+undefined undefined undefined undefined undefined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-load-lib.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+/**
+ * @subtest
+ */
+
+"use strict";
+
+// var should be visible in other script, let and const not
+var a = 1;
+let b = 2;
+const c = 3;
+
+// top level function should be visible
+function top() {
+    print("top level function");
+}
+
+// block level function not visible outside script
+{
+    function block() {
+        print("block function");
+    }
+
+    top();
+    block();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-load.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+load(__DIR__ + "let-load-lib.js");
+
+{
+    let a = 20;
+    const c = 30;
+    print("print local defs: " + a, c);
+}
+
+print("imported var: " + a);
+try {
+    print("imported let: " + b);
+} catch (e) {
+    print(e);
+}
+
+try {
+    print("imported const: " + c);
+} catch (e) {
+    print(e);
+}
+
+top();
+
+try {
+    block();
+} catch (e) {
+    print(e);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-load.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,8 @@
+top level function
+block function
+print local defs: 20 30
+imported var: 1
+ReferenceError: "b" is not defined
+ReferenceError: "c" is not defined
+top level function
+ReferenceError: "block" is not defined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-nodeclare.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+try {
+    if (true) {
+        let x = 2;
+        print(x);
+    }
+    print(x);
+} catch (e) {
+    print(e);
+}
+
+
+try {
+    if (true) {
+        const x = 2;
+        print(x);
+    }
+    print(x);
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-nodeclare.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,4 @@
+2
+ReferenceError: "x" is not defined
+2
+ReferenceError: "x" is not defined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-redeclare-extra.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt (code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+tryIt(<<CODE
+    "use strict";
+    let x = 2;
+    const x = function (a,b,c) {};
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    let x = {};
+    var x = 2;
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    var x = 2;
+    let x = undefined;
+CODE)
+
+tryIt(<<CODE
+    "use strict";
+    const x = function (){};
+    let x = {};
+CODE)
+
+
+tryIt(<<CODE
+    "use strict";
+    let a = 2;
+    function a () {};
+CODE)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-redeclare-extra.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,15 @@
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared
+    let x = 2;
+        ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
+    var x = 2;
+        ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared
+    var x = 2;
+        ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:10 Variable "x" has already been declared
+    const x = function (){};
+          ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:13 Variable "a" has already been declared
+    function a () {};
+             ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-redeclare.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+try {
+    eval('"use strict";\n' +
+         'let x = 2;\n' +
+         'let x = 2;\n');
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-redeclare.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,3 @@
+SyntaxError: test/script/basic/es6/let-redeclare.js#33:4<eval>:2:4 Variable "x" has already been declared
+let x = 2;
+    ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-self.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+let a, b = a;
+
+print(a, b);
+
+try {
+    eval('"use strict";\n' +
+         'let a = a;\n');
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-self.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,2 @@
+undefined undefined
+ReferenceError: "a" is not defined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-tdz.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+{
+    print("test 1");
+
+    function f() {
+        try {
+            print(a);
+        } catch (a) {
+            print(a);
+        }
+    }
+
+    f();
+    let a = 1;
+    f();
+}
+
+{
+    print("test 2");
+
+    function f() {
+        try {
+            print(a);
+        } catch (a) {
+            print(a);
+        }
+    }
+
+    f();
+    let a = 2;
+    f();
+}
+
+{
+    print("test 3");
+
+    {
+        try {
+            print(a);
+        } catch (a) {
+            print(a);
+        }
+    }
+
+    let a = 3;
+
+    {
+        print(a);
+    }
+}
+
+{
+    print("test 4");
+    let a;
+
+    {
+        print(a);
+    }
+
+    a = 4;
+
+    {
+        print(a);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let-tdz.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,12 @@
+test 1
+ReferenceError: "a" is not defined
+1
+test 2
+ReferenceError: "a" is not defined
+2
+test 3
+ReferenceError: "a" is not defined
+3
+test 4
+undefined
+4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+let a = 2;
+let c = 2;
+print(a, c);
+
+function f(x) {
+    let a = 5;
+    const c = 10;
+    print(a, c);
+    if (x) {
+        let a = 42;
+        const c = 43;
+        print(a, c);
+    }
+    print(a, c);
+
+    function inner() {
+        (function() {
+            print(a, c);
+        })();
+    }
+    inner();
+}
+
+f(true);
+f(false);
+
+(function() {
+    (function() {
+        print(a, c);
+    })();
+})();
+
+function outer() {
+    print(a, c);
+}
+outer();
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,10 @@
+2 2
+5 10
+42 43
+5 10
+5 10
+5 10
+5 10
+5 10
+2 2
+2 2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let_const_closure.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014, 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt(code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+
+tryIt(<<CODE
+    function a () {
+        this.val = 41
+        let self = this
+        this.b = function () {
+            return self.val;
+        }
+    }
+    c = new a()
+    print(c.b.call(null))
+CODE)
+
+
+tryIt(<<CODE
+        function a () {
+            this.val = 42
+            let self = this
+            this.b = function () {
+                return this.val;
+            }.bind(self)
+        }
+        c = new a()
+        print(c.b.call(null))
+CODE)
+
+tryIt(<<CODE
+    function a () {
+        this.val = 43
+        const self = this
+        this.b = function () {
+            return self.val;
+        }
+    }
+    c = new a()
+    print(c.b.call(null))
+CODE)
+
+tryIt(<<CODE
+        function a () {
+            this.val = 44
+            const self = this
+            this.b = function () {
+                return this.val;
+            }.bind(self)
+        }
+        c = new a()
+        print(c.b.call(null))
+CODE)
+
+tryIt(<<CODE
+       let a = {name : 'test'}
+       let f = function () {
+            print(this.name)
+       }
+       let nf = f.bind(a)
+       nf()
+       if (true) {
+            let a = null
+            nf()
+       }
+       nf()
+CODE)
+
+
+tryIt(<<CODE
+       let arr = []
+       for (let i = 0; i < 3; i++) {
+           arr[i] = function(){return i;}
+       }
+       for (let i in arr) {
+            print(arr[i]())
+       }
+       arr = []
+       for (var i = 0; i < 3; i++) {
+            (function(i){
+                arr[i] = function(){return i;}
+            })(i)
+       }
+       for (let i in arr) {
+           print(arr[i]())
+       }
+CODE)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let_const_closure.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,13 @@
+41
+42
+43
+44
+test
+test
+test
+3
+3
+3
+0
+1
+2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let_const_reuse.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt (code) {
+     try {
+         eval(code)
+     } catch (e) {
+         print(e)
+     }
+}
+
+tryIt(<<CODE
+    let a = 23
+    if (true) {
+        a--
+        let a = 43;
+    }
+CODE)
+
+tryIt(<<CODE
+    const a = 23
+    if (true) {
+        a--
+        const a = 43;
+    }
+CODE)
+
+tryIt(<<CODE
+    let a = 23
+    if (true) {
+        a--
+        const a = 43;
+    }
+CODE)
+
+tryIt(<<CODE
+    const a = 23
+    if (true) {
+        a--
+        let a = 43;
+    }
+CODE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let_const_reuse.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,8 @@
+ReferenceError: "a" is not defined
+SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
+        a--
+        ^
+SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
+        a--
+        ^
+ReferenceError: "a" is not defined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let_different_types.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt (code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+tryIt(<<CODE
+    let a = function () {  var a = "Hello World!"; return a; }
+    print(typeof a)
+    {
+        let a = 34;
+        print(typeof a)
+        if (true) {
+            let c = 54.7
+            var d = c
+            print(typeof c)
+            print(typeof d)
+        }
+    }
+    print(typeof a)
+    print(typeof a())
+    print(typeof c)
+    print(typeof d)
+    print(d)
+CODE)
+
+tryIt(<<CODE
+    let a = {}
+    if (true) {
+        function a () {
+            print (typeof a)
+            return 'Hello World!'
+        }
+        print(typeof a)
+        print(a())
+    }
+    print(typeof a)
+CODE)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let_different_types.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,13 @@
+function
+number
+number
+number
+function
+string
+undefined
+number
+54.7
+function
+function
+Hello World!
+object
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let_loops.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+
+function tryIt (code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(e)
+    }
+}
+
+tryIt(<<CODE
+      let a = 2;
+      do {
+        a--;
+        let b = a;
+      } while (a > 0);
+      print(a)
+      print(b)
+CODE)
+
+tryIt(<<CODE
+       let a = 2
+       while(a > 0) {
+            a--
+            let b = a
+       }
+       print(a)
+       print(b)
+CODE)
+
+tryIt(<<CODE
+       let a = 2
+       while(a > 0) {
+            a--
+            const b = a
+       }
+       print(a)
+       print(b)
+CODE)
+
+tryIt(<<CODE
+       let a = 2;
+       do {
+         a--;
+         const b = a;
+       } while (a > 0);
+       print(a)
+       print(b)
+CODE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/es6/let_loops.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,8 @@
+0
+ReferenceError: "b" is not defined
+0
+ReferenceError: "b" is not defined
+0
+ReferenceError: "b" is not defined
+0
+ReferenceError: "b" is not defined
--- a/test/script/basic/optimistic_check_type.js	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/script/basic/optimistic_check_type.js	Tue Sep 16 13:59:37 2014 -0700
@@ -36,13 +36,18 @@
 
 // Testing conditional operator
 print(inspect("" ? b : x.a, "ternary operator"))
-print(inspect(x.b ? b : x.a, "ternary operator"))
-print(inspect(c ? b : a, "ternary operator"))
-print(inspect(!c ? b : a, "ternary operator"))
-print(inspect(d ? b : x.c, "ternary operator"))
+var b1 = b;
+print(inspect(x.b ? b1 : x.a, "ternary operator"))
+var b2 = b;
+print(inspect(c ? b2 : a, "ternary operator"))
+var b3 = b;
+print(inspect(!c ? b3 : a, "ternary operator"))
+var b4 = b;
+print(inspect(d ? b4 : x.c, "ternary operator"))
 print(inspect(x.c ? a : c, "ternary operator"))
 print(inspect(c ? d : a, "ternary operator"))
-print(inspect(c ? +a : b, "ternary operator"))
+var b5 = b;
+print(inspect(c ? +a : b5, "ternary operator"))
 
 // Testing format methods
 print(inspect(b.toFixed(2), "global double toFixed()"))
@@ -53,11 +58,14 @@
 print(inspect(trees[1], "member object"))
 trees[1] = undefined;
 print(inspect(trees[1], "member undefined"))
-print(inspect(1 in trees ? b : a, "conditional on array member"))
+var b6=b;
+print(inspect(1 in trees ? b6 : a, "conditional on array member"))
 delete trees[2]
-print(inspect(2 in trees ? b : a, "conditional on array member"))
+var b7=b;
+print(inspect(2 in trees ? b7 : a, "conditional on array member"))
 print(inspect(3 in trees ? trees[2]="bay" : a, "conditional on array member"))
-print(inspect("oak" in trees ? b : a, "conditional on array member"))
+var b8=b;
+print(inspect("oak" in trees ? b8 : a, "conditional on array member"))
 
 // Testing nested functions and return value
 function f1() {
--- a/test/script/basic/splitter.js	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/script/basic/splitter.js	Tue Sep 16 13:59:37 2014 -0700
@@ -30,7 +30,5 @@
  * @fork
  */
 
-load(__DIR__ + 'prototype.js');
-load(__DIR__ + 'yui.js');
 load(__DIR__ + 'NASHORN-689.js');
 load(__DIR__ + 'NASHORN-58.js');
--- a/test/script/basic/splitter.js.EXPECTED	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/script/basic/splitter.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -1,6 +1,3 @@
-parsed and compiled ok prototype.js
-parsed and compiled ok yui-min.js
-parsed and compiled ok yui.js
 a=10
 a=9
 a=8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/splitter_prototype.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+/**
+ * Test various scripts with low splitter threshold
+ *
+ * @test
+ * @option -Dnashorn.compiler.splitter.threshold=200
+ * @runif external.prototype
+ * @fork
+ */
+
+load(__DIR__ + 'prototype.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/splitter_prototype.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,1 @@
+parsed and compiled ok prototype.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/splitter_yui.js	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+/**
+ * Test various scripts with low splitter threshold
+ *
+ * @test
+ * @option -Dnashorn.compiler.splitter.threshold=200
+ * @runif external.yui
+ * @fork
+ */
+
+load(__DIR__ + 'yui.js');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/splitter_yui.js.EXPECTED	Tue Sep 16 13:59:37 2014 -0700
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
--- a/test/script/trusted/JDK-8006529.js	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/script/trusted/JDK-8006529.js	Tue Sep 16 13:59:37 2014 -0700
@@ -120,7 +120,7 @@
 
 var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class)
 var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class)
-var CompilerConstructor = Compiler.class.getConstructor(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, boolean.class);
+var CompilerConstructor = Compiler.class.getConstructor(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, ErrorManager.class, boolean.class);
 
 // compile(script) -- compiles a script specified as a string with its
 // source code, returns a jdk.nashorn.internal.ir.FunctionNode object
@@ -134,7 +134,7 @@
     var parser   = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance());
     var func     = parseMethod.invoke(parser);
 
-    var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, false);
+    var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, null, false);
 
     return compileMethod.invoke(compiler, func, phases);
 };
--- a/test/src/jdk/nashorn/api/scripting/ScopeTest.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/src/jdk/nashorn/api/scripting/ScopeTest.java	Tue Sep 16 13:59:37 2014 -0700
@@ -407,6 +407,75 @@
         Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context");
     }
 
+
+    /**
+     * Test multi-threaded access to prototype user accessor properties for shared script classes with multiple globals.
+     */
+    @Test
+    public static void multiThreadedAccessorTest() throws ScriptException, InterruptedException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final Bindings b = e.createBindings();
+        final ScriptContext origContext = e.getContext();
+        final ScriptContext newCtxt = new SimpleScriptContext();
+        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+        e.eval("Object.defineProperty(Object.prototype, 'foo', { get: function() 'original context' })", origContext);
+        e.eval("Object.defineProperty(Object.prototype, 'foo', { get: function() 'new context', configurable: true })", newCtxt);
+        final String sharedScript = "({}).foo";
+
+        final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+        t1.start();
+        t2.start();
+        t1.join();
+        t2.join();
+
+        final Object obj3 = e.eval("delete Object.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+        assertEquals(obj3, "newer context");
+        final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+        t3.start();
+        t4.start();
+        t3.join();
+        t4.join();
+    }
+
+    /**
+     * Test multi-threaded access to primitive prototype user accessor properties for shared script classes with multiple globals.
+     */
+    @Test
+    public static void multiThreadedPrimitiveAccessorTest() throws ScriptException, InterruptedException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final Bindings b = e.createBindings();
+        final ScriptContext origContext = e.getContext();
+        final ScriptContext newCtxt = new SimpleScriptContext();
+        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+        e.eval("Object.defineProperty(String.prototype, 'foo', { get: function() 'original context' })", origContext);
+        e.eval("Object.defineProperty(String.prototype, 'foo', { get: function() 'new context' })", newCtxt);
+        final String sharedScript = "''.foo";
+
+        final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+        t1.start();
+        t2.start();
+        t1.join();
+        t2.join();
+
+        final Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+        assertEquals(obj3, "newer context");
+        final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+        t3.start();
+        t4.start();
+        t3.join();
+        t4.join();
+    }
+
     /**
      * Test multi-threaded scope function invocation for shared script classes with multiple globals.
      */
--- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java	Tue Sep 16 13:59:37 2014 -0700
@@ -98,11 +98,16 @@
             compileTestSet(new File(TEST262_SUITE_DIR), new TestFilter() {
                 @Override
                 public boolean exclude(final File file, final String content) {
-                    return content.indexOf("@negative") != -1;
+                    return content != null && content.contains("@negative");
                 }
             });
         }
-        compileTestSet(new File(TEST_BASIC_DIR), null);
+        compileTestSet(new File(TEST_BASIC_DIR), new TestFilter() {
+            @Override
+            public boolean exclude(final File file, final String content) {
+                return file.getName().equals("es6");
+            }
+        });
         compileTestSet(new File(TEST_NODE_DIR, "node"), null);
         compileTestSet(new File(TEST_NODE_DIR, "src"), null);
     }
@@ -136,6 +141,9 @@
     private int skipped;
 
     private void compileJSDirectory(final File dir, final TestFilter filter) {
+        if (filter != null && filter.exclude(dir, null)) {
+            return;
+        }
         for (final File f : dir.listFiles()) {
             if (f.isDirectory()) {
                 compileJSDirectory(f, filter);
--- a/test/src/jdk/nashorn/internal/parser/ParserTest.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java	Tue Sep 16 13:59:37 2014 -0700
@@ -82,11 +82,16 @@
             parseTestSet(TEST262_SUITE_DIR, new TestFilter() {
                 @Override
                 public boolean exclude(final File file, final String content) {
-                    return content.indexOf("@negative") != -1;
+                    return content != null && content.contains("@negative");
                 }
             });
         }
-        parseTestSet(TEST_BASIC_DIR, null);
+        parseTestSet(TEST_BASIC_DIR,  new TestFilter() {
+            @Override
+            public boolean exclude(final File file, final String content) {
+                return file.getName().equals("es6");
+            }
+        });
     }
 
     private void parseTestSet(final String testSet, final TestFilter filter) {
@@ -120,6 +125,9 @@
     private int skipped;
 
     private void parseJSDirectory(final File dir, final TestFilter filter) {
+        if (filter != null && filter.exclude(dir, null)) {
+            return;
+        }
         for (final File f : dir.listFiles()) {
             if (f.isDirectory()) {
                 parseJSDirectory(f, filter);
--- a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Thu Sep 11 15:34:13 2014 -0700
+++ b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Tue Sep 16 13:59:37 2014 -0700
@@ -261,14 +261,17 @@
                     isTest = false;
                     isNotTest = true;
                     break;
-                case "@runif":
-                    if (System.getProperty(scanner.next()) != null) {
+                case "@runif": {
+                    final String prop = scanner.next();
+                    if (System.getProperty(prop) != null) {
                         shouldRun = true;
                     } else {
+                        factory.log("WARNING: (" + prop + ") skipping " + testFile);
                         isTest = false;
                         isNotTest = true;
                     }
                     break;
+                }
                 case "@run":
                     shouldRun = true;
                     break;