changeset 1726:bf97e9141fe5

Merge
author asaha
date Thu, 29 Oct 2015 17:22:12 -0700
parents ee2c313d02a3 (current diff) d0af1c9ef101 (diff)
children 822042f1e4e8
files .hgtags src/jdk/nashorn/internal/codegen/AstSerializer.java src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java src/jdk/nashorn/internal/objects/PrototypeObject.java src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java src/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java test/src/jdk/nashorn/api/scripting/JSONCompatibleTest.java
diffstat 239 files changed, 7232 insertions(+), 3261 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Oct 16 12:19:59 2015 -0700
+++ b/.hgtags	Thu Oct 29 17:22:12 2015 -0700
@@ -484,4 +484,14 @@
 b8987f466586180cb4dc387f5fa290bb4cf34983 jdk8u71-b01
 a8fd49cb76fafc704b746a98bd18647802674d2d jdk8u71-b02
 12745568f9fb73a452d85b2388fef29909dafc24 jdk8u71-b03
+92b196168ef13e159e311e864c08d70e2c23dec6 jdk8u71-b04
+c870d760ca23b0f2c21813946eeb36563eeea8d4 jdk8u71-b05
+f76ef9364e15663fe29cda34f7d95cbab224ff36 jdk8u71-b06
+667e020da337e453eac8ecb9285c9b34a47e25fd jdk8u72-b00
+a105e7b0eff93895b82e3d372a63df4311d79821 jdk8u72-b01
+f7c3d65076a0c0bf1bb4ea633b4ea0af9ffb12fe jdk8u72-b02
+c47a6341ae31e394f6748acbeebf68de3ae285ff jdk8u72-b03
+4592976d8655d9ec0ad364901ae07c79813c8cd4 jdk8u72-b04
+0c87ce7cc7d01462476bce07945dc1646b4f08d1 jdk8u72-b05
+a2591c7bcb92f5bb2bd53b46d5a2c97be367f7fe jdk8u72-b06
 c7eddafb2ee2cc9d62f20c4d821ccac03bd4617d jdk8u75-b00
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -54,10 +54,9 @@
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE;
@@ -282,9 +281,9 @@
         assert specs != null;
         if (!specs.isEmpty()) {
             mi.memberInfoArray(className, specs);
-            mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC);
+            mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC);
         } else {
-            mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC);
+            mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_DESC);
         }
 
         if (arityFound) {
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -38,9 +38,8 @@
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC3;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC4;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC3;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC4;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETPROTOTYPE;
@@ -55,7 +54,7 @@
 import jdk.internal.org.objectweb.asm.Handle;
 
 /**
- * This class generates constructor class for a @ClassInfo annotated class.
+ * This class generates constructor class for a @ScriptClass annotated class.
  *
  */
 public class ConstructorGenerator extends ClassGenerator {
@@ -75,8 +74,8 @@
     }
 
     byte[] getClassBytes() {
-        // new class extensing from ScriptObject
-        final String superClass = (constructor != null)? SCRIPTFUNCTIONIMPL_TYPE : SCRIPTOBJECT_TYPE;
+        // new class extending from ScriptObject
+        final String superClass = (constructor != null)? SCRIPTFUNCTION_TYPE : SCRIPTOBJECT_TYPE;
         cw.visit(V1_7, ACC_FINAL, className, null, superClass, null);
         if (memberCount > 0) {
             // add fields
@@ -182,8 +181,8 @@
             loadMap(mi);
         } else {
             // call Function.<init>
-            superClass = SCRIPTFUNCTIONIMPL_TYPE;
-            superDesc = (memberCount > 0) ? SCRIPTFUNCTIONIMPL_INIT_DESC4 : SCRIPTFUNCTIONIMPL_INIT_DESC3;
+            superClass = SCRIPTFUNCTION_TYPE;
+            superDesc = (memberCount > 0) ? SCRIPTFUNCTION_INIT_DESC4 : SCRIPTFUNCTION_INIT_DESC3;
             mi.loadLiteral(constructor.getName());
             mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc()));
             loadMap(mi);
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java	Thu Oct 29 17:22:12 2015 -0700
@@ -161,7 +161,7 @@
     }
 
     /**
-     * Tag something as optimitic builtin or not
+     * Tag something as optimistic builtin or not
      * @param isOptimistic boolean, true if builtin constructor
      */
     public void setIsOptimistic(final boolean isOptimistic) {
@@ -178,7 +178,7 @@
     }
 
     /**
-     * Set thre SpecializedFunction link logic class for specializations, i.e. optimistic
+     * Set the SpecializedFunction link logic class for specializations, i.e. optimistic
      * builtins
      * @param linkLogicClass link logic class
      */
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -42,7 +42,7 @@
 import java.io.IOException;
 
 /**
- * This class generates prototype class for a @ClassInfo annotated class.
+ * This class generates prototype class for a @ScriptClass annotated class.
  *
  */
 public class PrototypeGenerator extends ClassGenerator {
@@ -57,7 +57,7 @@
     }
 
     byte[] getClassBytes() {
-        // new class extensing from ScriptObject
+        // new class extending from ScriptObject
         cw.visit(V1_7, ACC_FINAL | ACC_SUPER, className, null, PROTOTYPEOBJECT_TYPE, null);
         if (memberCount > 0) {
             // add fields
@@ -155,7 +155,7 @@
      */
     public static void main(final String[] args) throws IOException {
         if (args.length != 1) {
-            System.err.println("Usage: " + ConstructorGenerator.class.getName() + " <class>");
+            System.err.println("Usage: " + PrototypeGenerator.class.getName() + " <class>");
             System.exit(1);
         }
 
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java	Thu Oct 29 17:22:12 2015 -0700
@@ -48,7 +48,7 @@
  *
  */
 public final class ScriptClassInfo {
-    // descriptots for various annotations
+    // descriptors for various annotations
     static final String SCRIPT_CLASS_ANNO_DESC  = Type.getDescriptor(ScriptClass.class);
     static final String CONSTRUCTOR_ANNO_DESC   = Type.getDescriptor(Constructor.class);
     static final String FUNCTION_ANNO_DESC      = Type.getDescriptor(Function.class);
@@ -140,7 +140,7 @@
     }
 
     boolean isPrototypeNeeded() {
-        // Prototype class generation is needed if we have atleast one
+        // Prototype class generation is needed if we have at least one
         // prototype property or @Constructor defined in the class.
         for (final MemberInfo memInfo : members) {
             if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) {
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java	Thu Oct 29 17:22:12 2015 -0700
@@ -118,7 +118,7 @@
                     addScriptMember(memInfo);
 
                     return new AnnotationVisitor(Opcodes.ASM4, delegateAV) {
-                        // These could be "null" if values are not suppiled,
+                        // These could be "null" if values are not supplied,
                         // in which case we have to use the default values.
                         private String  name;
                         private Integer attributes;
@@ -194,7 +194,7 @@
 
                     final MemberInfo memInfo = new MemberInfo();
 
-                    //annokind == e.g. GETTER or SPECIALIZED_FUNCTION
+                    // annoKind == GETTER or SPECIALIZED_FUNCTION
                     memInfo.setKind(annoKind);
                     memInfo.setJavaName(methodName);
                     memInfo.setJavaDesc(methodDesc);
@@ -203,7 +203,7 @@
                     addScriptMember(memInfo);
 
                     return new AnnotationVisitor(Opcodes.ASM4, delegateAV) {
-                        // These could be "null" if values are not suppiled,
+                        // These could be "null" if values are not supplied,
                         // in which case we have to use the default values.
                         private String  name;
                         private Integer attributes;
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java	Thu Oct 29 17:22:12 2015 -0700
@@ -65,7 +65,6 @@
  * 2) add "Map" type static field named "$map".
  * 3) add static initializer block to initialize map.
  */
-
 public class ScriptClassInstrumentor extends ClassVisitor {
     private final ScriptClassInfo scriptClassInfo;
     private final int memberCount;
@@ -267,7 +266,7 @@
      */
     public static void main(final String[] args) throws IOException {
         if (args.length != 1) {
-            System.err.println("Usage: " + ScriptClassInfoCollector.class.getName() + " <class>");
+            System.err.println("Usage: " + ScriptClassInstrumentor.class.getName() + " <class>");
             System.exit(1);
         }
 
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java	Thu Oct 29 17:22:12 2015 -0700
@@ -31,10 +31,9 @@
 import java.util.Collections;
 import java.util.List;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.nashorn.internal.objects.PrototypeObject;
-import jdk.nashorn.internal.objects.ScriptFunctionImpl;
 import jdk.nashorn.internal.runtime.AccessorProperty;
 import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.PrototypeObject;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Specialization;
@@ -88,7 +87,6 @@
     static final Type TYPE_PROPERTYMAP        = Type.getType(PropertyMap.class);
     static final Type TYPE_PROTOTYPEOBJECT    = Type.getType(PrototypeObject.class);
     static final Type TYPE_SCRIPTFUNCTION     = Type.getType(ScriptFunction.class);
-    static final Type TYPE_SCRIPTFUNCTIONIMPL = Type.getType(ScriptFunctionImpl.class);
     static final Type TYPE_SCRIPTOBJECT       = Type.getType(ScriptObject.class);
 
     static final String PROTOTYPE_SUFFIX = "$Prototype";
@@ -122,17 +120,14 @@
     static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE);
     static final String SCRIPTFUNCTION_SETPROTOTYPE = "setPrototype";
     static final String SCRIPTFUNCTION_SETPROTOTYPE_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT);
-
-    // ScriptFunctionImpl
-    static final String SCRIPTFUNCTIONIMPL_TYPE = TYPE_SCRIPTFUNCTIONIMPL.getInternalName();
-    static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION = "makeFunction";
-    static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC =
+    static final String SCRIPTFUNCTION_CREATEBUILTIN = "createBuiltin";
+    static final String SCRIPTFUNCTION_CREATEBUILTIN_DESC =
         Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE);
-    static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC =
+    static final String SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC =
         Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY);
-    static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 =
+    static final String SCRIPTFUNCTION_INIT_DESC3 =
         Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY);
-    static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 =
+    static final String SCRIPTFUNCTION_INIT_DESC4 =
         Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_SPECIALIZATION_ARRAY);
 
     // ScriptObject
--- a/make/build.xml	Fri Oct 16 12:19:59 2015 -0700
+++ b/make/build.xml	Thu Oct 29 17:22:12 2015 -0700
@@ -209,10 +209,11 @@
     </jar>
   </target>
 
+  <!-- generate javadoc for all Nashorn and ASM classes -->
   <target name="javadoc" depends="jar">
     <javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${src.dir}/overview.html" 
         extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
-        additionalparam="-quiet" failonerror="true">
+        additionalparam="-quiet" failonerror="true" useexternalfile="true">
       <classpath>
         <pathelement location="${build.classes.dir}"/>
       </classpath>
@@ -226,10 +227,23 @@
     </javadoc>
   </target>
 
+  <!-- generate javadoc for Nashorn classes -->
+  <target name="javadocnh" depends="jar">
+    <javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${src.dir}/overview.html"
+        extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
+        additionalparam="-quiet" failonerror="true" useexternalfile="true">
+      <classpath>
+        <pathelement location="${build.classes.dir}"/>
+      </classpath>
+      <fileset dir="${src.dir}" includes="**/*.java"/>
+      <link href="http://docs.oracle.com/javase/8/docs/api/"/>
+    </javadoc>
+  </target>
+
   <!-- generate javadoc only for nashorn extension api classes -->
   <target name="javadocapi" depends="jar">
     <javadoc destdir="${dist.javadoc.dir}" use="yes" extdirs="${nashorn.ext.path}" 
-        windowtitle="${nashorn.product.name}" additionalparam="-quiet" failonerror="true">
+        windowtitle="${nashorn.product.name}" additionalparam="-quiet" failonerror="true" useexternalfile="true">
       <classpath>
         <pathelement location="${build.classes.dir}"/>
       </classpath>
@@ -238,7 +252,6 @@
     </javadoc>
   </target>
 
-
   <!-- generate shell.html for shell tool documentation -->
   <target name="shelldoc" depends="jar">
     <java classname="${nashorn.shell.tool}" dir="${basedir}" output="${dist.dir}/shell.html" failonerror="true" fork="true">
@@ -267,8 +280,8 @@
     <javac srcdir="${test.src.dir}"
            destdir="${build.test.classes.dir}"
            classpath="${javac.test.classpath}"
-           source="${javac.source}"
-           target="${javac.target}"
+           source="${test.javac.source}"
+           target="${test.javac.target}"
            debug="${javac.debug}"
            encoding="${javac.encoding}"
            includeantruntime="false" fork="true">
@@ -460,7 +473,7 @@
     </testng>
   </target>
 
-  <target name="test" depends="get-testng, javadoc, test-pessimistic, test-optimistic"/>
+  <target name="test" depends="get-testng, javadocnh, test-pessimistic, test-optimistic"/>
 
   <target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <echo message="Running test suite in OPTIMISTIC mode..."/>
--- a/make/project.properties	Fri Oct 16 12:19:59 2015 -0700
+++ b/make/project.properties	Thu Oct 29 17:22:12 2015 -0700
@@ -30,6 +30,8 @@
 build.compiler=modern
 javac.source=1.7
 javac.target=1.7
+test.javac.source=1.8
+test.javac.target=1.8
 
 # nashorn version information
 nashorn.version=0.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/EvalWithArbitraryThis.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import javax.script.*;
+import jdk.nashorn.api.scripting.*;
+
+// Simple nashorn demo that evals a script with arbitrary script
+// object bound as "this" for the evaluated script.
+
+public class EvalWithArbitraryThis {
+    public static void main(String[] args) throws Exception {
+        ScriptEngineManager m = new ScriptEngineManager();
+        ScriptEngine e = m.getEngineByName("nashorn");
+        Object sobj = e.eval("( { foo: 343, bar: 'hello' } )");
+
+        // "this" bound to sobj in this eval.
+        // so it prints sobj.foo and sobj.bar.
+        ((ScriptObjectMirror)sobj).eval("print(this.foo); print(this.bar)");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/LambdaAsFunc.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import javax.script.*;
+import java.util.function.*;
+
+// example demonstrating that arbitrary Lambda can be called as function from script
+
+public class LambdaAsFunc {
+    public static void main(String[] args) throws Exception {
+        ScriptEngineManager m = new ScriptEngineManager();
+        ScriptEngine e = m.getEngineByName("nashorn");
+
+        // expose a lambda as top-level script function
+        e.put("upper", (Function<String, String>) String::toUpperCase);
+
+        // call lambda as though it is a normal script function
+        System.out.println(e.eval("upper('hello')"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/Main.asm	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Simple sample to demonstrate openjdk asmtools assembler with
+// nashorn dynalink linker in a invokedynamic instruction.
+//
+// To assemble this file, use the following command:
+//
+//    java -cp <asmtools.jar> org.openjdk.asmtools.Main jasm Main.asm
+//
+// See also: https://wiki.openjdk.java.net/display/CodeTools/asmtools
+//
+// NOTE: Uses nashorn internals and so *may* break with later nashorn!
+
+super public class Main
+	version 52:0
+{
+
+
+public Method "<init>":"()V"
+	stack 1 locals 1
+{
+		aload_0;
+		invokespecial	Method java/lang/Object."<init>":"()V";
+		return;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+	stack 2 locals 2
+{
+                // List l = new ArrayList();
+		new	class java/util/ArrayList;
+		dup;
+		invokespecial	Method java/util/ArrayList."<init>":"()V";
+		astore_1;
+		aload_1;
+
+                // l.add("hello");
+		ldc	String "hello";
+		invokeinterface	InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z",  2;
+		pop;
+
+                // l.add("world");
+		aload_1;
+		ldc	String "world";
+		invokeinterface	InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z",  2;
+		pop;
+
+                // printLength(l);
+		aload_1;
+		invokestatic	Method printLength:"(Ljava/lang/Object;)V";
+
+                // printLength(args); // args is argument of main method
+		aload_0;
+		invokestatic	Method printLength:"(Ljava/lang/Object;)V";
+		return;
+}
+
+private static Method printLength:"(Ljava/lang/Object;)V"
+	stack 2 locals 1
+{
+		getstatic	Field java/lang/System.out:"Ljava/io/PrintStream;";
+		aload_0;
+
+                // Using nashorn embedded dynalink linker with the following invokedynamic
+                // 'length' property on a bean - arrays, lists supported
+
+                invokedynamic   InvokeDynamic REF_invokeStatic:jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;":"dyn:getProp|getElem|getMethod:length":"(Ljava/lang/Object;)Ljava/lang/Object;" int 0;
+
+                // print 'length' value
+		invokevirtual	Method java/io/PrintStream.println:"(Ljava/lang/Object;)V";
+		return;
+}
+
+} // end Class Main
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/PrintToString.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import javax.script.*;
+import java.io.StringWriter;
+
+// simple example demonstrating capturing of "print" output
+// from script execution as a String via script engine API.
+
+public class PrintToString {
+  public static void main(String[] args) throws ScriptException {
+    ScriptEngineManager m = new ScriptEngineManager();
+    ScriptEngine e = m.getEngineByName("nashorn");
+    StringWriter sw = new StringWriter();
+    e.getContext().setWriter(sw);
+    e.eval("print('hello world')");
+    System.out.println(sw.toString());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/array_removeif.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Sample for Collection.removeIf and Java.to
+// See http://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#removeIf-java.util.function.Predicate-
+ 
+var langs = [
+    "java", "javascript",
+    "C", "C#", "C++",
+    "Erlang", "Haskell"
+];
+ 
+// convert script array to a Java List
+function asList(array) {
+    return Java.to(array, java.util.List);
+}
+ 
+// remove elements that satisfy a predicate
+// using Collection.removeIf(Predicate)
+asList(langs).removeIf(
+    function(s) s.startsWith("C"));
+ 
+// print modified array
+print(langs);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/bind_on_java.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// sample to demonstrate calling Function.prototype.bind on Java methods.
+
+var DoubleStream = java.util.stream.DoubleStream;
+var r = new java.util.Random();
+
+// bind "this" for nextGaussian method of Random class
+var next = Function.bind.call(r.nextGaussian, r);
+
+// next is used as no argument "function"
+DoubleStream
+    .generate(function() next())
+    .limit(100)
+    .forEach(print);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/call_bind_java.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Sample demonstrating calling Java methods like normal
+// functions. Bound instance methods, static methods can be
+// called like normal script functions.
+
+// Java types used
+var Files = Java.type("java.nio.file.Files");
+var FileSystems = Java.type("java.nio.file.FileSystems");
+var System = Java.type("java.lang.System");
+
+var fs = FileSystems.default;
+var bind = Function.prototype.bind;
+
+// Java methods as "functions"
+
+// Java method with bound "this"
+var Path = bind.call(fs.getPath, fs);
+// Java static method
+var Property = System.getProperty;
+
+// call Java static methods and bound instance methods
+// like normal script functions.
+
+var root = Path("/");
+// print URI for root dir
+print(root.toUri());
+var home = Path(Property("user.home"));
+// list home directory
+Files.walk(home).forEach(print);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/check_nashorn.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// check if script is being run using nashorn script engine
+function isNashorn() {
+  try {
+    // "engine" variable is of type javax.script.ScriptEngine is defined
+    // by nashorn jsr-223 engine. Check the name of the engine from
+    // javax.script.ScriptEngineFactory associated
+    
+    return engine.factory.engineName.contains("Nashorn");
+  } catch (e) {
+    // if engine or any of the properties are undefined
+    // then script is not being run using nashorn.
+    return false;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/datetime.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// converting b/w JavaScript Date and Java LocalDateTime
+
+// JavaScript Date with current time
+var d = new Date();
+print(d);
+ 
+// Java 8 java.time classes used
+var Instant = java.time.Instant;
+var LocalDateTime = java.time.LocalDateTime;
+var ZoneId = java.time.ZoneId;
+ 
+// Date.prototype.getTime
+
+// getTime() method returns the numeric value corresponding to the time
+// for the specified date according to universal time. The value returned
+// by the getTime() method is the number of milliseconds since 1 January 1970 00:00:00 UTC.
+// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime
+ 
+// Java Instant.ofEpochMilli to convert time in milliseconds to Instant object
+// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#ofEpochMilli-long-
+ 
+var instant = Instant.ofEpochMilli(d.getTime());
+ 
+// Instant to LocalDateTime using LocalDateTime.ofInstant
+// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#ofInstant-java.time.Instant-java.time.ZoneId-
+ 
+var ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
+print(ldt);
+ 
+// converting a LocalDateTime to JavaScript Date
+// convert LocalDateTime to Instant first
+// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#atZone-java.time.ZoneId-
+ 
+var instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
+ 
+// instant to to epoch milliseconds
+// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#toEpochMilli--
+// and then to JavaScript Date from time in milliseconds
+// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date
+
+var d1 = new Date(instant.toEpochMilli());
+print(d1); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/defaults.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// print default methods of a Java class
+
+if (arguments.length == 0) {
+   print("Usage: jjs defaults.js -- <java class name>");
+   exit(1);
+}
+
+var jclass = Java.type(arguments[0]).class;
+for each (m in jclass.methods) {
+    // http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#isDefault--
+    if (m.default) print(m);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/exceptionswallow.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,136 @@
+#// Usage: jjs exceptionswallow.js -- <directory>
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This example demonstrates Java subclassing by Java.extend
+// and javac Compiler and Tree API. This example looks for
+// empty catch blocks ("exception swallow") and reports those.
+
+if (arguments.length == 0) {
+    print("Usage: jjs exceptionswallow.js -- <directory>");
+    exit(1);
+}
+ 
+// Java types used
+var File = Java.type("java.io.File");
+var Files = Java.type("java.nio.file.Files");
+var StringArray = Java.type("java.lang.String[]");
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var Tree = Java.type("com.sun.source.tree.Tree");
+var EmptyStatementTree = Java.type("com.sun.source.tree.EmptyStatementTree");
+var Trees = Java.type("com.sun.source.util.Trees");
+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
+
+// printEmptyCatch
+
+function printEmptyCatch() {
+    // get the system compiler tool
+    var compiler = ToolProvider.systemJavaCompiler;
+    // get standard file manager
+    var fileMgr = compiler.getStandardFileManager(null, null, null);
+    // Using Java.to convert script array (arguments) to a Java String[]
+    var compUnits = fileMgr.getJavaFileObjects(
+        Java.to(arguments, StringArray));
+    // create a new compilation task
+    var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
+
+    // SourcePositions object to get positions of AST nodes
+    var sourcePositions = Trees.instance(task).sourcePositions;
+
+    // subclass SimpleTreeVisitor - to print empty catch
+    var EmptyCatchFinder = Java.extend(TreeScanner);
+   
+    function hasOnlyEmptyStats(stats) {
+        var itr = stats.iterator();
+        while (itr.hasNext()) {
+            if (! (itr.next() instanceof EmptyStatementTree)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+ 
+    var visitor = new EmptyCatchFinder() {
+        // current CompilationUnitTree
+        compUnit: null,
+        // current LineMap (pos -> line, column)
+        lineMap: null,
+        // current compilation unit's file name
+        fileName: null,
+
+        // overrides of TreeScanner methods
+
+        visitCompilationUnit: function(node, p) {
+            // capture info about current Compilation unit
+            this.compUnit = node;
+            this.lineMap = node.lineMap;
+            this.fileName = node.sourceFile.name;
+
+            // Using Java.super API to call super class method here
+            return Java.super(visitor).visitCompilationUnit(node, p);
+        },
+
+        visitCatch: function (node, p) {
+            var stats = node.block.statements;
+            if (stats.empty || hasOnlyEmptyStats(stats)) {
+                // print information on this empty catch
+                var pos = sourcePositions.getStartPosition(this.compUnit, node);
+                var line = this.lineMap.getLineNumber(pos);
+                var col = this.lineMap.getColumnNumber(pos);
+                print("Exception swallow" + " @ " + this.fileName + ":" + line + ":" + col);
+                // print(node);
+            }
+        }
+    }
+ 
+    for each (var cu in task.parse()) {
+        cu.accept(visitor, null);
+    }
+}
+ 
+// for each ".java" file in directory (recursively) and check it!
+function main(dir) {
+    Files.walk(dir.toPath()).
+      forEach(function(p) {
+        var name = p.toFile().absolutePath;
+        if (name.endsWith(".java")) {
+            try {
+                printEmptyCatch(p.toFile().getAbsolutePath());
+            } catch (e) {
+                print(e);
+            }
+        }
+      });
+}
+ 
+main(new File(arguments[0]));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/find_max_lines.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Find the file with maximum number of lines
+
+var Files = Java.type("java.nio.file.Files");
+var Integer = Java.type("java.lang.Integer");
+var Paths = Java.type("java.nio.file.Paths");
+
+var file = arguments.length == 0? "." : arguments[0];
+var ext = arguments.length > 1? arguments[1] : ".java";
+var path = Paths.get(file);
+
+// return number of lines in given Path (that represents a file)
+function lines(p) {
+    var strm = Files.lines(p);
+    try {
+        return strm.count();
+    } finally {
+        strm.close();
+    }
+}
+
+// walk files, map to file and lines, find the max    
+var obj = Files.find(path, Integer.MAX_VALUE, 
+    function(p, a) !p.toFile().isDirectory() && p.toString().endsWith(ext)).
+map(function(p) ({ path : p, lines: lines(p) })).
+max(function(x, y) x.lines - y.lines).get();
+
+// print path and lines of the max line file
+print(obj.path, obj.lines);
--- a/samples/find_nonfinals2.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/samples/find_nonfinals2.js	Thu Oct 29 17:22:12 2015 -0700
@@ -43,7 +43,6 @@
 // Java types used
 var File = Java.type("java.io.File");
 var Files = Java.type("java.nio.file.Files");
-var FileVisitOption = Java.type("java.nio.file.FileVisitOption");
 var StringArray = Java.type("java.lang.String[]");
 var ToolProvider = Java.type("javax.tools.ToolProvider");
 var Tree = Java.type("com.sun.source.tree.Tree");
@@ -106,7 +105,7 @@
 // for each ".java" file in directory (recursively).
 function main(dir) {
     var totalCount = 0;
-    Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS).
+    Files.walk(dir.toPath()).
       forEach(function(p) {
         var name = p.toFile().absolutePath;
         if (name.endsWith(".java")) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/fixed_point.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Simple sample demonstrating "fixed point" computation with Streams
+
+// See also https://mitpress.mit.edu/sicp/chapter1/node21.html#secprocgeneralmethods
+var Stream = Java.type("java.util.stream.Stream");
+
+// generic fixed point procedure
+function fixed_point(f, init_guess) {
+  var tolerance = 0.00001;
+  function close_enough(v1, v2) Math.abs(v1 - v2) < tolerance;
+ 
+  var prev; 
+  return Stream.iterate(init_guess, f)
+      .filter(function(x) {
+          try {
+              return prev == undefined? false : close_enough(prev, x);
+          } finally {
+              prev = x;
+          }
+      })
+      .findFirst()
+      .get();
+}
+
+// solution to x = cos(x)
+print(fixed_point(Math.cos, 1.0))
+
+// solution to x = sin(x) + cos(x)
+print(fixed_point(function(x) Math.sin(x) + Math.cos(x), 1.0));
+
+// square root by Newton's method
+// http://en.wikipedia.org/wiki/Newton's_method
+function sqrt(n)
+  fixed_point(function(x) (x + n/x) / 2, 2.0);
+
+print(sqrt(2))
+print(sqrt(3))
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/importstatic.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Java like "import static class_name.*" for nashorn
+
+function importStatic(clazz) {
+    // make sure the argument is a Java type
+    if (! Java.isType(clazz)) {
+        throw new TypeError(clazz + " is not a Java type");
+    }
+
+    // bind properties of clazz to an object
+    var obj = Object.bindProperties({}, clazz);
+
+    // copy properties to global to "import" those
+    for (var i in obj) {
+        this[i] = obj[i];
+    }
+}
+
+importStatic(java.time.Instant);
+print(now());
+print(ofEpochSecond(1));
+print(parse("2007-12-03T10:15:30.00Z"));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/javabind.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// bind on a Java method
+
+// #javascript "bind" function
+var bind = Function.prototype.bind;
+
+// Java console object
+var console = java.lang.System.console();
+
+// arguments "this" and prompt string of Console.readLine method are bound
+var readName = bind.call(console.readLine, console, "Your name: ");
+
+// Now call it like a function that takes no arguments!
+print("Hello,", readName());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/javaconstructorbind.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// bind on a Java constructor
+
+// See Function.prototype.bind:
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
+var bind = Function.prototype.bind;
+
+var URL = Java.type("java.net.URL");
+
+// get the constructor that accepts URL, String parameters.
+// constructor signatures are properties of type object.
+var newURL = URL["(URL, String)"];
+
+// bind "context" URL parameter.
+var TwitterURL = bind.call(newURL, null, new URL('https://www.twitter.com'));
+
+// now you can create context relative URLs using the bound constructor
+print(new TwitterURL("sundararajan_a"));
+
+// read the URL content and print (optional part)
+
+var BufferedReader = Java.type("java.io.BufferedReader");
+var InputStreamReader = Java.type("java.io.InputStreamReader");
+
+// function to retrieve text content of the given URL
+function readTextFromURL(url) {
+    var str = '';
+    var u = new URL(url);
+    var reader = new BufferedReader(
+        new InputStreamReader(u.openStream()));
+    try {
+        reader.lines().forEach(function(x) str += x);
+        return str;
+    } finally {
+        reader.close();
+    }
+}
+
+print(readTextFromURL(new TwitterURL("sundararajan_a")));
--- a/samples/javafoovars.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/samples/javafoovars.js	Thu Oct 29 17:22:12 2015 -0700
@@ -42,7 +42,6 @@
 // Java types used
 var File = Java.type("java.io.File");
 var Files = Java.type("java.nio.file.Files");
-var FileVisitOption = Java.type("java.nio.file.FileVisitOption");
 var StringArray = Java.type("java.lang.String[]");
 var ToolProvider = Java.type("javax.tools.ToolProvider");
 var Tree = Java.type("com.sun.source.tree.Tree");
@@ -81,7 +80,7 @@
 // for each ".java" file in directory (recursively) count "foo".
 function main(dir) {
     var totalCount = 0;
-    Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS).
+    Files.walk(dir.toPath()).
       forEach(function(p) {
         var name = p.toFile().absolutePath;
         if (name.endsWith(".java")) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/mapwith.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Using a Java map with Javascript "with" statement
+
+var map = new java.util.HashMap();
+map.put("foo", 34);
+map.put("bar", "hello");
+
+var obj = {
+    __noSuchProperty__: function(name) {
+        return map.get(name);
+    }
+};
+
+with(obj) {
+   print(foo);
+   print(bar);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/mothers_day.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,56 @@
+# compute Mothers day of the given the year
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// print "Mother's day" of the given year using Java Time API
+
+if (arguments.length == 0) {
+    print("Usage: jjs mothers_day.js -- year");
+    exit(1);
+}
+
+// java classes used
+var DayOfWeek = java.time.DayOfWeek;
+var LocalDate = java.time.LocalDate;
+var TemporalAdjusters = java.time.temporal.TemporalAdjusters;
+
+var year = parseInt(arguments[0]);
+
+// See: https://en.wikipedia.org/?title=Mother%27s_Day
+// We need second Sunday of May. Make April 30 of the given
+// year adjust and adjust to next Sunday from there twice. To adjust a Date
+// we use a common TemporalAdjuster provided in JDK8.
+// https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAdjusters.html
+
+print(LocalDate.of(year, 4, 30).
+    with(TemporalAdjusters.next(DayOfWeek.SUNDAY)).
+    with(TemporalAdjusters.next(DayOfWeek.SUNDAY)));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/passwordgen.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Simple password generator using SecureRandom + stream API
+
+// accept optional password length from command line
+var len = arguments.length? parseInt(arguments[0]) : 8;
+
+// Java types used
+var Collectors = Java.type("java.util.stream.Collectors");
+var SecureRandom = Java.type("java.security.SecureRandom");
+
+// allowed password chars
+var chars =
+ "!@#$%ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+// generated and print password
+print(new SecureRandom().
+    ints(len, 0, chars.length).
+    mapToObj(function(i) chars[i]).
+    collect(Collectors.joining("")));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/print_symlinks.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Print all symbolic links in user's home directory
+
+// JavaImporter and "with" to simulate "import" statements in Java.
+// See https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions
+
+with (new JavaImporter(java.nio.file, java.lang)) {
+
+  var userDir = System.getProperty("user.dir")
+  var home = FileSystems.default.getPath(userDir);
+
+  // JS functions can be passed where Java lambdas are required.
+  // Also, using "Expression closure" extension here.
+  // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Expression_Closures
+
+  Files.walk(home).
+    filter(function(p) Files.isSymbolicLink(p)).
+    forEach(function(p)
+      print(p, '->', Files.readSymbolicLink(p)));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/resourcetrysuggester.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,156 @@
+#// Usage: jjs resourcetrysuggester.js -- <directory>
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This example demonstrates Java subclassing by Java.extend
+// and javac Compiler and Tree API. This example looks for
+// finally clauses with "close" call and suggests "resource try"!
+
+if (arguments.length == 0) {
+    print("Usage: jjs resourcetrysuggester.js -- <directory>");
+    exit(1);
+}
+ 
+// Java types used
+var ExpressionStatementTree = Java.type("com.sun.source.tree.ExpressionStatementTree");
+var File = Java.type("java.io.File");
+var Files = Java.type("java.nio.file.Files");
+var MemberSelectTree = Java.type("com.sun.source.tree.MemberSelectTree");
+var MethodInvocationTree = Java.type("com.sun.source.tree.MethodInvocationTree");
+var StringArray = Java.type("java.lang.String[]");
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var Tree = Java.type("com.sun.source.tree.Tree");
+var Trees = Java.type("com.sun.source.util.Trees");
+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
+
+// resourceTrySuggestions
+
+function resourceTrySuggestions() {
+    // get the system compiler tool
+    var compiler = ToolProvider.systemJavaCompiler;
+    // get standard file manager
+    var fileMgr = compiler.getStandardFileManager(null, null, null);
+    // Using Java.to convert script array (arguments) to a Java String[]
+    var compUnits = fileMgr.getJavaFileObjects(
+        Java.to(arguments, StringArray));
+    // create a new compilation task
+    var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
+
+    // SourcePositions object to get positions of AST nodes
+    var sourcePositions = Trees.instance(task).sourcePositions;
+
+    // subclass SimpleTreeVisitor - to print resource try suggestions
+    var ResourceTrySuggester = Java.extend(TreeScanner);
+   
+    function hasOnlyEmptyStats(stats) {
+        var itr = stats.iterator();
+        while (itr.hasNext()) {
+            if (! (itr.next() instanceof EmptyStatementTree)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    // does the given statement list has an expression statement which
+    // calls "close" method (don't worry about types - just crude one will do)
+    function hasCloseCall(stats) {
+        var itr = stats.iterator();
+        while (itr.hasNext()) {
+            var stat = itr.next();
+            if (stat instanceof ExpressionStatementTree) {
+                var expr = stat.expression;
+                if (expr instanceof MethodInvocationTree) {
+                    var method = expr.methodSelect;
+                    if (method instanceof MemberSelectTree) {
+                        return method.identifier.toString().equals("close");
+                    }
+                }
+            }
+        }
+        return false;
+    }
+ 
+    var visitor = new ResourceTrySuggester() {
+        // current CompilationUnitTree
+        compUnit: null,
+        // current LineMap (pos -> line, column)
+        lineMap: null,
+        // current compilation unit's file name
+        fileName: null,
+
+        // overrides of TreeScanner methods
+
+        visitCompilationUnit: function(node, p) {
+            // capture info about current Compilation unit
+            this.compUnit = node;
+            this.lineMap = node.lineMap;
+            this.fileName = node.sourceFile.name;
+
+            // Using Java.super API to call super class method here
+            return Java.super(visitor).visitCompilationUnit(node, p);
+        },
+
+        visitTry: function (node, p) {
+            var finallyBlk = node.finallyBlock;
+            if (finallyBlk != null && hasCloseCall(finallyBlk.statements)) {
+                var pos = sourcePositions.getStartPosition(this.compUnit, node);
+                var line = this.lineMap.getLineNumber(pos);
+                var col = this.lineMap.getColumnNumber(pos);
+                print("Consider resource try statement " + " @ " + this.fileName + ":" + line + ":" + col);
+                // print(node);
+            }
+        }
+    }
+ 
+    for each (var cu in task.parse()) {
+        cu.accept(visitor, null);
+    }
+}
+ 
+// for each ".java" file in directory (recursively) and check it!
+function main(dir) {
+    Files.walk(dir.toPath()).
+      forEach(function(p) {
+        var name = p.toFile().absolutePath;
+        if (name.endsWith(".java")) {
+            try {
+                resourceTrySuggestions(p.toFile().getAbsolutePath());
+            } catch (e) {
+                print(e);
+            }
+        }
+      });
+}
+ 
+main(new File(arguments[0]));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/sort_by_java8.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Simple sorting with Java8 APIs
+
+// Separation key-extraction from key ordering
+
+// Simple demo for Comparator.comparing
+// http://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#comparing-java.util.function.Function-
+
+// data to be sorted
+var cards = [
+   { name: "hello", email: "foo@hello.com" },
+   { name: "world", email: "bar@world.com" },
+   { name: "see", email: "see@dontsee.com" },
+];
+
+var Collections = java.util.Collections;
+var Comparator = java.util.Comparator;
+
+// sort records name in reverse order of names
+Collections.sort(cards,
+  Comparator.comparing(function(a) a.name).reversed());
+
+print(JSON.stringify(cards))
+
+// sort records by email
+Collections.sort(cards,
+  Comparator.comparing(function(a) a.email));
+
+print(JSON.stringify(cards))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/this_for_eval.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// how to pass arbitrary "this" object for eval'ed script?
+
+var obj = { foo: 44 };
+
+// the following won't work. eval.apply is indirect eval call
+// and so 'this' will be global object always! So, this
+// line will print 'undefined'
+eval.apply(obj, [ " print(this.foo)" ]);
+
+obj.myEval = eval;
+
+// still won't work - still indirect 'eval' call!
+// still undefined is printed!
+obj.myEval("print(this.foo)");
+
+function func(code) {
+    eval(code);
+}
+
+// eval called inside func and so get's func's "this" as it's "this"!
+// So, 44 is printed
+
+func.apply(obj, [ "print(this.foo)" ]);
--- a/samples/zipfs.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/samples/zipfs.js	Thu Oct 29 17:22:12 2015 -0700
@@ -36,13 +36,12 @@
 
 var Files = Java.type("java.nio.file.Files")
 var FileSystems = Java.type("java.nio.file.FileSystems")
-var FileVisitOption = Java.type("java.nio.file.FileVisitOption")
 var Paths = Java.type("java.nio.file.Paths")
 
 var zipfile = Paths.get(arguments[0])
 var fs = FileSystems.newFileSystem(zipfile, null)
 var root = fs.rootDirectories[0]
-Files.walk(root, FileVisitOption.FOLLOW_LINKS).forEach(
+Files.walk(root).forEach(
    function(p) (print(p), print(Files.readAttributes(p, "zip:*")))
 )
 fs.close()
--- a/src/jdk/internal/dynalink/DynamicLinker.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/internal/dynalink/DynamicLinker.java	Thu Oct 29 17:22:12 2015 -0700
@@ -117,7 +117,7 @@
  *         return factory.createLinker();
  *     }
  *
- *     public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) {
+ *     public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
  *         return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(lookup, name, type)));
  *     }
  * }
--- a/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java	Thu Oct 29 17:22:12 2015 -0700
@@ -107,7 +107,7 @@
     private final AccessibleObject target;
     private final MethodType type;
 
-    public CallerSensitiveDynamicMethod(final AccessibleObject target) {
+    CallerSensitiveDynamicMethod(final AccessibleObject target) {
         super(getName(target));
         this.target = target;
         this.type = getMethodType(target);
@@ -115,8 +115,9 @@
 
     private static String getName(final AccessibleObject target) {
         final Member m = (Member)target;
-        return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(),
-                m.getName()));
+        final boolean constructor = m instanceof Constructor;
+        return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() :
+            getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor);
     }
 
     @Override
--- a/src/jdk/internal/dynalink/beans/FacetIntrospector.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/internal/dynalink/beans/FacetIntrospector.java	Thu Oct 29 17:22:12 2015 -0700
@@ -152,7 +152,7 @@
     boolean isAccessible(final Member m) {
         final Class<?> declaring = m.getDeclaringClass();
         // (declaring == clazz) is just an optimization - we're calling this only from code that operates on a
-        // non-restriced class, so if the declaring class is identical to the class being inspected, then forego
+        // non-restricted class, so if the declaring class is identical to the class being inspected, then forego
         // a potentially expensive restricted-package check.
         return declaring == clazz || !CheckRestrictedPackage.isRestrictedClass(declaring);
     }
--- a/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java	Thu Oct 29 17:22:12 2015 -0700
@@ -86,7 +86,9 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.text.Collator;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -242,6 +244,35 @@
         return methods.getFirst().isConstructor();
     }
 
+    @Override
+    public String toString() {
+        // First gather the names and sort them. This makes it consistent and easier to read.
+        final List<String> names = new ArrayList<>(methods.size());
+        int len = 0;
+        for (final SingleDynamicMethod m: methods) {
+            final String name = m.getName();
+            len += name.length();
+            names.add(name);
+        }
+        // Case insensitive sorting, so e.g. "Object" doesn't come before "boolean".
+        final Collator collator = Collator.getInstance();
+        collator.setStrength(Collator.SECONDARY);
+        Collections.sort(names, collator);
+
+        final String className = getClass().getName();
+        // Class name length + length of signatures + 2 chars/per signature for indentation and newline +
+        // 3 for brackets and initial newline
+        final int totalLength = className.length() + len + 2 * names.size() + 3;
+        final StringBuilder b = new StringBuilder(totalLength);
+        b.append('[').append(className).append('\n');
+        for(final String name: names) {
+            b.append(' ').append(name).append('\n');
+        }
+        b.append(']');
+        assert b.length() == totalLength;
+        return b.toString();
+    };
+
     ClassLoader getClassLoader() {
         return classLoader;
     }
--- a/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java	Thu Oct 29 17:22:12 2015 -0700
@@ -122,13 +122,13 @@
      * @param constructor does this represent a constructor?
      */
     SimpleDynamicMethod(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) {
-        super(getName(target, clazz, name));
+        super(getName(target, clazz, name, constructor));
         this.target = target;
         this.constructor = constructor;
     }
 
-    private static String getName(final MethodHandle target, final Class<?> clazz, final String name) {
-        return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name));
+    private static String getName(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) {
+        return getMethodNameWithSignature(target.type(), constructor ? name : getClassAndMethodName(clazz, name), !constructor);
     }
 
     @Override
--- a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java	Thu Oct 29 17:22:12 2015 -0700
@@ -98,7 +98,6 @@
  * target method to a call site type (including mapping variable arity methods to a call site signature with different
  * arity).
  * @author Attila Szegedi
- * @version $Id: $
  */
 abstract class SingleDynamicMethod extends DynamicMethod {
 
@@ -143,14 +142,18 @@
         return getMethodType().parameterList().equals(method.getMethodType().parameterList());
     }
 
-    static String getMethodNameWithSignature(final MethodType type, final String methodName) {
+    static String getMethodNameWithSignature(final MethodType type, final String methodName, final boolean withReturnType) {
         final String typeStr = type.toString();
         final int retTypeIndex = typeStr.lastIndexOf(')') + 1;
         int secondParamIndex = typeStr.indexOf(',') + 1;
         if(secondParamIndex == 0) {
             secondParamIndex = retTypeIndex - 1;
         }
-        return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex);
+        final StringBuilder b = new StringBuilder();
+        if (withReturnType) {
+            b.append(typeStr, retTypeIndex, typeStr.length()).append(' ');
+        }
+        return b.append(methodName).append('(').append(typeStr, secondParamIndex, retTypeIndex).toString();
     }
 
     /**
--- a/src/jdk/internal/dynalink/linker/GuardedInvocation.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/internal/dynalink/linker/GuardedInvocation.java	Thu Oct 29 17:22:12 2015 -0700
@@ -353,7 +353,7 @@
 
     /**
      * Applies argument filters to both the invocation and the guard (if there is one).
-     * @param pos the position of the first argumen being filtered
+     * @param pos the position of the first argument being filtered
      * @param filters the argument filters
      * @return a filtered invocation
      */
--- a/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java	Thu Oct 29 17:22:12 2015 -0700
@@ -110,7 +110,7 @@
 
     /**
      * Check if invocation is cacheable
-     * @return true if cachable, false otherwise
+     * @return true if cacheable, false otherwise
      */
     public boolean isCacheable() {
         return cacheable;
--- a/src/jdk/nashorn/api/scripting/AbstractJSObject.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/api/scripting/AbstractJSObject.java	Thu Oct 29 17:22:12 2015 -0700
@@ -182,7 +182,7 @@
     /**
      * Checking whether the given object is an instance of 'this' object.
      *
-     * @param instance instace to check
+     * @param instance instance to check
      * @return true if the given 'instance' is an instance of this 'function' object
      */
     @Override
--- a/src/jdk/nashorn/api/scripting/JSObject.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/api/scripting/JSObject.java	Thu Oct 29 17:22:12 2015 -0700
@@ -141,7 +141,7 @@
     /**
      * Checking whether the given object is an instance of 'this' object.
      *
-     * @param instance instace to check
+     * @param instance instance to check
      * @return true if the given 'instance' is an instance of this 'function' object
      */
     public boolean isInstance(final Object instance);
--- a/src/jdk/nashorn/api/scripting/NashornException.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/api/scripting/NashornException.java	Thu Oct 29 17:22:12 2015 -0700
@@ -51,6 +51,8 @@
     private String fileName;
     // script line number
     private int line;
+    // are the line and fileName unknown?
+    private boolean lineAndFileNameUnknown;
     // script column number
     private int column;
     // underlying ECMA error object - lazily initialized
@@ -92,27 +94,10 @@
      */
     protected NashornException(final String msg, final Throwable cause) {
         super(msg, cause == null ? null : cause);
-        // This is not so pretty - but it gets the job done. Note that the stack
-        // trace has been already filled by "fillInStackTrace" call from
-        // Throwable
-        // constructor and so we don't pay additional cost for it.
-
         // Hard luck - no column number info
         this.column = -1;
-
-        // Find the first JavaScript frame by walking and set file, line from it
-        // Usually, we should be able to find it in just few frames depth.
-        for (final StackTraceElement ste : getStackTrace()) {
-            if (ECMAErrors.isScriptFrame(ste)) {
-                // Whatever here is compiled from JavaScript code
-                this.fileName = ste.getFileName();
-                this.line = ste.getLineNumber();
-                return;
-            }
-        }
-
-        this.fileName = null;
-        this.line = 0;
+        // We can retrieve the line number and file name from the stack trace if needed
+        this.lineAndFileNameUnknown = true;
     }
 
     /**
@@ -121,6 +106,7 @@
      * @return the file name
      */
     public final String getFileName() {
+        ensureLineAndFileName();
         return fileName;
     }
 
@@ -131,6 +117,7 @@
      */
     public final void setFileName(final String fileName) {
         this.fileName = fileName;
+        lineAndFileNameUnknown = false;
     }
 
     /**
@@ -139,6 +126,7 @@
      * @return the line number
      */
     public final int getLineNumber() {
+        ensureLineAndFileName();
         return line;
     }
 
@@ -148,6 +136,7 @@
      * @param line the line number
      */
     public final void setLineNumber(final int line) {
+        lineAndFileNameUnknown = false;
         this.line = line;
     }
 
@@ -274,4 +263,19 @@
     public void setEcmaError(final Object ecmaError) {
         this.ecmaError = ecmaError;
     }
+
+    private void ensureLineAndFileName() {
+        if (lineAndFileNameUnknown) {
+            for (final StackTraceElement ste : getStackTrace()) {
+                if (ECMAErrors.isScriptFrame(ste)) {
+                    // Whatever here is compiled from JavaScript code
+                    fileName = ste.getFileName();
+                    line = ste.getLineNumber();
+                    return;
+                }
+            }
+
+            lineAndFileNameUnknown = false;
+        }
+    }
 }
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Oct 29 17:22:12 2015 -0700
@@ -140,7 +140,7 @@
         this._global_per_engine = nashornContext.getEnv()._global_per_engine;
 
         // create new global object
-        this.global = createNashornGlobal(context);
+        this.global = createNashornGlobal();
         // set the default ENGINE_SCOPE object for the default context
         context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
     }
@@ -167,7 +167,7 @@
             // We use same 'global' for all Bindings.
             return new SimpleBindings();
         }
-        return createGlobalMirror(null);
+        return createGlobalMirror();
     }
 
     // Compilable methods
@@ -317,7 +317,7 @@
 
         // We didn't find associated nashorn global mirror in the Bindings given!
         // Create new global instance mirror and associate with the Bindings.
-        final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
+        final ScriptObjectMirror mirror = createGlobalMirror();
         bindings.put(NASHORN_GLOBAL, mirror);
         return mirror.getHomeGlobal();
     }
@@ -333,13 +333,13 @@
     }
 
     // Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
-    private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
-        final Global newGlobal = createNashornGlobal(ctxt);
+    private ScriptObjectMirror createGlobalMirror() {
+        final Global newGlobal = createNashornGlobal();
         return new ScriptObjectMirror(newGlobal, newGlobal);
     }
 
     // Create a new Nashorn Global object
-    private Global createNashornGlobal(final ScriptContext ctxt) {
+    private Global createNashornGlobal() {
         final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
             @Override
             public Global run() {
@@ -354,7 +354,7 @@
             }
         }, CREATE_GLOBAL_ACC_CTXT);
 
-        nashornContext.initGlobal(newGlobal, this, ctxt);
+        nashornContext.initGlobal(newGlobal, this);
 
         return newGlobal;
     }
--- a/src/jdk/nashorn/api/scripting/ScriptUtils.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java	Thu Oct 29 17:22:12 2015 -0700
@@ -79,7 +79,7 @@
      * @return a synchronizing wrapper function
      */
     public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) {
-        return func.makeSynchronizedFunction(unwrap(sync));
+        return func.createSynchronized(unwrap(sync));
     }
 
     /**
--- a/src/jdk/nashorn/api/scripting/URLReader.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/api/scripting/URLReader.java	Thu Oct 29 17:22:12 2015 -0700
@@ -103,7 +103,7 @@
     /**
      * Charset used by this reader
      *
-     * @return the Chartset used to convert bytes to chars
+     * @return the Charset used to convert bytes to chars
      */
     public Charset getCharset() {
         return cs;
--- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Thu Oct 29 17:22:12 2015 -0700
@@ -40,11 +40,9 @@
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IdentNode;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -82,7 +80,7 @@
  */
 
 @Logger(name="apply2call")
-public final class ApplySpecialization extends NodeVisitor<LexicalContext> implements Loggable {
+public final class ApplySpecialization extends SimpleNodeVisitor implements Loggable {
 
     private static final boolean USE_APPLY2CALL = Options.getBooleanProperty("nashorn.apply2call", true);
 
@@ -106,7 +104,6 @@
      * @param compiler compiler
      */
     public ApplySpecialization(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
         this.log = initLogger(compiler.getContext());
     }
@@ -139,7 +136,7 @@
 
     private boolean hasApplies(final FunctionNode functionNode) {
         try {
-            functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            functionNode.accept(new SimpleNodeVisitor() {
                 @Override
                 public boolean enterFunctionNode(final FunctionNode fn) {
                     return fn == functionNode;
@@ -173,7 +170,7 @@
         final Deque<Set<Expression>> stack = new ArrayDeque<>();
 
         //ensure that arguments is only passed as arg to apply
-        functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        functionNode.accept(new SimpleNodeVisitor() {
 
             private boolean isCurrentArg(final Expression expr) {
                 return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call
@@ -283,17 +280,13 @@
             start++;
         }
 
-        start++; //we always uses this
+        start++; // we always use this
 
-        final List<IdentNode> params    = functionNode.getParameters();
+        assert functionNode.getNumOfParams() == 0 : "apply2call on function with named paramaters!";
         final List<IdentNode> newParams = new ArrayList<>();
-        final long to = Math.max(params.size(), actualCallSiteType.parameterCount() - start);
+        final long to = actualCallSiteType.parameterCount() - start;
         for (int i = 0; i < to; i++) {
-            if (i >= params.size()) {
-                newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i)));
-            } else {
-                newParams.add(params.get(i));
-            }
+            newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i)));
         }
 
         callSiteTypes.push(actualCallSiteType);
@@ -302,7 +295,28 @@
 
     @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
-        if (!USE_APPLY2CALL) {
+        // Cheap tests first
+        if (!(
+                // is the transform globally enabled?
+                USE_APPLY2CALL
+
+                // Are we compiling lazily? We can't known the number and types of the actual parameters at
+                // the caller when compiling eagerly, so this only works with on-demand compilation.
+                && compiler.isOnDemandCompilation()
+
+                // Does the function even reference the "arguments" identifier (without redefining it)? If not,
+                // it trivially can't have an expression of form "f.apply(self, arguments)" that this transform
+                // is targeting.
+                && functionNode.needsArguments()
+
+                // Does the function have eval? If so, it can arbitrarily modify arguments so we can't touch it.
+                && !functionNode.hasEval()
+
+                // Finally, does the function declare any parameters explicitly? We don't support that. It could
+                // be done, but has some complications. Therefore only a function with no explicit parameters
+                // is considered.
+                && functionNode.getNumOfParams() == 0))
+        {
             return false;
         }
 
@@ -312,14 +326,6 @@
             return false;
         }
 
-        if (!compiler.isOnDemandCompilation()) {
-            return false;
-        }
-
-        if (functionNode.hasEval()) {
-            return false;
-        }
-
         if (!hasApplies(functionNode)) {
             return false;
         }
@@ -375,7 +381,7 @@
         callSiteTypes.pop();
         explodedArguments.pop();
 
-        return newFunctionNode.setState(lc, CompilationState.BUILTINS_TRANSFORMED);
+        return newFunctionNode;
     }
 
     private static boolean isApply(final CallNode callNode) {
--- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Thu Oct 29 17:22:12 2015 -0700
@@ -65,17 +65,14 @@
 import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IndexNode;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LexicalContextNode;
 import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.RuntimeNode.Request;
+import jdk.nashorn.internal.ir.Splittable;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.SwitchNode;
 import jdk.nashorn.internal.ir.Symbol;
@@ -83,7 +80,7 @@
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ECMAErrors;
@@ -104,7 +101,7 @@
  * visitor.
  */
 @Logger(name="symbols")
-final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggable {
+final class AssignSymbols extends SimpleNodeVisitor implements Loggable {
     private final DebugLogger log;
     private final boolean     debug;
 
@@ -149,12 +146,13 @@
     private final Deque<Set<String>> thisProperties = new ArrayDeque<>();
     private final Map<String, Symbol> globalSymbols = new HashMap<>(); //reuse the same global symbol
     private final Compiler compiler;
+    private final boolean isOnDemand;
 
     public AssignSymbols(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
         this.log   = initLogger(compiler.getContext());
         this.debug = log.isEnabled();
+        this.isOnDemand = compiler.isOnDemandCompilation();
     }
 
     @Override
@@ -187,7 +185,7 @@
      */
     private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
         // This visitor will assign symbol to all declared variables.
-        body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        body.accept(new SimpleNodeVisitor() {
             @Override
             protected boolean enterDefault(final Node node) {
                 // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
@@ -242,7 +240,7 @@
 
     /**
      * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically
-     * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function
+     * used to create assignment of {@code :callee} to the function name symbol in self-referential function
      * expressions as well as for assignment of {@code :arguments} to {@code arguments}.
      *
      * @param name the ident node identifying the variable to initialize
@@ -390,7 +388,7 @@
 
             // Create and add to appropriate block.
             symbol = createSymbol(name, flags);
-            symbolBlock.putSymbol(lc, symbol);
+            symbolBlock.putSymbol(symbol);
 
             if ((flags & IS_SCOPE) == 0) {
                 // Initial assumption; symbol can lose its slot later
@@ -440,7 +438,7 @@
         start(block);
 
         if (lc.isFunctionBody()) {
-            block.clearSymbols();
+            assert !block.hasSymbols();
             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.
@@ -459,7 +457,7 @@
     }
 
     private boolean isUnparsedFunction(final FunctionNode fn) {
-        return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction();
+        return isOnDemand && fn != lc.getOutermostFunction();
     }
 
     @Override
@@ -551,9 +549,7 @@
     private void defineVarIdent(final VarNode varNode) {
         final IdentNode ident = varNode.getName();
         final int flags;
-        if (varNode.isAnonymousFunctionDeclaration()) {
-            flags = IS_INTERNAL;
-        } else if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
+        if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
             flags = IS_SCOPE;
         } else {
             flags = 0;
@@ -749,28 +745,6 @@
         }
     }
 
-    @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.
-        if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) {
-            // 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;
-    }
-
     private Node leaveDELETE(final UnaryNode unaryNode) {
         final FunctionNode currentFunctionNode = lc.getCurrentFunction();
         final boolean      strictMode          = currentFunctionNode.isStrict();
@@ -785,13 +759,14 @@
             // If this is a declared variable or a function parameter, delete always fails (except for globals).
             final String name = ident.getName();
             final Symbol symbol = ident.getSymbol();
+
+            if (symbol.isThis()) {
+                // Can't delete "this", ignore and return true
+                return LiteralNode.newInstance(unaryNode, true);
+            }
+            final Expression literalNode = LiteralNode.newInstance(unaryNode, name);
             final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel())));
 
-            if (failDelete && symbol.isThis()) {
-                return LiteralNode.newInstance(unaryNode, true).accept(this);
-            }
-            final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this);
-
             if (!failDelete) {
                 args.add(compilerConstantIdentifier(SCOPE));
             }
@@ -800,13 +775,15 @@
 
             if (failDelete) {
                 request = Request.FAIL_DELETE;
+            } else if ((symbol.isGlobal() && !symbol.isFunctionDeclaration()) || symbol.isProgramLevel()) {
+                request = Request.SLOW_DELETE;
             }
         } else if (rhs instanceof AccessNode) {
             final Expression base     = ((AccessNode)rhs).getBase();
             final String     property = ((AccessNode)rhs).getProperty();
 
             args.add(base);
-            args.add((Expression)LiteralNode.newInstance(unaryNode, property).accept(this));
+            args.add(LiteralNode.newInstance(unaryNode, property));
             args.add(strictFlagNode);
 
         } else if (rhs instanceof IndexNode) {
@@ -819,15 +796,15 @@
             args.add(strictFlagNode);
 
         } else {
-            return LiteralNode.newInstance(unaryNode, true).accept(this);
+            return LiteralNode.newInstance(unaryNode, true);
         }
-        return new RuntimeNode(unaryNode, request, args).accept(this);
+        return new RuntimeNode(unaryNode, request, args);
     }
 
     @Override
     public Node leaveForNode(final ForNode forNode) {
         if (forNode.isForIn()) {
-            forNode.setIterator(newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73
+            return forNode.setIterator(lc, newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73
         }
 
         return end(forNode);
@@ -847,7 +824,7 @@
                        lc.applyTopFlags(functionNode))))
                        .setThisProperties(lc, thisProperties.pop().size()));
         }
-        return finalizedFunction.setState(lc, CompilationState.SYMBOLS_ASSIGNED);
+        return finalizedFunction;
     }
 
     @Override
@@ -903,19 +880,18 @@
     public Node leaveSwitchNode(final SwitchNode switchNode) {
         // We only need a symbol for the tag if it's not an integer switch node
         if(!switchNode.isUniqueInteger()) {
-            switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX));
+            return switchNode.setTag(lc, newObjectInternal(SWITCH_TAG_PREFIX));
         }
         return switchNode;
     }
 
     @Override
     public Node leaveTryNode(final TryNode tryNode) {
-        tryNode.setException(exceptionSymbol());
         assert tryNode.getFinallyBody() == null;
 
         end(tryNode);
 
-        return tryNode;
+        return tryNode.setException(lc, exceptionSymbol());
     }
 
     private Node leaveTYPEOF(final UnaryNode unaryNode) {
@@ -924,13 +900,13 @@
         final List<Expression> args = new ArrayList<>();
         if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) {
             args.add(compilerConstantIdentifier(SCOPE));
-            args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null
+            args.add(LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName())); //null
         } else {
             args.add(rhs);
-            args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
+            args.add(LiteralNode.newInstance(unaryNode)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
         }
 
-        final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args).accept(this);
+        final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args);
 
         end(unaryNode);
 
@@ -938,7 +914,7 @@
     }
 
     private FunctionNode markProgramBlock(final FunctionNode functionNode) {
-        if (compiler.isOnDemandCompilation() || !functionNode.isProgram()) {
+        if (isOnDemand || !functionNode.isProgram()) {
             return functionNode;
         }
 
@@ -1005,7 +981,7 @@
         boolean previousWasBlock = false;
         for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
             final LexicalContextNode node = it.next();
-            if (node instanceof FunctionNode || isSplitArray(node)) {
+            if (node instanceof FunctionNode || isSplitLiteral(node)) {
                 // We reached the function boundary or a splitting boundary without seeing a definition for the symbol.
                 // It needs to be in scope.
                 return true;
@@ -1031,12 +1007,8 @@
         throw new AssertionError();
     }
 
-    private static boolean isSplitArray(final LexicalContextNode expr) {
-        if(!(expr instanceof ArrayLiteralNode)) {
-            return false;
-        }
-        final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits();
-        return !(units == null || units.isEmpty());
+    private static boolean isSplitLiteral(final LexicalContextNode expr) {
+        return expr instanceof Splittable && ((Splittable) expr).getSplitRanges() != null;
     }
 
     private void throwUnprotectedSwitchError(final VarNode varNode) {
--- a/src/jdk/nashorn/internal/codegen/AstSerializer.java	Fri Oct 16 12:19:59 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +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.  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.codegen;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.util.Collections;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import jdk.nashorn.internal.ir.Block;
-import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.Statement;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.runtime.options.Options;
-
-/**
- * This static utility class performs serialization of FunctionNode ASTs to a byte array.
- * The format is a standard Java serialization stream, deflated.
- */
-final class AstSerializer {
-    // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed
-    // and size.
-    private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4);
-    static byte[] serialize(final FunctionNode fn) {
-        final ByteArrayOutputStream out = new ByteArrayOutputStream();
-        final Deflater deflater = new Deflater(COMPRESSION_LEVEL);
-        try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) {
-            oout.writeObject(removeInnerFunctionBodies(fn));
-        } catch (final IOException e) {
-            throw new AssertionError("Unexpected exception serializing function", e);
-        } finally {
-            deflater.end();
-        }
-        return out.toByteArray();
-    }
-
-    private static FunctionNode removeInnerFunctionBodies(final FunctionNode fn) {
-        return (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            @Override
-            public Node leaveBlock(final Block block) {
-                if (lc.isFunctionBody() && lc.getFunction(block) != lc.getOutermostFunction()) {
-                    return block.setStatements(lc, Collections.<Statement>emptyList());
-                }
-                return super.leaveBlock(block);
-            }
-        });
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/codegen/CacheAst.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, 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.codegen;
+
+import java.util.ArrayDeque;
+import java.util.Collections;
+import java.util.Deque;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+
+class CacheAst extends SimpleNodeVisitor {
+    private final Deque<RecompilableScriptFunctionData> dataStack = new ArrayDeque<>();
+
+    private final Compiler compiler;
+
+    CacheAst(final Compiler compiler) {
+        this.compiler = compiler;
+        assert !compiler.isOnDemandCompilation();
+    }
+
+    @Override
+    public boolean enterFunctionNode(final FunctionNode functionNode) {
+        final int id = functionNode.getId();
+        // It isn't necessary to keep a stack of RecompilableScriptFunctionData, but then we'd need to do a
+        // potentially transitive lookup with compiler.getScriptFunctionData(id) for deeper functions; this way
+        // we keep it constant time.
+        dataStack.push(dataStack.isEmpty() ? compiler.getScriptFunctionData(id) : dataStack.peek().getScriptFunctionData(id));
+        return true;
+    }
+
+    @Override
+    public Node leaveFunctionNode(final FunctionNode functionNode) {
+        final RecompilableScriptFunctionData data = dataStack.pop();
+        if (functionNode.isSplit()) {
+            // NOTE: cache only split function ASTs from eager pass. Caching non-split functions would require
+            // some additional work, namely creating the concept of "uncacheable" function and reworking
+            // ApplySpecialization to ensure that functions undergoing apply-to-call transformations are not
+            // cacheable as well as recomputing Symbol.useCount when caching the eagerly parsed AST.
+            // Recomputing Symbol.useCount would be needed so it will only reflect uses from within the
+            // function being cached (and not reflect uses from its own nested functions or functions it is
+            // nested in). This is consistent with the count an on-demand recompilation of the function would
+            // produce. This is important as the decision to emit shared scope calls is based on this count,
+            // and if it is not matched between a previous version of the code and its deoptimizing rest-of
+            // compilation, it can result in rest-of not emitting a shared scope call where a previous version
+            // of the code (compiled from a cached eager pre-pass seeing higher (global) useCount) would emit
+            // it, causing a mismatch in stack shapes between previous code and its rest-of.
+            data.setCachedAst(functionNode);
+        }
+
+        if (!dataStack.isEmpty() && ((dataStack.peek().getFunctionFlags() & FunctionNode.IS_SPLIT) != 0)) {
+            // Return a function node with no body so that caching outer functions doesn't hold on to nested
+            // functions' bodies. Note we're doing this only for functions directly nested inside split
+            // functions, since we're only caching the split ones. It is not necessary to limit body removal
+            // to just these functions, but it's a cheap way to prevent unnecessary AST mutations.
+            return functionNode.setBody(lc, functionNode.getBody().setStatements(null, Collections.<Statement>emptyList()));
+        }
+        return functionNode;
+    }
+}
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -93,7 +93,6 @@
 import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.GetSplitState;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
@@ -106,7 +105,6 @@
 import jdk.nashorn.internal.ir.LexicalContextNode;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
 import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
 import jdk.nashorn.internal.ir.LocalVariableConversion;
 import jdk.nashorn.internal.ir.LoopNode;
@@ -119,6 +117,7 @@
 import jdk.nashorn.internal.ir.RuntimeNode.Request;
 import jdk.nashorn.internal.ir.SetSplitState;
 import jdk.nashorn.internal.ir.SplitReturn;
+import jdk.nashorn.internal.ir.Splittable;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.SwitchNode;
 import jdk.nashorn.internal.ir.Symbol;
@@ -130,9 +129,8 @@
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.objects.Global;
-import jdk.nashorn.internal.objects.ScriptFunctionImpl;
 import jdk.nashorn.internal.parser.Lexer.RegexToken;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
@@ -195,9 +193,9 @@
     private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
             "ensureNumber", double.class, Object.class, int.class);
 
-    private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
+    private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunction.class,
             "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class);
-    private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
+    private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunction.class,
             "create", ScriptFunction.class, Object[].class, int.class);
 
     private static final Call TO_NUMBER_FOR_EQ = CompilerConstants.staticCallNoLookup(JSType.class,
@@ -244,12 +242,12 @@
     private final DebugLogger log;
 
     /** From what size should we use spill instead of fields for JavaScript objects? */
-    private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
+    static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
 
     private final Set<String> emittedMethods = new HashSet<>();
 
     // Function Id -> ContinuationInfo. Used by compilation of rest-of function only.
-    private final Map<Integer, ContinuationInfo> fnIdToContinuationInfo = new HashMap<>();
+    private ContinuationInfo continuationInfo;
 
     private final Deque<Label> scopeEntryLabels = new ArrayDeque<>();
 
@@ -349,11 +347,20 @@
         final int flags = getScopeCallSiteFlags(symbol);
         if (isFastScope(symbol)) {
             // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope.
-            if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !isOptimisticOrRestOf()) {
-                method.loadCompilerConstant(SCOPE);
-                // As shared scope vars are only used in non-optimistic compilation, we switch from using TypeBounds to
+            if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !identNode.isOptimistic()) {
+                // As shared scope vars are only used with non-optimistic identifiers, we switch from using TypeBounds to
                 // just a single definitive type, resultBounds.widest.
-                loadSharedScopeVar(resultBounds.widest, symbol, flags);
+                new OptimisticOperation(identNode, TypeBounds.OBJECT) {
+                    @Override
+                    void loadStack() {
+                        method.loadCompilerConstant(SCOPE);
+                    }
+
+                    @Override
+                    void consumeStack() {
+                        loadSharedScopeVar(resultBounds.widest, symbol, flags);
+                    }
+                }.emit();
             } else {
                 new LoadFastScopeVar(identNode, resultBounds, flags).emit();
             }
@@ -384,10 +391,6 @@
         return continuationEntryPoints != null;
     }
 
-    private boolean isOptimisticOrRestOf() {
-        return useOptimisticTypes() || isRestOf();
-    }
-
     private boolean isCurrentContinuationEntryPoint(final int programPoint) {
         return isRestOf() && getCurrentContinuationEntryPoint() == programPoint;
     }
@@ -464,12 +467,8 @@
     }
 
     private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) {
-        assert !isOptimisticOrRestOf();
-        if (isFastScope(symbol)) {
-            method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol));
-        } else {
-            method.load(-1);
-        }
+        assert isFastScope(symbol);
+        method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol));
         return lc.getScopeGet(unit, symbol, valueType, flags).generateInvoke(method);
     }
 
@@ -1434,8 +1433,7 @@
         final Block currentBlock = lc.getCurrentBlock();
         final CodeGeneratorLexicalContext codegenLexicalContext = lc;
 
-        function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-
+        function.accept(new SimpleNodeVisitor() {
             private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
                 final Symbol symbol = identNode.getSymbol();
                 final boolean isFastScope = isFastScope(symbol);
@@ -1480,7 +1478,7 @@
                     }
                     @Override
                     void consumeStack() {
-                        dynamicCall(2 + argsCount, flags);
+                        dynamicCall(2 + argsCount, flags, ident.getName());
                     }
                 }.emit();
             }
@@ -1494,7 +1492,7 @@
                     int argsCount;
                     @Override
                     void loadStack() {
-                        /**
+                        /*
                          * We want to load 'eval' to check if it is indeed global builtin eval.
                          * If this eval call is inside a 'with' statement, dyn:getMethod|getProp|getElem
                          * would be generated if ident is a "isFunction". But, that would result in a
@@ -1538,7 +1536,7 @@
                     @Override
                     void consumeStack() {
                         // Ordinary call
-                        dynamicCall(2 + argsCount, flags);
+                        dynamicCall(2 + argsCount, flags, "eval");
                         method._goto(eval_done);
 
                         method.label(invoke_direct_eval);
@@ -1573,7 +1571,7 @@
                     } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD
                             || !isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD
                             || CodeGenerator.this.lc.inDynamicScope()
-                            || isOptimisticOrRestOf()) {
+                            || callNode.isOptimistic()) {
                         scopeCall(node, flags);
                     } else {
                         sharedScopeCall(node, flags);
@@ -1610,7 +1608,7 @@
                     }
                     @Override
                     void consumeStack() {
-                        dynamicCall(2 + argCount, flags);
+                        dynamicCall(2 + argCount, flags, node.toString(false));
                     }
                 }.emit();
 
@@ -1635,9 +1633,7 @@
 
                     @Override
                     void consumeStack() {
-                        final int flags = getCallSiteFlags();
-                        //assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
-                        dynamicCall(2 + argsCount, flags);
+                        dynamicCall(2 + argsCount, getCallSiteFlags(), null);
                     }
                 }.emit();
                 return false;
@@ -1666,8 +1662,7 @@
                     }
                     @Override
                     void consumeStack() {
-                        final int flags = getCallSiteFlags();
-                        dynamicCall(2 + argsCount, flags);
+                        dynamicCall(2 + argsCount, getCallSiteFlags(), node.toString(false));
                     }
                 }.emit();
                 return false;
@@ -1687,7 +1682,7 @@
                         @Override
                         void consumeStack() {
                             final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
-                            dynamicCall(2 + argsCount, flags);
+                            dynamicCall(2 + argsCount, flags, node.toString(false));
                         }
                 }.emit();
                 return false;
@@ -2073,8 +2068,6 @@
 
     @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
-        final int fnId = functionNode.getId();
-
         if (skipFunction(functionNode)) {
             // In case we are not generating code for the function, we must create or retrieve the function object and
             // load it on the stack here.
@@ -2112,9 +2105,9 @@
             method.begin();
 
             if (isRestOf()) {
-                final ContinuationInfo ci = new ContinuationInfo();
-                fnIdToContinuationInfo.put(fnId, ci);
-                method.gotoLoopStart(ci.getHandlerLabel());
+                assert continuationInfo == null;
+                continuationInfo = new ContinuationInfo();
+                method.gotoLoopStart(continuationInfo.getHandlerLabel());
             }
         }
 
@@ -2147,7 +2140,7 @@
                 markOptimistic = false;
             }
 
-            FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.BYTECODE_GENERATED);
+            FunctionNode newFunctionNode = functionNode;
             if (markOptimistic) {
                 newFunctionNode = newFunctionNode.setFlag(lc, FunctionNode.IS_DEOPTIMIZABLE);
             }
@@ -2240,73 +2233,33 @@
      *
      * @param arrayLiteralNode the array of contents
      * @param arrayType        the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT
-     *
-     * @return the method generator that was used
      */
-    private MethodEmitter loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
+    private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
         assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
 
-        final Expression[]    nodes    = arrayLiteralNode.getValue();
-        final Object          presets  = arrayLiteralNode.getPresets();
-        final int[]           postsets = arrayLiteralNode.getPostsets();
-        final Class<?>        type     = arrayType.getTypeClass();
-        final List<ArrayUnit> units    = arrayLiteralNode.getUnits();
+        final Expression[]     nodes    = arrayLiteralNode.getValue();
+        final Object           presets  = arrayLiteralNode.getPresets();
+        final int[]            postsets = arrayLiteralNode.getPostsets();
+        final List<Splittable.SplitRange> ranges   = arrayLiteralNode.getSplitRanges();
 
         loadConstant(presets);
 
         final Type elementType = arrayType.getElementType();
 
-        if (units != null) {
-            final MethodEmitter savedMethod     = method;
-            final FunctionNode  currentFunction = lc.getCurrentFunction();
-
-            for (final ArrayUnit arrayUnit : units) {
-                unit = lc.pushCompileUnit(arrayUnit.getCompileUnit());
-
-                final String className = unit.getUnitClassName();
-                assert unit != null;
-                final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
-                final String signature = methodDescriptor(type, ScriptFunction.class, Object.class, ScriptObject.class, type);
-
-                pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
-
-                method.setFunctionNode(currentFunction);
-                method.begin();
-
-                defineCommonSplitMethodParameters();
-                defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), arrayType);
-
-                // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
-                // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
-                final int arraySlot = fixScopeSlot(currentFunction, 3);
-
-                lc.enterSplitNode();
-
-                for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) {
-                    method.load(arrayType, arraySlot);
-                    storeElement(nodes, elementType, postsets[i]);
+        if (ranges != null) {
+
+            loadSplitLiteral(new SplitLiteralCreator() {
+                @Override
+                public void populateRange(final MethodEmitter method, final Type type, final int slot, final int start, final int end) {
+                    for (int i = start; i < end; i++) {
+                        method.load(type, slot);
+                        storeElement(nodes, elementType, postsets[i]);
+                    }
+                    method.load(type, slot);
                 }
-
-                method.load(arrayType, arraySlot);
-                method._return();
-                lc.exitSplitNode();
-                method.end();
-                lc.releaseSlots();
-                popMethodEmitter();
-
-                assert method == savedMethod;
-                method.loadCompilerConstant(CALLEE);
-                method.swap();
-                method.loadCompilerConstant(THIS);
-                method.swap();
-                method.loadCompilerConstant(SCOPE);
-                method.swap();
-                method.invokestatic(className, name, signature);
-
-                unit = lc.popCompileUnit(unit);
-            }
-
-            return method;
+            }, ranges, arrayType);
+
+            return;
         }
 
         if(postsets.length > 0) {
@@ -2318,7 +2271,6 @@
             }
             method.load(arrayType, arraySlot);
         }
-        return method;
     }
 
     private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
@@ -2508,7 +2460,7 @@
 
             @Override
             public Boolean get() {
-                value.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                value.accept(new SimpleNodeVisitor() {
                     @Override
                     public boolean enterFunctionNode(final FunctionNode functionNode) {
                         return false;
@@ -2543,6 +2495,7 @@
         final List<MapTuple<Expression>> tuples = new ArrayList<>();
         final List<PropertyNode> gettersSetters = new ArrayList<>();
         final int ccp = getCurrentContinuationEntryPoint();
+        final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();
 
         Expression protoNode = null;
         boolean restOfProperty = false;
@@ -2589,7 +2542,13 @@
                     loadExpressionAsType(node, type);
                 }};
         }
-        oc.makeObject(method);
+
+        if (ranges != null) {
+            oc.createObject(method);
+            loadSplitLiteral(oc, ranges, Type.typeFor(oc.getAllocatorClass()));
+        } else {
+            oc.makeObject(method);
+        }
 
         //if this is a rest of method and our continuation point was found as one of the values
         //in the properties above, we need to reset the map to oc.getMap() in the continuation
@@ -2839,7 +2798,7 @@
             boolean contains;
             @Override
             public Boolean get() {
-                rootExpr.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                rootExpr.accept(new SimpleNodeVisitor() {
                     @Override
                     public boolean enterFunctionNode(final FunctionNode functionNode) {
                         return false;
@@ -2905,6 +2864,54 @@
         method.onLocalStore(type, slot);
     }
 
+    private void loadSplitLiteral(final SplitLiteralCreator creator, final List<Splittable.SplitRange> ranges, final Type literalType) {
+        assert ranges != null;
+
+        // final Type literalType = Type.typeFor(literalClass);
+        final MethodEmitter savedMethod     = method;
+        final FunctionNode  currentFunction = lc.getCurrentFunction();
+
+        for (final Splittable.SplitRange splitRange : ranges) {
+            unit = lc.pushCompileUnit(splitRange.getCompileUnit());
+
+            assert unit != null;
+            final String className = unit.getUnitClassName();
+            final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
+            final Class<?> clazz   = literalType.getTypeClass();
+            final String signature = methodDescriptor(clazz, ScriptFunction.class, Object.class, ScriptObject.class, clazz);
+
+            pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
+
+            method.setFunctionNode(currentFunction);
+            method.begin();
+
+            defineCommonSplitMethodParameters();
+            defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), literalType);
+
+            // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
+            // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
+            final int literalSlot = fixScopeSlot(currentFunction, 3);
+
+            lc.enterSplitNode();
+
+            creator.populateRange(method, literalType, literalSlot, splitRange.getLow(), splitRange.getHigh());
+
+            method._return();
+            lc.exitSplitNode();
+            method.end();
+            lc.releaseSlots();
+            popMethodEmitter();
+
+            assert method == savedMethod;
+            method.loadCompilerConstant(CALLEE).swap();
+            method.loadCompilerConstant(THIS).swap();
+            method.loadCompilerConstant(SCOPE).swap();
+            method.invokestatic(className, name, signature);
+
+            unit = lc.popCompileUnit(unit);
+        }
+    }
+
     private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) {
         // TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method)
         final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
@@ -3707,10 +3714,11 @@
         final CallNode callNode = (CallNode)unaryNode.getExpression();
         final List<Expression> args   = callNode.getArgs();
 
+        final Expression func = callNode.getFunction();
         // Load function reference.
-        loadExpressionAsObject(callNode.getFunction()); // must detect type error
-
-        method.dynamicNew(1 + loadArgs(args), getCallSiteFlags());
+        loadExpressionAsObject(func); // must detect type error
+
+        method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(), func.toString(false));
     }
 
     private void loadNOT(final UnaryNode unaryNode) {
@@ -4333,12 +4341,12 @@
         }
 
         private void prologue() {
-            /**
+            /*
              * This loads the parts of the target, e.g base and index. they are kept
              * on the stack throughout the store and used at the end to execute it
              */
 
-            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            target.accept(new SimpleNodeVisitor() {
                 @Override
                 public boolean enterIdentNode(final IdentNode node) {
                     if (node.getSymbol().isScope()) {
@@ -4437,7 +4445,7 @@
              * need to do a conversion on non-equivalent types exists, but is
              * very rare. See for example test/script/basic/access-specializer.js
              */
-            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            target.accept(new SimpleNodeVisitor() {
                 @Override
                 protected boolean enterDefault(final Node node) {
                     throw new AssertionError("Unexpected node " + node + " in store epilogue");
@@ -4801,7 +4809,7 @@
          * conversion has no side effects.
          * @param name the name of the property being get
          * @param flags call site flags
-         * @param isMethod whether we're preferrably retrieving a function
+         * @param isMethod whether we're preferably retrieving a function
          * @return the current method emitter
          */
         MethodEmitter dynamicGet(final String name, final int flags, final boolean isMethod, final boolean isIndex) {
@@ -4818,11 +4826,11 @@
             return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
         }
 
-        MethodEmitter dynamicCall(final int argCount, final int flags) {
+        MethodEmitter dynamicCall(final int argCount, final int flags, final String msg) {
             if (isOptimistic) {
-                return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags));
-            }
-            return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags));
+                return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags), msg);
+            }
+            return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags), msg);
         }
 
         int getOptimisticFlags(final int flags) {
@@ -5233,7 +5241,7 @@
         private Type returnValueType;
         // If we are in the middle of an object literal initialization, we need to update the map
         private PropertyMap objectLiteralMap;
-        // Object literal stack depth for object literal - not necessarly top if property is a tree
+        // Object literal stack depth for object literal - not necessarily top if property is a tree
         private int objectLiteralStackDepth = -1;
         // The line number at the continuation point
         private int lineNumber;
@@ -5310,7 +5318,7 @@
     }
 
     private ContinuationInfo getContinuationInfo() {
-        return fnIdToContinuationInfo.get(lc.getCurrentFunction().getId());
+        return continuationInfo;
     }
 
     private void generateContinuationHandler() {
@@ -5398,7 +5406,7 @@
                 method.load(lvarTypes.get(slot), slot);
                 method.convert(stackTypes[i]);
                 // stack: s0=object literal being initialized
-                // change map of s0 so that the property we are initilizing when we failed
+                // change map of s0 so that the property we are initializing when we failed
                 // is now ci.returnValueType
                 if (i == objectLiteralStackDepth) {
                     method.dup();
@@ -5466,4 +5474,21 @@
             method.uncheckedGoto(targetCatchLabel);
         }
     }
+
+    /**
+     * Interface implemented by object creators that support splitting over multiple methods.
+     */
+    interface SplitLiteralCreator {
+        /**
+         * Generate code to populate a range of the literal object. A reference to the object
+         * should be left on the stack when the method terminates.
+         *
+         * @param method the method emitter
+         * @param type the type of the literal object
+         * @param slot the local slot containing the literal object
+         * @param start the start index (inclusive)
+         * @param end the end index (exclusive)
+         */
+        void populateRange(MethodEmitter method, Type type, int slot, int start, int end);
+    }
 }
--- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Oct 29 17:22:12 2015 -0700
@@ -25,37 +25,24 @@
 
 package jdk.nashorn.internal.codegen;
 
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BUILTINS_TRANSFORMED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_GENERATED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_INSTALLED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.CONSTANT_FOLDED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.INITIALIZED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOCAL_VARIABLE_TYPES_CALCULATED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOWERED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.OPTIMISTIC_TYPES_ASSIGNED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.PARSED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SCOPE_DEPTHS_COMPUTED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SYMBOLS_ASSIGNED;
 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
 
 import java.io.PrintWriter;
-import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 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.Block;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.debug.ASTWriter;
 import jdk.nashorn.internal.ir.debug.PrintVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.runtime.CodeInstaller;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
@@ -65,15 +52,9 @@
  * A compilation phase is a step in the processes of turning a JavaScript
  * FunctionNode into bytecode. It has an optional return value.
  */
-enum CompilationPhase {
-    /**
-     * Constant folding pass Simple constant folding that will make elementary
-     * constructs go away
-     */
-    CONSTANT_FOLDING_PHASE(
-            EnumSet.of(
-                INITIALIZED,
-                PARSED)) {
+abstract class CompilationPhase {
+
+    private static final class ConstantFoldingPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new FoldConstants(compiler));
@@ -83,20 +64,15 @@
         public String toString() {
             return "'Constant Folding'";
         }
-    },
+    }
 
     /**
-     * Lower (Control flow pass) Finalizes the control flow. Clones blocks for
-     * finally constructs and similar things. Establishes termination criteria
-     * for nodes Guarantee return instructions to method making sure control
-     * flow cannot fall off the end. Replacing high level nodes with lower such
-     * as runtime nodes where applicable.
+     * Constant folding pass Simple constant folding that will make elementary
+     * constructs go away
      */
-    LOWERING_PHASE(
-            EnumSet.of(
-                INITIALIZED,
-                PARSED,
-                CONSTANT_FOLDED)) {
+    static final CompilationPhase CONSTANT_FOLDING_PHASE = new ConstantFoldingPhase();
+
+    private static final class LoweringPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new Lower(compiler));
@@ -106,42 +82,35 @@
         public String toString() {
             return "'Control Flow Lowering'";
         }
-    },
+    }
 
     /**
-     * Phase used only when doing optimistic code generation. It assigns all potentially
-     * optimistic ops a program point so that an UnwarrantedException knows from where
-     * a guess went wrong when creating the continuation to roll back this execution
+     * Lower (Control flow pass) Finalizes the control flow. Clones blocks for
+     * finally constructs and similar things. Establishes termination criteria
+     * for nodes Guarantee return instructions to method making sure control
+     * flow cannot fall off the end. Replacing high level nodes with lower such
+     * as runtime nodes where applicable.
      */
-    TRANSFORM_BUILTINS_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED)) {
-        //we only do this if we have a param type map, otherwise this is not a specialized recompile
+    static final CompilationPhase LOWERING_PHASE = new LoweringPhase();
+
+    private static final class ApplySpecializationPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
-            return setStates(transformFunction(fn, new ApplySpecialization(compiler)), BUILTINS_TRANSFORMED);
+            return transformFunction(fn, new ApplySpecialization(compiler));
         }
 
         @Override
         public String toString() {
             return "'Builtin Replacement'";
         }
-    },
+    };
 
     /**
-     * Splitter Split the AST into several compile units based on a heuristic size calculation.
-     * Split IR can lead to scope information being changed.
+     * Phase used to transform Function.prototype.apply.
      */
-    SPLITTING_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED)) {
+    static final CompilationPhase APPLY_SPECIALIZATION_PHASE = new ApplySpecializationPhase();
+
+    private static final class SplittingPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final CompileUnit  outermostCompileUnit = compiler.addCompileUnit(0L);
@@ -149,7 +118,7 @@
             FunctionNode newFunctionNode;
 
             //ensure elementTypes, postsets and presets exist for splitter and arraynodes
-            newFunctionNode = transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            newFunctionNode = transformFunction(fn, new SimpleNodeVisitor() {
                 @Override
                 public LiteralNode<?> leaveLiteralNode(final LiteralNode<?> literalNode) {
                     return literalNode.initialize(lc);
@@ -168,16 +137,15 @@
         public String toString() {
             return "'Code Splitting'";
         }
-    },
+    };
 
-    PROGRAM_POINT_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT)) {
+    /**
+     * Splitter Split the AST into several compile units based on a heuristic size calculation.
+     * Split IR can lead to scope information being changed.
+     */
+    static final CompilationPhase SPLITTING_PHASE = new SplittingPhase();
+
+    private static final class ProgramPointPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new ProgramPoints());
@@ -187,43 +155,34 @@
         public String toString() {
             return "'Program Point Calculation'";
         }
-    },
+    };
 
-    SERIALIZE_SPLIT_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT)) {
+    static final CompilationPhase PROGRAM_POINT_PHASE = new ProgramPointPhase();
+
+    private static final class CacheAstPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
-            return transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
-                @Override
-                public boolean enterFunctionNode(final FunctionNode functionNode) {
-                    if (functionNode.isSplit()) {
-                        compiler.serializeAst(functionNode);
-                    }
-                    return true;
-                }
-            });
+            if (!compiler.isOnDemandCompilation()) {
+                // Only do this on initial preprocessing of the source code. For on-demand compilations from
+                // source, FindScopeDepths#leaveFunctionNode() calls data.setCachedAst() for the sole function
+                // being compiled.
+                transformFunction(fn, new CacheAst(compiler));
+            }
+            // NOTE: we're returning the original fn as we have destructively modified the cached functions by
+            // removing their bodies. This step is associating FunctionNode objects with
+            // RecompilableScriptFunctionData; it's not really modifying the AST.
+            return fn;
         }
 
         @Override
         public String toString() {
-            return "'Serialize Split Functions'";
+            return "'Cache ASTs'";
         }
-    },
+    };
 
-    SYMBOL_ASSIGNMENT_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT)) {
+    static final CompilationPhase CACHE_AST_PHASE = new CacheAstPhase();
+
+    private static final class SymbolAssignmentPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new AssignSymbols(compiler));
@@ -233,17 +192,11 @@
         public String toString() {
             return "'Symbol Assignment'";
         }
-    },
+    };
 
-    SCOPE_DEPTH_COMPUTATION_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT,
-                    SYMBOLS_ASSIGNED)) {
+    static final CompilationPhase SYMBOL_ASSIGNMENT_PHASE = new SymbolAssignmentPhase();
+
+    private static final class ScopeDepthComputationPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new FindScopeDepths(compiler));
@@ -253,43 +206,66 @@
         public String toString() {
             return "'Scope Depth Computation'";
         }
-    },
+    };
+
+    static final CompilationPhase SCOPE_DEPTH_COMPUTATION_PHASE = new ScopeDepthComputationPhase();
 
-    OPTIMISTIC_TYPE_ASSIGNMENT_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT,
-                    SYMBOLS_ASSIGNED,
-                    SCOPE_DEPTHS_COMPUTED)) {
+    private static final class DeclareLocalSymbolsPhase extends CompilationPhase {
+        @Override
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            // 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()) {
+                fn.getBody().accept(new SimpleNodeVisitor() {
+                    @Override
+                    public boolean enterFunctionNode(final FunctionNode functionNode) {
+                        // 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.
+                        return false;
+                    };
+                    @Override
+                    public boolean enterBlock(final Block block) {
+                        for (final Symbol symbol: block.getSymbols()) {
+                            if (!symbol.isScope()) {
+                                compiler.declareLocalSymbol(symbol.getName());
+                            }
+                        }
+                        return true;
+                    };
+                });
+            }
+            return fn;
+        }
+
+        @Override
+        public String toString() {
+            return "'Local Symbols Declaration'";
+        }
+    };
+
+    static final CompilationPhase DECLARE_LOCAL_SYMBOLS_PHASE = new DeclareLocalSymbolsPhase();
+
+    private static final class OptimisticTypeAssignmentPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             if (compiler.useOptimisticTypes()) {
                 return transformFunction(fn, new OptimisticTypesCalculator(compiler));
             }
-            return setStates(fn, OPTIMISTIC_TYPES_ASSIGNED);
+            return fn;
         }
 
         @Override
         public String toString() {
             return "'Optimistic Type Assignment'";
         }
-    },
+    }
 
-    LOCAL_VARIABLE_TYPE_CALCULATION_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT,
-                    SYMBOLS_ASSIGNED,
-                    SCOPE_DEPTHS_COMPUTED,
-                    OPTIMISTIC_TYPES_ASSIGNED)) {
+    static final CompilationPhase OPTIMISTIC_TYPE_ASSIGNMENT_PHASE = new OptimisticTypeAssignmentPhase();
+
+    private static final class LocalVariableTypeCalculationPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final FunctionNode newFunctionNode = transformFunction(fn, new LocalVariableTypesCalculator(compiler));
@@ -314,25 +290,11 @@
         public String toString() {
             return "'Local Variable Type Calculation'";
         }
-    },
-
+    };
 
-    /**
-     * Reuse compile units, if they are already present. We are using the same compiler
-     * to recompile stuff
-     */
-    REUSE_COMPILE_UNITS_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT,
-                    SYMBOLS_ASSIGNED,
-                    SCOPE_DEPTHS_COMPUTED,
-                    OPTIMISTIC_TYPES_ASSIGNED,
-                    LOCAL_VARIABLE_TYPES_CALCULATED)) {
+    static final CompilationPhase LOCAL_VARIABLE_TYPE_CALCULATION_PHASE = new LocalVariableTypeCalculationPhase();
+
+    private static final class ReuseCompileUnitsPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             assert phases.isRestOfCompilation() : "reuse compile units currently only used for Rest-Of methods";
@@ -380,16 +342,15 @@
         public String toString() {
             return "'Reuse Compile Units'";
         }
-    },
+    }
 
-    REINITIALIZE_SERIALIZED(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT)) {
+    /**
+     * Reuse compile units, if they are already present. We are using the same compiler
+     * to recompile stuff
+     */
+    static final CompilationPhase REUSE_COMPILE_UNITS_PHASE = new ReuseCompileUnitsPhase();
+
+    private static final class ReinitializeCachedPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final Set<CompileUnit> unitSet = CompileUnit.createCompileUnitSet();
@@ -430,28 +391,13 @@
 
         @Override
         public String toString() {
-            return "'Deserialize'";
+            return "'Reinitialize cached'";
         }
-    },
+    }
 
-    /**
-     * Bytecode generation:
-     *
-     * Generate the byte code class(es) resulting from the compiled FunctionNode
-     */
-    BYTECODE_GENERATION_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT,
-                    SYMBOLS_ASSIGNED,
-                    SCOPE_DEPTHS_COMPUTED,
-                    OPTIMISTIC_TYPES_ASSIGNED,
-                    LOCAL_VARIABLE_TYPES_CALCULATED)) {
+    static final CompilationPhase REINITIALIZE_CACHED = new ReinitializeCachedPhase();
 
+    private static final class BytecodeGenerationPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final ScriptEnvironment senv = compiler.getScriptEnvironment();
@@ -469,7 +415,7 @@
             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().
-                newFunctionNode = transformFunction(newFunctionNode, codegen).setState(null, BYTECODE_GENERATED);
+                newFunctionNode = transformFunction(newFunctionNode, codegen);
                 codegen.generateScopeCalls();
             } catch (final VerifyError e) {
                 if (senv._verify_code || senv._print_code) {
@@ -517,22 +463,16 @@
         public String toString() {
             return "'Bytecode Generation'";
         }
-    },
+    }
 
-     INSTALL_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT,
-                    SYMBOLS_ASSIGNED,
-                    SCOPE_DEPTHS_COMPUTED,
-                    OPTIMISTIC_TYPES_ASSIGNED,
-                    LOCAL_VARIABLE_TYPES_CALCULATED,
-                    BYTECODE_GENERATED)) {
+    /**
+     * Bytecode generation:
+     *
+     * Generate the byte code class(es) resulting from the compiled FunctionNode
+     */
+    static final CompilationPhase BYTECODE_GENERATION_PHASE = new BytecodeGenerationPhase();
 
+    private static final class InstallPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final DebugLogger log = compiler.getLogger();
@@ -543,8 +483,8 @@
             Class<?> rootClass = null;
             long length = 0L;
 
-            final CodeInstaller<ScriptEnvironment> codeInstaller = compiler.getCodeInstaller();
-            final Map<String, byte[]>              bytecode      = compiler.getBytecode();
+            final CodeInstaller       codeInstaller = compiler.getCodeInstaller();
+            final Map<String, byte[]> bytecode      = compiler.getBytecode();
 
             for (final Entry<String, byte[]> entry : bytecode.entrySet()) {
                 final String className = entry.getKey();
@@ -600,18 +540,16 @@
                 log.fine(sb.toString());
             }
 
-            return setStates(fn.setRootClass(null, rootClass), BYTECODE_INSTALLED);
+            return fn.setRootClass(null, rootClass);
         }
 
         @Override
         public String toString() {
             return "'Class Installation'";
         }
-
-     };
+    }
 
-    /** pre conditions required for function node to which this transform is to be applied */
-    private final EnumSet<CompilationState> pre;
+    static final CompilationPhase INSTALL_PHASE = new InstallPhase();
 
     /** start time of transform - used for timing, see {@link jdk.nashorn.internal.runtime.Timing} */
     private long startTime;
@@ -622,21 +560,7 @@
     /** boolean that is true upon transform completion */
     private boolean isFinished;
 
-    private CompilationPhase(final EnumSet<CompilationState> pre) {
-        this.pre = pre;
-    }
-
-    private static FunctionNode setStates(final FunctionNode functionNode, final CompilationState state) {
-        if (!AssertsEnabled.assertsEnabled()) {
-            return functionNode;
-        }
-        return transformFunction(functionNode, new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            @Override
-            public Node leaveFunctionNode(final FunctionNode fn) {
-                return fn.setState(lc, state);
-           }
-        });
-    }
+    private CompilationPhase() {}
 
     /**
      * Start a compilation phase
@@ -646,23 +570,7 @@
      */
     protected FunctionNode begin(final Compiler compiler, final FunctionNode functionNode) {
         compiler.getLogger().indent();
-
-        assert pre != null;
-
-        if (!functionNode.hasState(pre)) {
-            final StringBuilder sb = new StringBuilder("Compilation phase ");
-            sb.append(this).
-                append(" is not applicable to ").
-                append(quote(functionNode.getName())).
-                append("\n\tFunctionNode state = ").
-                append(functionNode.getState()).
-                append("\n\tRequired state     = ").
-                append(this.pre);
-
-            throw new CompilationException(sb.toString());
-         }
-
-         startTime = System.nanoTime();
+        startTime = System.nanoTime();
 
          return functionNode;
      }
@@ -697,7 +605,7 @@
     abstract FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode functionNode) throws CompilationException;
 
     /**
-     * Apply a transform to a function node, returning the transfored function node. If the transform is not
+     * Apply a transform to a function node, returning the transformed function node. If the transform is not
      * applicable, an exception is thrown. Every transform requires the function to have a certain number of
      * states to operate. It can have more states set, but not fewer. The state list, i.e. the constructor
      * arguments to any of the CompilationPhase enum entries, is a set of REQUIRED states.
--- a/src/jdk/nashorn/internal/codegen/Compiler.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Thu Oct 29 17:22:12 2015 -0700
@@ -101,7 +101,7 @@
 
     private final ConstantData constantData;
 
-    private final CodeInstaller<ScriptEnvironment> installer;
+    private final CodeInstaller installer;
 
     /** logger for compiler, trampolines and related code generation events
      *  that affect classes */
@@ -160,42 +160,40 @@
      */
     private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32;
 
-    private final Map<Integer, byte[]> serializedAsts = new HashMap<>();
-
     /**
      * Compilation phases that a compilation goes through
      */
     public static class CompilationPhases implements Iterable<CompilationPhase> {
 
         /**
-         * Singleton that describes compilation up to the phase where a function can be serialized.
+         * Singleton that describes compilation up to the phase where a function can be cached.
          */
-        private final static CompilationPhases COMPILE_UPTO_SERIALIZABLE = new CompilationPhases(
+        private final static CompilationPhases COMPILE_UPTO_CACHED = new CompilationPhases(
                 "Common initial phases",
                 CompilationPhase.CONSTANT_FOLDING_PHASE,
                 CompilationPhase.LOWERING_PHASE,
-                CompilationPhase.TRANSFORM_BUILTINS_PHASE,
+                CompilationPhase.APPLY_SPECIALIZATION_PHASE,
                 CompilationPhase.SPLITTING_PHASE,
                 CompilationPhase.PROGRAM_POINT_PHASE,
-                CompilationPhase.SERIALIZE_SPLIT_PHASE
+                CompilationPhase.SYMBOL_ASSIGNMENT_PHASE,
+                CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
+                CompilationPhase.CACHE_AST_PHASE
                 );
 
-        private final static CompilationPhases COMPILE_SERIALIZABLE_UPTO_BYTECODE = new CompilationPhases(
+        private final static CompilationPhases COMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases(
                 "After common phases, before bytecode generator",
-                CompilationPhase.SYMBOL_ASSIGNMENT_PHASE,
-                CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
                 CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE,
                 CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE
                 );
 
         /**
-         * Singleton that describes additional steps to be taken after deserializing, all the way up to (but not
-         * including) generating and installing code.
+         * Singleton that describes additional steps to be taken after retrieving a cached function, all the
+         * way up to (but not including) generating and installing code.
          */
-        public final static CompilationPhases RECOMPILE_SERIALIZED_UPTO_BYTECODE = new CompilationPhases(
-                "Recompile serialized function up to bytecode",
-                CompilationPhase.REINITIALIZE_SERIALIZED,
-                COMPILE_SERIALIZABLE_UPTO_BYTECODE
+        public final static CompilationPhases RECOMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases(
+                "Recompile cached function up to bytecode",
+                CompilationPhase.REINITIALIZE_CACHED,
+                COMPILE_CACHED_UPTO_BYTECODE
                 );
 
         /**
@@ -211,8 +209,8 @@
         /** Singleton that describes compilation up to the CodeGenerator, but not actually generating code */
         public final static CompilationPhases COMPILE_UPTO_BYTECODE = new CompilationPhases(
                 "Compile upto bytecode",
-                COMPILE_UPTO_SERIALIZABLE,
-                COMPILE_SERIALIZABLE_UPTO_BYTECODE);
+                COMPILE_UPTO_CACHED,
+                COMPILE_CACHED_UPTO_BYTECODE);
 
         /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */
         public final static CompilationPhases COMPILE_ALL_NO_INSTALL = new CompilationPhases(
@@ -227,9 +225,9 @@
                 GENERATE_BYTECODE_AND_INSTALL);
 
         /** Singleton that describes a full compilation - this includes code installation - from serialized state*/
-        public final static CompilationPhases COMPILE_ALL_SERIALIZED = new CompilationPhases(
+        public final static CompilationPhases COMPILE_ALL_CACHED = new CompilationPhases(
                 "Eager compilation from serializaed state",
-                RECOMPILE_SERIALIZED_UPTO_BYTECODE,
+                RECOMPILE_CACHED_UPTO_BYTECODE,
                 GENERATE_BYTECODE_AND_INSTALL);
 
         /**
@@ -248,9 +246,9 @@
                 GENERATE_BYTECODE_AND_INSTALL_RESTOF);
 
         /** Compile from serialized for a rest of method */
-        public final static CompilationPhases COMPILE_SERIALIZED_RESTOF = new CompilationPhases(
+        public final static CompilationPhases COMPILE_CACHED_RESTOF = new CompilationPhases(
                 "Compile serialized, rest of",
-                RECOMPILE_SERIALIZED_UPTO_BYTECODE,
+                RECOMPILE_CACHED_UPTO_BYTECODE,
                 GENERATE_BYTECODE_AND_INSTALL_RESTOF);
 
         private final List<CompilationPhase> phases;
@@ -313,7 +311,7 @@
         }
 
         boolean isRestOfCompilation() {
-            return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_SERIALIZED_RESTOF;
+            return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_CACHED_RESTOF;
         }
 
         String getDesc() {
@@ -353,47 +351,83 @@
     private static final AtomicInteger COMPILATION_ID = new AtomicInteger(0);
 
     /**
-     * Constructor
+     * Creates a new compiler instance for initial compilation of a script.
      *
-     * @param context   context
-     * @param env       script environment
      * @param installer code installer
      * @param source    source to compile
      * @param errors    error manager
      * @param isStrict  is this a strict compilation
+     * @return a new compiler
      */
-    public Compiler(
-            final Context context,
-            final ScriptEnvironment env,
-            final CodeInstaller<ScriptEnvironment> installer,
+    public static Compiler forInitialCompilation(
+            final CodeInstaller installer,
             final Source source,
             final ErrorManager errors,
             final boolean isStrict) {
-        this(context, env, installer, source, errors, isStrict, false, null, null, null, null, null, null);
+        return new Compiler(installer.getContext(), installer, source, errors, isStrict);
     }
 
     /**
-     * Constructor
+     * Creates a compiler without a code installer. It can only be used to compile code, not install the
+     * generated classes and as such it is useful only for implementation of {@code --compile-only} command
+     * line option.
+     * @param context  the current context
+     * @param source   source to compile
+     * @param isStrict is this a strict compilation
+     * @return a new compiler
+     */
+    public static Compiler forNoInstallerCompilation(
+            final Context context,
+            final Source source,
+            final boolean isStrict) {
+        return new Compiler(context, null, source, context.getErrorManager(), isStrict);
+    }
+
+    /**
+     * Creates a compiler for an on-demand compilation job.
      *
-     * @param context                  context
-     * @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
      * @param types                    parameter and return value type information, if any is known
      * @param invalidatedProgramPoints invalidated program points for recompilation
      * @param typeInformationFile      descriptor of the location where type information is persisted
      * @param continuationEntryPoints  continuation entry points for restof method
      * @param runtimeScope             runtime scope for recompilation type lookup in {@code TypeEvaluator}
+     * @return a new compiler
      */
-    @SuppressWarnings("unused")
-    public Compiler(
+    public static Compiler forOnDemandCompilation(
+            final CodeInstaller installer,
+            final Source source,
+            final boolean isStrict,
+            final RecompilableScriptFunctionData compiledFunction,
+            final TypeMap types,
+            final Map<Integer, Type> invalidatedProgramPoints,
+            final Object typeInformationFile,
+            final int[] continuationEntryPoints,
+            final ScriptObject runtimeScope) {
+        final Context context = installer.getContext();
+        return new Compiler(context, installer, source, context.getErrorManager(), isStrict, true,
+                compiledFunction, types, invalidatedProgramPoints, typeInformationFile,
+                continuationEntryPoints, runtimeScope);
+    }
+
+    /**
+     * Convenience constructor for non on-demand compiler instances.
+     */
+    private Compiler(
             final Context context,
-            final ScriptEnvironment env,
-            final CodeInstaller<ScriptEnvironment> installer,
+            final CodeInstaller installer,
+            final Source source,
+            final ErrorManager errors,
+            final boolean isStrict) {
+        this(context, installer, source, errors, isStrict, false, null, null, null, null, null, null);
+    }
+
+    private Compiler(
+            final Context context,
+            final CodeInstaller installer,
             final Source source,
             final ErrorManager errors,
             final boolean isStrict,
@@ -405,7 +439,7 @@
             final int[] continuationEntryPoints,
             final ScriptObject runtimeScope) {
         this.context                  = context;
-        this.env                      = env;
+        this.env                      = context.getEnv();
         this.installer                = installer;
         this.constantData             = new ConstantData();
         this.compileUnits             = CompileUnit.createCompileUnitSet();
@@ -427,7 +461,7 @@
         this.optimistic = env._optimistic_types;
     }
 
-    private static String safeSourceName(final ScriptEnvironment env, final CodeInstaller<ScriptEnvironment> installer, final Source source) {
+    private String safeSourceName() {
         String baseName = new File(source.getName()).getName();
 
         final int index = baseName.lastIndexOf(".js");
@@ -486,7 +520,7 @@
             sb.append('$');
         }
 
-        sb.append(Compiler.safeSourceName(env, installer, source));
+        sb.append(safeSourceName());
 
         return sb.toString();
     }
@@ -607,7 +641,7 @@
             newFunctionNode.uniqueName(reservedName);
         }
 
-        final boolean info = log.levelFinerThanOrEqual(Level.INFO);
+        final boolean info = log.isLoggable(Level.INFO);
 
         final DebugLogger timeLogger = env.isTimingEnabled() ? env._timing.getLogger() : null;
 
@@ -644,8 +678,8 @@
         if (info) {
             final StringBuilder sb = new StringBuilder("<< Finished compile job for ");
             sb.append(newFunctionNode.getSource()).
-                append(':').
-                append(quote(newFunctionNode.getName()));
+            append(':').
+            append(quote(newFunctionNode.getName()));
 
             if (time > 0L && timeLogger != null) {
                 assert env.isTimingEnabled();
@@ -685,7 +719,7 @@
         return constantData;
     }
 
-    CodeInstaller<ScriptEnvironment> getCodeInstaller() {
+    CodeInstaller getCodeInstaller() {
         return installer;
     }
 
@@ -713,7 +747,7 @@
         if (cacheKey != null && env._persistent_cache) {
             // If this is an on-demand compilation create a function initializer for the function being compiled.
             // Otherwise use function initializer map generated by codegen.
-            Map<Integer, FunctionInitializer> initializers = new HashMap<>();
+            final Map<Integer, FunctionInitializer> initializers = new HashMap<>();
             if (isOnDemandCompilation()) {
                 initializers.put(functionNode.getId(), new FunctionInitializer(functionNode, getInvalidatedProgramPoints()));
             } else {
@@ -766,14 +800,6 @@
         compileUnits.addAll(newUnits);
     }
 
-    void serializeAst(final FunctionNode fn) {
-        serializedAsts.put(fn.getId(), AstSerializer.serialize(fn));
-    }
-
-    byte[] removeSerializedAst(final int fnId) {
-        return serializedAsts.remove(fnId);
-    }
-
     CompileUnit findUnit(final long weight) {
         for (final CompileUnit unit : compileUnits) {
             if (unit.canHold(weight)) {
@@ -829,9 +855,9 @@
         final long                        totalSize = osc.calculateObjectSize(functionNode);
 
         sb.append(phaseName).
-            append(" Total size = ").
-            append(totalSize / 1024 / 1024).
-            append("MB");
+        append(" Total size = ").
+        append(totalSize / 1024 / 1024).
+        append("MB");
         log.info(sb);
 
         Collections.sort(list, new Comparator<ClassHistogramElement>() {
--- a/src/jdk/nashorn/internal/codegen/CompilerConstants.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/CompilerConstants.java	Thu Oct 29 17:22:12 2015 -0700
@@ -192,7 +192,7 @@
     private static Set<String> symbolNames;
 
     /**
-     * Prefix used for internal methods generated in script clases.
+     * Prefix used for internal methods generated in script classes.
      */
     private static final String INTERNAL_METHOD_PREFIX = ":";
 
@@ -225,7 +225,7 @@
     }
 
     /**
-     * Check whether a name is that of a reserved compiler constnat
+     * Check whether a name is that of a reserved compiler constant
      * @param name name
      * @return true if compiler constant name
      */
--- a/src/jdk/nashorn/internal/codegen/ConstantData.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/ConstantData.java	Thu Oct 29 17:22:12 2015 -0700
@@ -30,6 +30,8 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+
 import jdk.nashorn.internal.runtime.PropertyMap;
 
 /**
@@ -120,7 +122,7 @@
         private final int hashCode;
 
         public PropertyMapWrapper(final PropertyMap map) {
-            this.hashCode = Arrays.hashCode(map.getProperties());
+            this.hashCode = Arrays.hashCode(map.getProperties()) + 31 * Objects.hashCode(map.getClassName());
             this.propertyMap = map;
         }
 
@@ -131,8 +133,13 @@
 
         @Override
         public boolean equals(final Object other) {
-            return other instanceof PropertyMapWrapper &&
-                    Arrays.equals(propertyMap.getProperties(), ((PropertyMapWrapper) other).propertyMap.getProperties());
+            if (!(other instanceof PropertyMapWrapper)) {
+                return false;
+            }
+            final PropertyMap otherMap = ((PropertyMapWrapper) other).propertyMap;
+            return propertyMap == otherMap
+                    || (Arrays.equals(propertyMap.getProperties(), otherMap.getProperties())
+                        && Objects.equals(propertyMap.getClassName(), otherMap.getClassName()));
         }
     }
 
--- a/src/jdk/nashorn/internal/codegen/DumpBytecode.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/DumpBytecode.java	Thu Oct 29 17:22:12 2015 -0700
@@ -88,7 +88,7 @@
             }
 
 
-            // should code be dumped to disk - only valid in compile_only mode?
+            // should code be dumped to disk
             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	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -34,7 +34,6 @@
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 
-import java.util.Iterator;
 import java.util.List;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.Symbol;
@@ -91,27 +90,20 @@
         findClass();
     }
 
-    /**
-     * Construct an object.
-     *
-     * @param method the method emitter
-     */
     @Override
-    protected void makeObject(final MethodEmitter method) {
+    public void createObject(final MethodEmitter method) {
         makeMap();
         final String className = getClassName();
-        try {
-            // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects,
-            // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type
-            // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the
-            // exact type information is needed for generating continuations in rest-of methods. If we didn't do this,
-            // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the
-            // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and
-            // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification.
-            method._new(Context.forStructureClass(className.replace('/', '.'))).dup();
-        } catch (final ClassNotFoundException e) {
-            throw new AssertionError(e);
-        }
+        // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects,
+        // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type
+        // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the
+        // exact type information is needed for generating continuations in rest-of methods. If we didn't do this,
+        // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the
+        // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and
+        // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification.
+        assert fieldObjectClass != null;
+        method._new(fieldObjectClass).dup();
+
         loadMap(method); //load the map
 
         if (isScope()) {
@@ -126,14 +118,14 @@
         } else {
             method.invoke(constructorNoLookup(className, PropertyMap.class));
         }
+    }
 
-        helpOptimisticRecognizeDuplicateIdentity(method);
-
+    @Override
+    public void populateRange(final MethodEmitter method, final Type objectType, final int objectSlot, final int start, final int end) {
+        method.load(objectType, objectSlot);
         // Set values.
-        final Iterator<MapTuple<T>> iter = tuples.iterator();
-
-        while (iter.hasNext()) {
-            final MapTuple<T> tuple = iter.next();
+        for (int i = start; i < end; i++) {
+            final MapTuple<T> tuple = tuples.get(i);
             //we only load when we have both symbols and values (which can be == the symbol)
             //if we didn't load, we need an array property
             if (tuple.symbol != null && tuple.value != null) {
@@ -212,6 +204,11 @@
         }
     }
 
+    @Override
+    protected Class<? extends ScriptObject> getAllocatorClass() {
+        return fieldObjectClass;
+    }
+
     /**
      * Get the class name for the object class,
      * e.g. {@code com.nashorn.oracle.scripts.JO2P0}
--- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Thu Oct 29 17:22:12 2015 -0700
@@ -34,13 +34,12 @@
 import java.util.Set;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -54,7 +53,7 @@
  * FunctionNode being compiled
  */
 @Logger(name="scopedepths")
-final class FindScopeDepths extends NodeVisitor<LexicalContext> implements Loggable {
+final class FindScopeDepths extends SimpleNodeVisitor implements Loggable {
 
     private final Compiler compiler;
     private final Map<Integer, Map<Integer, RecompilableScriptFunctionData>> fnIdToNestedFunctions = new HashMap<>();
@@ -67,7 +66,6 @@
     private int dynamicScopeCount;
 
     FindScopeDepths(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
         this.log      = initLogger(compiler.getContext());
     }
@@ -182,14 +180,16 @@
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         final String name = functionNode.getName();
-        FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.SCOPE_DEPTHS_COMPUTED);
-
+        FunctionNode newFunctionNode = functionNode;
         if (compiler.isOnDemandCompilation()) {
             final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(newFunctionNode.getId());
             if (data.inDynamicContext()) {
                 log.fine("Reviving scriptfunction ", quote(name), " as defined in previous (now lost) dynamic scope.");
                 newFunctionNode = newFunctionNode.setInDynamicContext(lc);
             }
+            if (newFunctionNode == lc.getOutermostFunction() && !newFunctionNode.hasApplyToCallSpecialization()) {
+                data.setCachedAst(newFunctionNode);
+            }
             return newFunctionNode;
         }
 
@@ -210,8 +210,7 @@
                 ObjectClassGenerator.createAllocationStrategy(newFunctionNode.getThisProperties(), compiler.getContext().useDualFields()),
                 nestedFunctions,
                 externalSymbolDepths.get(fnId),
-                internalSymbols.get(fnId),
-                compiler.removeSerializedAst(fnId));
+                internalSymbols.get(fnId));
 
         if (lc.getOutermostFunction() != newFunctionNode) {
             final FunctionNode parentFn = lc.getParentFunction(newFunctionNode);
@@ -275,17 +274,13 @@
 
         //get all symbols that are referenced inside this function body
         final Set<Symbol> symbols = new HashSet<>();
-        block.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        block.accept(new SimpleNodeVisitor() {
             @Override
-            public final boolean enterDefault(final Node node) {
-                if (!compiler.isOnDemandCompilation()) {
-                    if (node instanceof IdentNode) {
-                        final Symbol symbol = ((IdentNode)node).getSymbol();
-                        if (symbol != null && symbol.isScope()) {
-                            //if this is an internal symbol, skip it.
-                            symbols.add(symbol);
-                        }
-                    }
+            public boolean enterIdentNode(final IdentNode identNode) {
+                final Symbol symbol = identNode.getSymbol();
+                if (symbol != null && symbol.isScope()) {
+                    //if this is an internal symbol, skip it.
+                    symbols.add(symbol);
                 }
                 return true;
             }
--- a/src/jdk/nashorn/internal/codegen/FoldConstants.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java	Thu Oct 29 17:22:12 2015 -0700
@@ -37,9 +37,7 @@
 import jdk.nashorn.internal.ir.EmptyNode;
 import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IfNode;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
 import jdk.nashorn.internal.ir.Node;
@@ -48,7 +46,7 @@
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -60,12 +58,11 @@
  * Simple constant folding pass, executed before IR is starting to be lowered.
  */
 @Logger(name="fold")
-final class FoldConstants extends NodeVisitor<LexicalContext> implements Loggable {
+final class FoldConstants extends SimpleNodeVisitor implements Loggable {
 
     private final DebugLogger log;
 
     FoldConstants(final Compiler compiler) {
-        super(new LexicalContext());
         this.log = initLogger(compiler.getContext());
     }
 
@@ -101,7 +98,7 @@
 
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
-        return functionNode.setState(lc, CompilationState.CONSTANT_FOLDED);
+        return functionNode;
     }
 
     @Override
@@ -117,7 +114,7 @@
                 statements.addAll(executed.getStatements()); // Get statements form executed branch
             }
             if (dropped != null) {
-                extractVarNodes(dropped, statements); // Get var-nodes from non-executed branch
+                extractVarNodesFromDeadCode(dropped, statements); // Get var-nodes from non-executed branch
             }
             if (statements.isEmpty()) {
                 return new EmptyNode(ifNode);
@@ -186,14 +183,27 @@
         protected abstract LiteralNode<?> eval();
     }
 
-    private static void extractVarNodes(final Block block, final List<Statement> statements) {
-        final LexicalContext lc = new LexicalContext();
-        block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
+    /**
+     * When we eliminate dead code, we must preserve var declarations as they are scoped to the whole
+     * function. This method gathers var nodes from code passed to it, removing their initializers.
+     *
+     * @param deadCodeRoot the root node of eliminated dead code
+     * @param statements a list that will be receiving the var nodes from the dead code, with their
+     * initializers removed.
+     */
+    static void extractVarNodesFromDeadCode(final Node deadCodeRoot, final List<Statement> statements) {
+        deadCodeRoot.accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterVarNode(final VarNode varNode) {
                 statements.add(varNode.setInit(null));
                 return false;
             }
+
+            @Override
+            public boolean enterFunctionNode(final FunctionNode functionNode) {
+                // Don't descend into nested functions
+                return false;
+            }
         });
     }
 
@@ -353,8 +363,8 @@
                 return null;
             }
 
-            isInteger &= JSType.isRepresentableAsInt(value) && !JSType.isNegativeZero(value);
-            isLong    &= JSType.isRepresentableAsLong(value) && !JSType.isNegativeZero(value);
+            isInteger &= JSType.isStrictlyRepresentableAsInt(value);
+            isLong    &= JSType.isStrictlyRepresentableAsLong(value);
 
             if (isInteger) {
                 return LiteralNode.newInstance(token, finish, (int)value);
--- a/src/jdk/nashorn/internal/codegen/Label.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/Label.java	Thu Oct 29 17:22:12 2015 -0700
@@ -447,7 +447,7 @@
             undefineLocalVariables(liveLocalCount, true);
             // Temporaries are promoted
             firstTemp = liveLocalCount;
-            // No trailing undefineds
+            // No trailing undefined values
             localVariableTypes.subList(firstTemp, localVariableTypes.size()).clear();
             assert symbolBoundary.length() == firstTemp;
             // Generalize all reference types to Object, and promote boolean to int
@@ -497,7 +497,7 @@
     private transient Label.Stack stack;
 
     /** ASM representation of this label */
-    private jdk.internal.org.objectweb.asm.Label label;
+    private transient jdk.internal.org.objectweb.asm.Label label;
 
     /** Id for debugging purposes, remove if footprint becomes unmanageable */
     private final int id;
--- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -54,7 +54,6 @@
 import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.GetSplitState;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
@@ -88,6 +87,7 @@
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.parser.TokenType;
 
 /**
@@ -106,7 +106,7 @@
  * instances of the calculator to be run on nested functions (when not lazy compiling).
  *
  */
-final class LocalVariableTypesCalculator extends NodeVisitor<LexicalContext>{
+final class LocalVariableTypesCalculator extends SimpleNodeVisitor {
 
     private static class JumpOrigin {
         final JoinPredecessor node;
@@ -426,7 +426,6 @@
     private final Deque<Label> catchLabels = new ArrayDeque<>();
 
     LocalVariableTypesCalculator(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
     }
 
@@ -1331,7 +1330,7 @@
         // Sets the return type of the function and also performs the bottom-up pass of applying type and conversion
         // information to nodes as well as doing the calculation on nested functions as required.
         FunctionNode newFunction = functionNode;
-        final NodeVisitor<LexicalContext> applyChangesVisitor = new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        final SimpleNodeVisitor applyChangesVisitor = new SimpleNodeVisitor() {
             private boolean inOuterFunction = true;
             private final Deque<JoinPredecessor> joinPredecessors = new ArrayDeque<>();
 
@@ -1478,7 +1477,6 @@
         newFunction = newFunction.setReturnType(lc, returnType);
 
 
-        newFunction = newFunction.setState(lc, CompilationState.LOCAL_VARIABLE_TYPES_CALCULATED);
         newFunction = newFunction.setParameters(lc, newFunction.visitParameters(applyChangesVisitor));
         return newFunction;
     }
--- a/src/jdk/nashorn/internal/codegen/Lower.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/Lower.java	Thu Oct 29 17:22:12 2015 -0700
@@ -51,7 +51,6 @@
 import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
@@ -74,7 +73,7 @@
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
@@ -121,13 +120,7 @@
                             terminated = true;
                         }
                     } else {
-                        statement.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-                            @Override
-                            public boolean enterVarNode(final VarNode varNode) {
-                                newStatements.add(varNode.setInit(null));
-                                return false;
-                            }
-                        });
+                        FoldConstants.extractVarNodesFromDeadCode(statement, newStatements);
                     }
                 }
                 return newStatements;
@@ -266,7 +259,7 @@
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         log.info("END FunctionNode: ", functionNode.getName());
-        return functionNode.setState(lc, CompilationState.LOWERED);
+        return functionNode;
     }
 
     @Override
@@ -328,7 +321,7 @@
 
     @SuppressWarnings("unchecked")
     private static <T extends Node> T ensureUniqueNamesIn(final T node) {
-        return (T)node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        return (T)node.accept(new SimpleNodeVisitor() {
             @Override
             public Node leaveFunctionNode(final FunctionNode functionNode) {
                 final String name = functionNode.getName();
@@ -393,7 +386,7 @@
         final Block finallyBlock = createFinallyBlock(finallyBody);
         final ArrayList<Block> inlinedFinallies = new ArrayList<>();
         final FunctionNode fn = lc.getCurrentFunction();
-        final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        final TryNode newTryNode = (TryNode)tryNode.accept(new SimpleNodeVisitor() {
 
             @Override
             public boolean enterFunctionNode(final FunctionNode functionNode) {
@@ -511,7 +504,7 @@
         }
 
         /*
-         * create a new trynode
+         * create a new try node
          *    if we have catches:
          *
          *    try            try
@@ -522,7 +515,7 @@
          *                   catchall
          *                        rethrow
          *
-         *   otheriwse
+         *   otherwise
          *
          *   try              try
          *      x               x
@@ -536,7 +529,7 @@
         final Block catchAll = catchAllBlock(tryNode);
 
         final List<ThrowNode> rethrows = new ArrayList<>(1);
-        catchAll.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        catchAll.accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterThrowNode(final ThrowNode throwNode) {
                 rethrows.add(throwNode);
@@ -681,7 +674,7 @@
     private static boolean controlFlowEscapes(final LexicalContext lex, final Block loopBody) {
         final List<Node> escapes = new ArrayList<>();
 
-        loopBody.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        loopBody.accept(new SimpleNodeVisitor() {
             @Override
             public Node leaveBreakNode(final BreakNode node) {
                 escapes.add(node);
--- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu Oct 29 17:22:12 2015 -0700
@@ -258,8 +258,7 @@
      */
     private Type popType(final Type expected) {
         final Type type = popType();
-        assert type.isObject() && expected.isObject() ||
-            type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
+        assert type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
         return type;
     }
 
@@ -1159,7 +1158,7 @@
     /**
      * Pop a value from the stack and store it in a variable denoted by the given symbol. The variable should be either
      * a local variable, or a function parameter (and not a scoped variable). For local variables, this method will also
-     * do the bookeeping of the local variable table as well as mark values in all alternative slots for the symbol as
+     * do the bookkeeping of the local variable table as well as mark values in all alternative slots for the symbol as
      * dead. In this regard it differs from {@link #storeHidden(Type, int)}.
      *
      * @param symbol the symbol to store into.
@@ -2133,10 +2132,25 @@
      * @return the method emitter
      */
     MethodEmitter dynamicNew(final int argCount, final int flags) {
+        return dynamicNew(argCount, flags, null);
+    }
+
+    /**
+     * Generate a dynamic new
+     *
+     * @param argCount  number of arguments
+     * @param flags     callsite flags
+     * @param msg        additional message to be used when reporting error
+     *
+     * @return the method emitter
+     */
+    MethodEmitter dynamicNew(final int argCount, final int flags, final String msg) {
         assert !isOptimistic(flags);
         debug("dynamic_new", "argcount=", argCount);
         final String signature = getDynamicSignature(Type.OBJECT, argCount);
-        method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
+        method.visitInvokeDynamicInsn(
+                msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:new:" + NameCodec.encode(msg) : "dyn:new",
+                signature, LINKERBOOTSTRAP, flags);
         pushType(Type.OBJECT); //TODO fix result type
         return this;
     }
@@ -2151,10 +2165,26 @@
      * @return the method emitter
      */
     MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) {
+        return dynamicCall(returnType, argCount, flags, null);
+    }
+
+    /**
+     * Generate a dynamic call
+     *
+     * @param returnType return type
+     * @param argCount   number of arguments
+     * @param flags      callsite flags
+     * @param msg        additional message to be used when reporting error
+     *
+     * @return the method emitter
+     */
+    MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags, final String msg) {
         debug("dynamic_call", "args=", argCount, "returnType=", returnType);
         final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target)
         debug("   signature", signature);
-        method.visitInvokeDynamicInsn("dyn:call", signature, LINKERBOOTSTRAP, flags);
+        method.visitInvokeDynamicInsn(
+                msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:call:" + NameCodec.encode(msg) : "dyn:call",
+                signature, LINKERBOOTSTRAP, flags);
         pushType(returnType);
 
         return this;
--- a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -69,7 +69,6 @@
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
-import jdk.nashorn.internal.runtime.options.Options;
 
 /**
  * Generates the ScriptObject subclass structure with fields for a user objects.
@@ -787,7 +786,7 @@
      * @param primitiveSetter   primitive setter for the current type with an element of the current type
      * @param objectSetter      the object setter
      *
-     * @return method handle that checks if the element to be set is of the currenttype, even though it's boxed
+     * @return method handle that checks if the element to be set is of the current type, even though it's boxed
      *  and instead of using the generic object setter, that would blow up the type and invalidate the map,
      *  unbox it and call the primitive setter instead
      */
--- a/src/jdk/nashorn/internal/codegen/ObjectCreator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/ObjectCreator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -36,7 +36,7 @@
  * Base class for object creation code generation.
  * @param <T> value type
  */
-public abstract class ObjectCreator<T> {
+public abstract class ObjectCreator<T> implements CodeGenerator.SplitLiteralCreator {
 
     /** List of keys & symbols to initiate in this ObjectCreator */
     final List<MapTuple<T>> tuples;
@@ -69,7 +69,23 @@
      * Generate code for making the object.
      * @param method Script method.
      */
-    protected abstract void makeObject(final MethodEmitter method);
+    public void makeObject(final MethodEmitter method) {
+        createObject(method);
+        // We need to store the object in a temporary slot as populateRange expects to load the
+        // object from a slot (as it is also invoked within split methods). Note that this also
+        // helps optimistic continuations to handle the stack in case an optimistic assumption
+        // fails during initialization (see JDK-8079269).
+        final int objectSlot = method.getUsedSlotsWithLiveTemporaries();
+        final Type objectType = method.peekType();
+        method.storeTemp(objectType, objectSlot);
+        populateRange(method, objectType, objectSlot, 0, tuples.size());
+    }
+
+    /**
+     * Generate code for creating and initializing the object.
+     * @param method the method emitter
+     */
+    protected abstract void createObject(final MethodEmitter method);
 
     /**
      * Construct the property map appropriate for the object.
@@ -125,6 +141,12 @@
     }
 
     /**
+     * Get the class of objects created by this ObjectCreator
+     * @return class of created object
+     */
+    abstract protected Class<? extends ScriptObject> getAllocatorClass();
+
+    /**
      * Technique for loading an initial value. Defined by anonymous subclasses in code gen.
      *
      * @param value Value to load.
@@ -145,29 +167,4 @@
     MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple) {
         return loadTuple(method, tuple, true);
     }
-
-    /**
-     * If using optimistic typing, let the code generator realize that the newly created object on the stack
-     * when DUP-ed will be the same value. Basically: {NEW, DUP, INVOKESPECIAL init, DUP} will leave a stack
-     * load specification {unknown, unknown} on stack (that is "there's two values on the stack, but neither
-     * comes from a known local load"). If there's an optimistic operation in the literal initializer,
-     * OptimisticOperation.storeStack will allocate two temporary locals for it and store them as
-     * {ASTORE 4, ASTORE 3}. If we instead do {NEW, DUP, INVOKESPECIAL init, ASTORE 3, ALOAD 3, DUP} we end up
-     * with stack load specification {ALOAD 3, ALOAD 3} (as DUP can track that the value it duplicated came
-     * from a local load), so if/when a continuation needs to be recreated from it, it'll be
-     * able to emit ALOAD 3, ALOAD 3 to recreate the stack. If we didn't do this, deoptimization within an
-     * object literal initialization could in rare cases cause an incompatible change in the shape of the
-     * local variable table for the temporaries, e.g. in the following snippet where a variable is reassigned
-     * to a wider type in an object initializer:
-     * <code>var m = 1; var obj = {p0: m, p1: m = "foo", p2: m}</code>
-     * @param method the current method emitter.
-     */
-    void helpOptimisticRecognizeDuplicateIdentity(final MethodEmitter method) {
-        if (codegen.useOptimisticTypes()) {
-            final Type objectType = method.peekType();
-            final int tempSlot = method.defineTemporaryLocalVariable(objectType.getSlots());
-            method.storeHidden(objectType, tempSlot);
-            method.load(objectType, tempSlot);
-        }
-    }
 }
--- a/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -38,12 +38,10 @@
 import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LoopNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.Optimistic;
@@ -53,7 +51,7 @@
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.ScriptObject;
 
@@ -62,7 +60,7 @@
  * must not ever be marked as optimistic, assigning narrowest non-invalidated types to program points from the
  * compilation environment, as well as initializing optimistic types of global properties for scripts.
  */
-final class OptimisticTypesCalculator extends NodeVisitor<LexicalContext> {
+final class OptimisticTypesCalculator extends SimpleNodeVisitor {
 
     final Compiler compiler;
 
@@ -70,7 +68,6 @@
     final Deque<BitSet> neverOptimistic = new ArrayDeque<>();
 
     OptimisticTypesCalculator(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
     }
 
@@ -208,7 +205,7 @@
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         neverOptimistic.pop();
-        return functionNode.setState(lc, CompilationState.OPTIMISTIC_TYPES_ASSIGNED);
+        return functionNode;
     }
 
     @Override
--- a/src/jdk/nashorn/internal/codegen/ProgramPoints.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/ProgramPoints.java	Thu Oct 29 17:22:12 2015 -0700
@@ -37,25 +37,20 @@
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IndexNode;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.Optimistic;
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 
 /**
  * Find program points in the code that are needed for optimistic assumptions
  */
-class ProgramPoints extends NodeVisitor<LexicalContext> {
+class ProgramPoints extends SimpleNodeVisitor {
 
     private final IntDeque nextProgramPoint = new IntDeque();
     private final Set<Node> noProgramPoint = new HashSet<>();
 
-    ProgramPoints() {
-        super(new LexicalContext());
-    }
-
     private int next() {
         final int next = nextProgramPoint.getAndIncrement();
         if(next > MAX_PROGRAM_POINT_VALUE) {
--- a/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java	Thu Oct 29 17:22:12 2015 -0700
@@ -29,21 +29,17 @@
 import java.util.List;
 import jdk.nashorn.internal.ir.CompileUnitHolder;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
 import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.ObjectNode;
+import jdk.nashorn.internal.ir.Splittable;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 
 /**
  * Base class for a node visitor that replaces {@link CompileUnit}s in {@link CompileUnitHolder}s.
  */
-abstract class ReplaceCompileUnits extends NodeVisitor<LexicalContext> {
-    ReplaceCompileUnits() {
-        super(new LexicalContext());
-    }
+abstract class ReplaceCompileUnits extends SimpleNodeVisitor {
 
     /**
      * Override to provide a replacement for an old compile unit.
@@ -64,22 +60,35 @@
 
     @Override
     public Node leaveFunctionNode(final FunctionNode node) {
-        return node.setCompileUnit(lc, getExistingReplacement(node)).setState(lc, CompilationState.COMPILE_UNITS_REUSED);
+        return node.setCompileUnit(lc, getExistingReplacement(node));
     }
 
     @Override
     public Node leaveLiteralNode(final LiteralNode<?> node) {
         if (node instanceof ArrayLiteralNode) {
             final ArrayLiteralNode aln = (ArrayLiteralNode)node;
-            if (aln.getUnits() == null) {
+            if (aln.getSplitRanges() == null) {
                 return node;
             }
-            final List<ArrayUnit> newArrayUnits = new ArrayList<>();
-            for (final ArrayUnit au : aln.getUnits()) {
-                newArrayUnits.add(new ArrayUnit(getExistingReplacement(au), au.getLo(), au.getHi()));
+            final List<Splittable.SplitRange> newArrayUnits = new ArrayList<>();
+            for (final Splittable.SplitRange au : aln.getSplitRanges()) {
+                newArrayUnits.add(new Splittable.SplitRange(getExistingReplacement(au), au.getLow(), au.getHigh()));
             }
-            return aln.setUnits(lc, newArrayUnits);
+            return aln.setSplitRanges(lc, newArrayUnits);
         }
         return node;
     }
+
+    @Override
+    public Node leaveObjectNode(final ObjectNode objectNode) {
+        final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();
+        if (ranges != null) {
+            final List<Splittable.SplitRange> newRanges = new ArrayList<>();
+            for (final Splittable.SplitRange range : ranges) {
+                newRanges.add(new Splittable.SplitRange(getExistingReplacement(range), range.getLow(), range.getHigh()));
+            }
+            return objectNode.setSplitRanges(lc, newRanges);
+        }
+        return super.leaveObjectNode(objectNode);
+    }
 }
--- a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java	Thu Oct 29 17:22:12 2015 -0700
@@ -169,7 +169,7 @@
                 slot += type.getSlots();
             }
             // Shared scope calls disabled in optimistic world. TODO is this right?
-            method.dynamicCall(returnType, 2 + paramTypes.length, flags);
+            method.dynamicCall(returnType, 2 + paramTypes.length, flags, symbol.getName());
         }
 
         method._return(returnType);
--- a/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -61,7 +61,7 @@
     }
 
     @Override
-    protected void makeObject(final MethodEmitter method) {
+    public void createObject(final MethodEmitter method) {
         assert !isScope() : "spill scope objects are not currently supported";
 
         final int          length        = tuples.size();
@@ -69,9 +69,7 @@
         final int          spillLength   = ScriptObject.spillAllocationLength(length);
         final long[]       jpresetValues = dualFields ? new long[spillLength] : null;
         final Object[]     opresetValues = new Object[spillLength];
-        final Set<Integer> postsetValues = new LinkedHashSet<>();
-        final int          callSiteFlags = codegen.getCallSiteFlags();
-        final Class<?>     objectClass   = dualFields ? JD.class : JO.class;
+        final Class<?>     objectClass   = getAllocatorClass();
         ArrayData          arrayData     = ArrayData.allocate(ScriptRuntime.EMPTY_ARRAY);
 
         // Compute constant property values
@@ -85,9 +83,7 @@
 
             if (value != null) {
                 final Object constantValue = LiteralNode.objectAsConstant(value);
-                if (constantValue == LiteralNode.POSTSET_MARKER) {
-                    postsetValues.add(pos);
-                } else {
+                if (constantValue != LiteralNode.POSTSET_MARKER) {
                     final Property property = propertyMap.findProperty(key);
                     if (property != null) {
                         // normal property key
@@ -146,25 +142,34 @@
         // instantiate the script object with spill objects
         method.invoke(constructorNoLookup(objectClass, PropertyMap.class, long[].class, Object[].class));
 
-        helpOptimisticRecognizeDuplicateIdentity(method);
-
         // Set prefix array data if any
         if (arrayData.length() > 0) {
             method.dup();
             codegen.loadConstant(arrayData);
             method.invoke(virtualCallNoLookup(ScriptObject.class, "setArray", void.class, ArrayData.class));
         }
+    }
+
+    @Override
+    public void populateRange(final MethodEmitter method, final Type objectType, final int objectSlot, final int start, final int end) {
+        final int  callSiteFlags = codegen.getCallSiteFlags();
+        method.load(objectType, objectSlot);
 
         // set postfix values
-        for (final int i : postsetValues) {
+        for (int i = start; i < end; i++) {
             final MapTuple<Expression> tuple = tuples.get(i);
+
+            if (LiteralNode.isConstant(tuple.value)) {
+                continue;
+            }
+
             final Property property = propertyMap.findProperty(tuple.key);
+
             if (property == null) {
                 final int index = ArrayIndex.getArrayIndex(tuple.key);
                 assert ArrayIndex.isValidArrayIndex(index);
                 method.dup();
                 method.load(ArrayIndex.toLongIndex(index));
-                //method.println("putting " + tuple + " into arraydata");
                 loadTuple(method, tuple);
                 method.dynamicSetIndex(callSiteFlags);
             } else {
@@ -178,8 +183,7 @@
     @Override
     protected PropertyMap makeMap() {
         assert propertyMap == null : "property map already initialized";
-        final boolean dualFields = codegen.useDualFields();
-        final Class<? extends ScriptObject> clazz = dualFields ? JD.class : JO.class;
+        final Class<? extends ScriptObject> clazz = getAllocatorClass();
         propertyMap = new MapCreator<>(clazz, tuples).makeSpillMap(false, codegen.useDualFields());
         return propertyMap;
     }
@@ -188,4 +192,9 @@
     protected void loadValue(final Expression expr, final Type type) {
         codegen.loadExpressionAsType(expr, type);
     }
+
+    @Override
+    protected Class<? extends ScriptObject> getAllocatorClass() {
+        return codegen.useDualFields() ? JD.class : JO.class;
+    }
 }
--- a/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Thu Oct 29 17:22:12 2015 -0700
@@ -175,8 +175,7 @@
                 FunctionNode.IS_ANONYMOUS | FunctionNode.USES_ANCESTOR_SCOPE | FunctionNode.IS_SPLIT
         )
         .setBody(lc, body)
-        .setCompileUnit(lc, splitNode.getCompileUnit())
-        .copyCompilationState(lc, originalFn);
+        .setCompileUnit(lc, splitNode.getCompileUnit());
 
         // Call the function:
         //     either "(function () { ... }).call(this)"
@@ -308,10 +307,6 @@
         assert !varNode.isBlockScoped(); //TODO: we must handle these too, but we currently don't
 
         final Expression init = varNode.getInit();
-        if (varNode.isAnonymousFunctionDeclaration()) {
-            // We ain't moving anonymous function declarations.
-            return super.enterVarNode(varNode);
-        }
 
         // Move a declaration-only var statement to the top of the outermost function.
         getCurrentFunctionState().varStatements.add(varNode.setInit(null));
--- a/src/jdk/nashorn/internal/codegen/Splitter.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/Splitter.java	Thu Oct 29 17:22:12 2015 -0700
@@ -33,15 +33,15 @@
 import java.util.Map;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
 import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.ObjectNode;
+import jdk.nashorn.internal.ir.PropertyNode;
 import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.Splittable;
 import jdk.nashorn.internal.ir.Statement;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
@@ -52,7 +52,7 @@
  * Split the IR into smaller compile units.
  */
 @Logger(name="splitter")
-final class Splitter extends NodeVisitor<LexicalContext> implements Loggable {
+final class Splitter extends SimpleNodeVisitor implements Loggable {
     /** Current compiler. */
     private final Compiler compiler;
 
@@ -78,7 +78,6 @@
      * @param outermostCompileUnit  compile unit for outermost function, if non-lazy this is the script's compile unit
      */
     public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) {
-        super(new LexicalContext());
         this.compiler             = compiler;
         this.outermost            = functionNode;
         this.outermostCompileUnit = outermostCompileUnit;
@@ -141,7 +140,7 @@
         final Block body = functionNode.getBody();
         final List<FunctionNode> dc = directChildren(functionNode);
 
-        final Block newBody = (Block)body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        final Block newBody = (Block)body.accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterFunctionNode(final FunctionNode nestedFunction) {
                 return dc.contains(nestedFunction);
@@ -158,12 +157,12 @@
 
         assert functionNode.getCompileUnit() != null;
 
-        return functionNode.setState(null, CompilationState.SPLIT);
+        return functionNode;
     }
 
     private static List<FunctionNode> directChildren(final FunctionNode functionNode) {
         final List<FunctionNode> dc = new ArrayList<>();
-        functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        functionNode.accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterFunctionNode(final FunctionNode child) {
                 if (child == functionNode) {
@@ -296,7 +295,7 @@
             final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal;
             final Node[]           value            = arrayLiteralNode.getValue();
             final int[]            postsets         = arrayLiteralNode.getPostsets();
-            final List<ArrayUnit>  units            = new ArrayList<>();
+            final List<Splittable.SplitRange> ranges = new ArrayList<>();
 
             long totalWeight = 0;
             int  lo          = 0;
@@ -310,7 +309,7 @@
 
                 if (totalWeight >= SPLIT_THRESHOLD) {
                     final CompileUnit unit = compiler.findUnit(totalWeight - weight);
-                    units.add(new ArrayUnit(unit, lo, i));
+                    ranges.add(new Splittable.SplitRange(unit, lo, i));
                     lo = i;
                     totalWeight = weight;
                 }
@@ -318,16 +317,59 @@
 
             if (lo != postsets.length) {
                 final CompileUnit unit = compiler.findUnit(totalWeight);
-                units.add(new ArrayUnit(unit, lo, postsets.length));
+                ranges.add(new Splittable.SplitRange(unit, lo, postsets.length));
             }
 
-            return arrayLiteralNode.setUnits(lc, units);
+            return arrayLiteralNode.setSplitRanges(lc, ranges);
         }
 
         return literal;
     }
 
     @Override
+    public Node leaveObjectNode(final ObjectNode objectNode) {
+        long weight = WeighNodes.weigh(objectNode);
+
+        if (weight < SPLIT_THRESHOLD) {
+            return objectNode;
+        }
+
+        final FunctionNode functionNode = lc.getCurrentFunction();
+        lc.setFlag(functionNode, FunctionNode.IS_SPLIT);
+
+        final List<Splittable.SplitRange> ranges        = new ArrayList<>();
+        final List<PropertyNode>          properties    = objectNode.getElements();
+        final boolean                     isSpillObject = properties.size() > CodeGenerator.OBJECT_SPILL_THRESHOLD;
+        long totalWeight = 0;
+        int  lo          = 0;
+
+        for (int i = 0; i < properties.size(); i++) {
+
+            final PropertyNode property = properties.get(i);
+            final boolean isConstant = LiteralNode.isConstant(property.getValue());
+
+            if (!isConstant || !isSpillObject) {
+                weight = isConstant ? 0 : WeighNodes.weigh(property.getValue());
+                totalWeight += WeighNodes.AASTORE_WEIGHT + weight;
+
+                if (totalWeight >= SPLIT_THRESHOLD) {
+                    final CompileUnit unit = compiler.findUnit(totalWeight - weight);
+                    ranges.add(new Splittable.SplitRange(unit, lo, i));
+                    lo = i;
+                    totalWeight = weight;
+                }
+            }
+        }
+
+        if (lo != properties.size()) {
+            final CompileUnit unit = compiler.findUnit(totalWeight);
+            ranges.add(new Splittable.SplitRange(unit, lo, properties.size()));
+        }
+
+        return objectNode.setSplitRanges(lc, ranges);
+    }
+
+    @Override
     public boolean enterFunctionNode(final FunctionNode node) {
         //only go into the function node for this splitter. any subfunctions are rejected
         return node == outermost;
--- a/src/jdk/nashorn/internal/codegen/TypeMap.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/TypeMap.java	Thu Oct 29 17:22:12 2015 -0700
@@ -27,21 +27,18 @@
 
 import java.lang.invoke.MethodType;
 import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.NoSuchElementException;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 
 /**
- * A data structure that maps one or several function nodes (by their unique id:s, not by
- * the FunctionNode object itself, due to copy on write changing it several times through
- * code generation.
+ * A tuple containing function id, parameter types, return type and needsCallee flag.
  */
-public class TypeMap {
-    private final Map<Integer, Type[]> paramTypeMap  = new HashMap<>();
-    private final Map<Integer, Type>   returnTypeMap = new HashMap<>();
+public final class TypeMap {
+    private final int functionNodeId;
+    private final Type[] paramTypes;
+    private final Type returnType;
     private final boolean needsCallee;
 
     /**
@@ -56,9 +53,10 @@
         for (final Class<?> p : type.parameterArray()) {
             types[pos++] = Type.typeFor(p);
         }
-        paramTypeMap.put(functionNodeId, types);
-        returnTypeMap.put(functionNodeId, Type.typeFor(type.returnType()));
 
+        this.functionNodeId = functionNodeId;
+        this.paramTypes = types;
+        this.returnType = Type.typeFor(type.returnType());
         this.needsCallee = needsCallee;
     }
 
@@ -69,20 +67,14 @@
      * @throws NoSuchElementException if the type map has no mapping for the requested function
      */
     public Type[] getParameterTypes(final int functionNodeId) {
-        final Type[] paramTypes = paramTypeMap.get(functionNodeId);
-        if (paramTypes == null) {
-            throw new NoSuchElementException(Integer.toString(functionNodeId));
-        }
+        assert this.functionNodeId == functionNodeId;
         return paramTypes.clone();
     }
 
     MethodType getCallSiteType(final FunctionNode functionNode) {
-        final Type[] types = paramTypeMap.get(functionNode.getId());
-        if (types == null) {
-            return null;
-        }
-
-        MethodType mt = MethodType.methodType(returnTypeMap.get(functionNode.getId()).getTypeClass());
+        assert this.functionNodeId == functionNode.getId();
+        final Type[] types = paramTypes;
+        MethodType mt = MethodType.methodType(returnType.getTypeClass());
         if (needsCallee) {
             mt = mt.appendParameterTypes(ScriptFunction.class);
         }
@@ -116,7 +108,8 @@
      * @return parameter type for this callsite if known
      */
     Type get(final FunctionNode functionNode, final int pos) {
-        final Type[] types = paramTypeMap.get(functionNode.getId());
+        assert this.functionNodeId == functionNode.getId();
+        final Type[] types = paramTypes;
         assert types == null || pos < types.length : "fn = " + functionNode.getId() + " " + "types=" + Arrays.toString(types) + " || pos=" + pos + " >= length=" + types.length + " in " + this;
         if (types != null && pos < types.length) {
             return types[pos];
@@ -124,13 +117,6 @@
         return null;
     }
 
-    boolean has(final FunctionNode functionNode) {
-        final int id = functionNode.getId();
-        final Type[] paramTypes = paramTypeMap.get(id);
-        assert (paramTypes == null) == (returnTypeMap.get(id) == null) : "inconsistent param and return types in param map";
-        return paramTypes != null;
-    }
-
     @Override
     public String toString() {
         return toString("");
@@ -139,27 +125,16 @@
     String toString(final String prefix) {
         final StringBuilder sb = new StringBuilder();
 
-        if (paramTypeMap.isEmpty()) {
-            sb.append(prefix).append("\t<empty>");
-            return sb.toString();
-        }
-
-        for (final Map.Entry<Integer, Type[]> entry : paramTypeMap.entrySet()) {
-            final int id = entry.getKey();
-            sb.append(prefix).append('\t');
-            sb.append("function ").append(id).append('\n');
-            sb.append(prefix).append("\t\tparamTypes=");
-            if (entry.getValue() == null) {
-                sb.append("[]");
-            } else {
-                sb.append(Arrays.toString(entry.getValue()));
-            }
-            sb.append('\n');
-            sb.append(prefix).append("\t\treturnType=");
-            final Type ret = returnTypeMap.get(id);
-            sb.append(ret == null ? "N/A" : ret);
-            sb.append('\n');
-        }
+        final int id = functionNodeId;
+        sb.append(prefix).append('\t');
+        sb.append("function ").append(id).append('\n');
+        sb.append(prefix).append("\t\tparamTypes=");
+        sb.append(Arrays.toString(paramTypes));
+        sb.append('\n');
+        sb.append(prefix).append("\t\treturnType=");
+        final Type ret = returnType;
+        sb.append(ret == null ? "N/A" : ret);
+        sb.append('\n');
 
         return sb.toString();
     }
--- a/src/jdk/nashorn/internal/codegen/WeighNodes.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/WeighNodes.java	Thu Oct 29 17:22:12 2015 -0700
@@ -44,12 +44,13 @@
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
 import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.ObjectNode;
 import jdk.nashorn.internal.ir.PropertyNode;
 import jdk.nashorn.internal.ir.ReturnNode;
 import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.Splittable;
 import jdk.nashorn.internal.ir.SwitchNode;
 import jdk.nashorn.internal.ir.ThrowNode;
 import jdk.nashorn.internal.ir.TryNode;
@@ -88,6 +89,8 @@
     static final long THROW_WEIGHT     =  2;
     static final long VAR_WEIGHT       = 40;
     static final long WITH_WEIGHT      =  8;
+    static final long OBJECT_WEIGHT    = 16;
+    static final long SETPROP_WEIGHT   =  5;
 
     /** Accumulated weight. */
     private long weight;
@@ -213,7 +216,7 @@
             final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode)literalNode;
             final Node[]           value            = arrayLiteralNode.getValue();
             final int[]            postsets         = arrayLiteralNode.getPostsets();
-            final List<ArrayUnit>  units            = arrayLiteralNode.getUnits();
+            final List<Splittable.SplitRange>  units            = arrayLiteralNode.getSplitRanges();
 
             if (units == null) {
                 for (final int postset : postsets) {
@@ -233,6 +236,27 @@
     }
 
     @Override
+    public boolean enterObjectNode(final ObjectNode objectNode) {
+        weight += OBJECT_WEIGHT;
+        final List<PropertyNode> properties = objectNode.getElements();
+        final boolean isSpillObject = properties.size() > CodeGenerator.OBJECT_SPILL_THRESHOLD;
+
+        for (final PropertyNode property : properties) {
+            if (!LiteralNode.isConstant(property.getValue())) {
+                weight += SETPROP_WEIGHT;
+                property.getValue().accept(this);
+            } else if (!isSpillObject) {
+                // constants in spill object are set via preset spill array,
+                // but fields objects need to set constants.
+                weight += SETPROP_WEIGHT;
+            }
+
+        }
+
+        return false;
+    }
+
+    @Override
     public Node leavePropertyNode(final PropertyNode propertyNode) {
         weight += LITERAL_WEIGHT;
         return propertyNode;
--- a/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java	Thu Oct 29 17:22:12 2015 -0700
@@ -36,7 +36,7 @@
  * The bytecode ops are coupled to a MethodVisitor from ASM for
  * byte code generation. They know nothing about our MethodGenerator,
  * which is the abstraction for working with Nashorn JS types
- * For exmaple, anything like "two or one slots" for a type, which
+ * For example, anything like "two or one slots" for a type, which
  * is represented in bytecode and ASM, is abstracted away in the
  * MethodGenerator. There you just say "dup" or "store".
  *
--- a/src/jdk/nashorn/internal/codegen/types/Type.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/codegen/types/Type.java	Thu Oct 29 17:22:12 2015 -0700
@@ -65,6 +65,7 @@
 import jdk.internal.org.objectweb.asm.Handle;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Undefined;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -256,6 +257,9 @@
         case jdk.internal.org.objectweb.asm.Type.DOUBLE:
             return NUMBER;
         case jdk.internal.org.objectweb.asm.Type.OBJECT:
+            if (Context.isStructureClass(itype.getClassName())) {
+                return SCRIPT_OBJECT;
+            }
             try {
                 return Type.typeFor(Class.forName(itype.getClassName()));
             } catch(final ClassNotFoundException e) {
@@ -949,7 +953,7 @@
     /**
      * This is the singleton for integer arrays
      */
-    public static final ArrayType INT_ARRAY = new ArrayType(int[].class) {
+    public static final ArrayType INT_ARRAY = putInCache(new ArrayType(int[].class) {
         private static final long serialVersionUID = 1L;
 
         @Override
@@ -973,12 +977,12 @@
         public Type getElementType() {
             return INT;
         }
-    };
+    });
 
     /**
      * This is the singleton for long arrays
      */
-    public static final ArrayType LONG_ARRAY = new ArrayType(long[].class) {
+    public static final ArrayType LONG_ARRAY = putInCache(new ArrayType(long[].class) {
         private static final long serialVersionUID = 1L;
 
         @Override
@@ -1002,12 +1006,12 @@
         public Type getElementType() {
             return LONG;
         }
-    };
+    });
 
     /**
      * This is the singleton for numeric arrays
      */
-    public static final ArrayType NUMBER_ARRAY = new ArrayType(double[].class) {
+    public static final ArrayType NUMBER_ARRAY = putInCache(new ArrayType(double[].class) {
         private static final long serialVersionUID = 1L;
 
         @Override
@@ -1031,13 +1035,7 @@
         public Type getElementType() {
             return NUMBER;
         }
-    };
-
-    /** Singleton for method handle arrays used for properties etc. */
-    public static final ArrayType METHODHANDLE_ARRAY = putInCache(new ArrayType(MethodHandle[].class));
-
-    /** This is the singleton for string arrays */
-    public static final ArrayType STRING_ARRAY = putInCache(new ArrayType(String[].class));
+    });
 
     /** This is the singleton for object arrays */
     public static final ArrayType OBJECT_ARRAY = putInCache(new ArrayType(Object[].class));
--- a/src/jdk/nashorn/internal/ir/Block.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/Block.java	Thu Oct 29 17:22:12 2015 -0700
@@ -130,11 +130,42 @@
     }
 
     /**
-     * Clear the symbols in the block.
-     * TODO: make this immutable.
+     * Returns true if this block defines any symbols.
+     * @return true if this block defines any symbols.
+     */
+    public boolean hasSymbols() {
+        return !symbols.isEmpty();
+    }
+
+    /**
+     * Replaces symbols defined in this block with different symbols. Used to ensure symbol tables are
+     * immutable upon construction and have copy-on-write semantics. Note that this method only replaces the
+     * symbols in the symbol table, it does not act on any contained AST nodes that might reference the symbols.
+     * Those should be updated separately as this method is meant to be used as part of such an update pass.
+     * @param lc the current lexical context
+     * @param replacements the map of symbol replacements
+     * @return a new block with replaced symbols, or this block if none of the replacements modified the symbol
+     * table.
      */
-    public void clearSymbols() {
-        symbols.clear();
+    public Block replaceSymbols(final LexicalContext lc, final Map<Symbol, Symbol> replacements) {
+        if (symbols.isEmpty()) {
+            return this;
+        }
+        final LinkedHashMap<String, Symbol> newSymbols = new LinkedHashMap<>(symbols);
+        for (final Map.Entry<String, Symbol> entry: newSymbols.entrySet()) {
+            final Symbol newSymbol = replacements.get(entry.getValue());
+            assert newSymbol != null : "Missing replacement for " + entry.getKey();
+            entry.setValue(newSymbol);
+        }
+        return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, newSymbols, conversion));
+    }
+
+    /**
+     * Returns a copy of this block with a shallow copy of the symbol table.
+     * @return a copy of this block with a shallow copy of the symbol table.
+     */
+    public Block copyWithNewSymbols() {
+        return new Block(this, finish, statements, flags, new LinkedHashMap<>(symbols), conversion);
     }
 
     @Override
@@ -162,7 +193,7 @@
      * @return symbol iterator
      */
     public List<Symbol> getSymbols() {
-        return Collections.unmodifiableList(new ArrayList<>(symbols.values()));
+        return symbols.isEmpty() ? Collections.<Symbol>emptyList() : Collections.unmodifiableList(new ArrayList<>(symbols.values()));
     }
 
     /**
@@ -326,10 +357,9 @@
     /**
      * Add or overwrite an existing symbol in the block
      *
-     * @param lc     get lexical context
      * @param symbol symbol
      */
-    public void putSymbol(final LexicalContext lc, final Symbol symbol) {
+    public void putSymbol(final Symbol symbol) {
         symbols.put(symbol.getName(), symbol);
     }
 
--- a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java	Thu Oct 29 17:22:12 2015 -0700
@@ -34,7 +34,7 @@
  * This is a subclass of lexical context used for filling
  * blocks (and function nodes) with statements. When popping
  * a block from the lexical context, any statements that have
- * been generated in it are commited to the block. This saves
+ * been generated in it are committed to the block. This saves
  * unnecessary object mutations and lexical context replacement
  */
 public class BlockLexicalContext extends LexicalContext {
--- a/src/jdk/nashorn/internal/ir/ForNode.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/ForNode.java	Thu Oct 29 17:22:12 2015 -0700
@@ -43,7 +43,7 @@
     private final JoinPredecessorExpression modify;
 
     /** Iterator symbol. */
-    private Symbol iterator;
+    private final Symbol iterator;
 
     /** Is this a normal for in loop? */
     public static final int IS_FOR_IN           = 1 << 0;
@@ -70,22 +70,22 @@
         this.flags  = flags;
         this.init = null;
         this.modify = null;
+        this.iterator = null;
     }
 
     private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test,
-            final Block body, final JoinPredecessorExpression modify, final int flags, final boolean controlFlowEscapes, final LocalVariableConversion conversion) {
+            final Block body, final JoinPredecessorExpression modify, final int flags,
+            final boolean controlFlowEscapes, final LocalVariableConversion conversion, final Symbol iterator) {
         super(forNode, test, body, controlFlowEscapes, conversion);
         this.init   = init;
         this.modify = modify;
         this.flags  = flags;
-        // Even if the for node gets cloned in try/finally, the symbol can be shared as only one branch of the finally
-        // is executed.
-        this.iterator = forNode.iterator;
+        this.iterator = iterator;
     }
 
     @Override
     public Node ensureUniqueLabels(final LexicalContext lc) {
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
@@ -158,7 +158,7 @@
         if (this.init == init) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     /**
@@ -206,10 +206,15 @@
 
     /**
      * Assign an iterator symbol to this ForNode. Used for for in and for each constructs
+     * @param lc the current lexical context
      * @param iterator the iterator symbol
+     * @return a ForNode with the iterator set
      */
-    public void setIterator(final Symbol iterator) {
-        this.iterator = iterator;
+    public ForNode setIterator(final LexicalContext lc, final Symbol iterator) {
+        if (this.iterator == iterator) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     /**
@@ -230,7 +235,7 @@
         if (this.modify == modify) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
@@ -238,7 +243,7 @@
         if (this.test == test) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
@@ -251,7 +256,7 @@
         if (this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
@@ -259,19 +264,19 @@
         if (this.controlFlowEscapes == controlFlowEscapes) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     private ForNode setFlags(final LexicalContext lc, final int flags) {
         if (this.flags == flags) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
     JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
--- a/src/jdk/nashorn/internal/ir/FunctionNode.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/FunctionNode.java	Thu Oct 29 17:22:12 2015 -0700
@@ -33,10 +33,8 @@
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
 
 import java.util.Collections;
-import java.util.EnumSet;
 import java.util.Iterator;
 import java.util.List;
-import jdk.nashorn.internal.AssertsEnabled;
 import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.CompilerConstants;
@@ -73,40 +71,6 @@
         SETTER
     }
 
-    /** Compilation states available */
-    public enum CompilationState {
-        /** compiler is ready */
-        INITIALIZED,
-        /** method has been parsed */
-        PARSED,
-        /** method has been parsed */
-        PARSE_ERROR,
-        /** constant folding pass */
-        CONSTANT_FOLDED,
-        /** method has been lowered */
-        LOWERED,
-        /** program points have been assigned to unique locations */
-        PROGRAM_POINTS_ASSIGNED,
-        /** any transformations of builtins have taken place, e.g. apply=&gt;call */
-        BUILTINS_TRANSFORMED,
-        /** method has been split */
-        SPLIT,
-        /** method has had symbols assigned */
-        SYMBOLS_ASSIGNED,
-        /** computed scope depths for symbols */
-        SCOPE_DEPTHS_COMPUTED,
-        /** method has had types calculated*/
-        OPTIMISTIC_TYPES_ASSIGNED,
-        /** method has had types calculated */
-        LOCAL_VARIABLE_TYPES_CALCULATED,
-        /** compile units reused (optional) */
-        COMPILE_UNITS_REUSED,
-        /** method has been emitted to bytecode */
-        BYTECODE_GENERATED,
-        /** method has been installed */
-        BYTECODE_INSTALLED
-    }
-
     /** Source of entity. */
     private transient final Source source;
 
@@ -144,10 +108,6 @@
     /** Method's namespace. */
     private transient final Namespace namespace;
 
-    /** Current compilation state */
-    @Ignore
-    private final EnumSet<CompilationState> compilationState;
-
     /** Number of properties of "this" object assigned in this function */
     @Ignore
     private final int thisProperties;
@@ -263,6 +223,11 @@
      */
     public static final int NEEDS_CALLEE       = 1 << 26;
 
+    /**
+     * Is the function node cached?
+     */
+    public static final int IS_CACHED = 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 |
@@ -322,7 +287,6 @@
         this.firstToken       = firstToken;
         this.lastToken        = token;
         this.namespace        = namespace;
-        this.compilationState = EnumSet.of(CompilationState.INITIALIZED);
         this.flags            = flags;
         this.compileUnit      = null;
         this.body             = null;
@@ -339,12 +303,11 @@
         final String name,
         final Type returnType,
         final CompileUnit compileUnit,
-        final EnumSet<CompilationState> compilationState,
         final Block body,
         final List<IdentNode> parameters,
         final int thisProperties,
         final Class<?> rootClass,
-        final Source source, Namespace namespace) {
+        final Source source, final Namespace namespace) {
         super(functionNode);
 
         this.endParserState    = endParserState;
@@ -354,7 +317,6 @@
         this.returnType       = returnType;
         this.compileUnit      = compileUnit;
         this.lastToken        = lastToken;
-        this.compilationState = compilationState;
         this.body             = body;
         this.parameters       = parameters;
         this.thisProperties   = thisProperties;
@@ -454,7 +416,6 @@
             name,
             returnType,
             compileUnit,
-            compilationState,
             body,
             parameters,
             thisProperties,
@@ -530,80 +491,6 @@
     }
 
     /**
-     * Get the compilation state of this function
-     * @return the compilation state
-     */
-    public EnumSet<CompilationState> getState() {
-        return compilationState;
-    }
-
-    /**
-     * Check whether this FunctionNode has reached a give CompilationState.
-     *
-     * @param state the state to check for
-     * @return true of the node is in the given state
-     */
-    public boolean hasState(final EnumSet<CompilationState> state) {
-        return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state);
-    }
-
-    /**
-     * Add a state to the total CompilationState of this node, e.g. if
-     * FunctionNode has been lowered, the compiler will add
-     * {@code CompilationState#LOWERED} to the state vector
-     *
-     * @param lc lexical context
-     * @param state {@link CompilationState} to add
-     * @return function node or a new one if state was changed
-     */
-    public FunctionNode setState(final LexicalContext lc, final CompilationState state) {
-        if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) {
-            return this;
-        }
-        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
-        newState.add(state);
-        return setCompilationState(lc, newState);
-    }
-
-    /**
-     * Copy a compilation state from an original function to this function. Used when creating synthetic
-     * function nodes by the splitter.
-     *
-     * @param lc lexical context
-     * @param original the original function node to copy compilation state from
-     * @return function node or a new one if state was changed
-     */
-    public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) {
-        final EnumSet<CompilationState> origState = original.compilationState;
-        if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) {
-            return this;
-        }
-        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
-        newState.addAll(origState);
-        return setCompilationState(lc, newState);
-    }
-
-    private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) {
-        return Node.replaceInLexicalContext(
-                lc,
-                this,
-                new FunctionNode(
-                        this,
-                        lastToken,
-                        endParserState,
-                        flags,
-                        name,
-                        returnType,
-                        compileUnit,
-                        compilationState,
-                        body,
-                        parameters,
-                        thisProperties,
-                        rootClass, source, namespace));
-    }
-
-
-    /**
      * Create a unique name in the namespace of this FunctionNode
      * @param base prefix for name
      * @return base if no collision exists, otherwise a name prefix with base
@@ -668,7 +555,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -748,7 +634,7 @@
      */
     public boolean needsCallee() {
         // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
-        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
+        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasApplyToCallSpecialization();
     }
 
     /**
@@ -765,7 +651,7 @@
      * Return true if function contains an apply to call transform
      * @return true if this function has transformed apply to call
      */
-    public boolean hasOptimisticApplyToCall() {
+    public boolean hasApplyToCallSpecialization() {
         return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
     }
 
@@ -809,7 +695,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -905,7 +790,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -966,7 +850,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1002,7 +885,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1040,7 +922,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1077,6 +958,14 @@
     }
 
     /**
+     * Return the number of parameters to this function
+     * @return the number of parameters
+     */
+    public int getNumOfParams() {
+        return parameters.size();
+    }
+
+    /**
      * Returns the identifier for a named parameter at the specified position in this function's parameter list.
      * @param index the parameter's position.
      * @return the identifier for the requested named parameter.
@@ -1108,7 +997,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1196,7 +1084,6 @@
                 name,
                 type,
                 compileUnit,
-                compilationState,
                 body,
                 parameters,
                 thisProperties,
@@ -1213,6 +1100,24 @@
     }
 
     /**
+     * Returns true if this function node has been cached.
+     * @return true if this function node has been cached.
+     */
+    public boolean isCached() {
+        return getFlag(IS_CACHED);
+    }
+
+    /**
+     * Mark this function node as having been cached.
+     * @param lc the current lexical context
+     * @return a function node equivalent to this one, with the flag set.
+     */
+    public FunctionNode setCached(final LexicalContext lc) {
+        return setFlag(lc, IS_CACHED);
+    }
+
+
+    /**
      * Get the compile unit used to compile this function
      * @see Compiler
      * @return the compile unit
@@ -1244,7 +1149,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1300,7 +1204,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
--- a/src/jdk/nashorn/internal/ir/LiteralNode.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/LiteralNode.java	Thu Oct 29 17:22:12 2015 -0700
@@ -25,11 +25,9 @@
 
 package jdk.nashorn.internal.ir;
 
-import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.codegen.types.ArrayType;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -430,7 +428,7 @@
      *
      * @param token   token
      * @param finish  finish
-     * @param value   undefined value, passed only for polymorphisism discrimination
+     * @param value   undefined value, passed only for polymorphism discrimination
      *
      * @return the new literal node
      */
@@ -561,6 +559,15 @@
         return POSTSET_MARKER;
     }
 
+    /**
+     * Test whether {@code object} represents a constant value.
+     * @param object a node or value object
+     * @return true if object is a constant value
+     */
+    public static boolean isConstant(final Object object) {
+        return objectAsConstant(object) != POSTSET_MARKER;
+    }
+
     private static final class NullLiteralNode extends PrimitiveLiteralNode<Object> {
         private static final long serialVersionUID = 1L;
 
@@ -592,7 +599,7 @@
      * Array literal node class.
      */
     @Immutable
-    public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode {
+    public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode, Splittable {
         private static final long serialVersionUID = 1L;
 
         /** Array element type. */
@@ -604,59 +611,8 @@
         /** Indices of array elements requiring computed post sets. */
         private final int[] postsets;
 
-        /** Sub units with indexes ranges, in which to split up code generation, for large literals */
-        private final List<ArrayUnit> units;
-
-        /**
-         * 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 implements CompileUnitHolder, Serializable {
-            private static final long serialVersionUID = 1L;
-
-            /** Compile unit associated with the postsets range. */
-            private final CompileUnit compileUnit;
-
-            /** postsets range associated with the unit (hi not inclusive). */
-            private final int lo, hi;
-
-            /**
-             * Constructor
-             * @param compileUnit compile unit
-             * @param lo lowest array index in unit
-             * @param hi highest array index in unit + 1
-             */
-            public ArrayUnit(final CompileUnit compileUnit, final int lo, final int hi) {
-                this.compileUnit = compileUnit;
-                this.lo   = lo;
-                this.hi   = hi;
-            }
-
-            /**
-             * Get the high index position of the ArrayUnit (non inclusive)
-             * @return high index position
-             */
-            public int getHi() {
-                return hi;
-            }
-
-            /**
-             * Get the low index position of the ArrayUnit (inclusive)
-             * @return low index position
-             */
-            public int getLo() {
-                return lo;
-            }
-
-            /**
-             * The array compile unit
-             * @return array compile unit
-             */
-            @Override
-            public CompileUnit getCompileUnit() {
-                return compileUnit;
-            }
-        }
+        /** Ranges for splitting up large literals in code generation */
+        private final List<Splittable.SplitRange> splitRanges;
 
         private static final class ArrayLiteralInitializer {
 
@@ -664,7 +620,7 @@
                 final Type elementType = computeElementType(node.value);
                 final int[] postsets = computePostsets(node.value);
                 final Object presets = computePresets(node.value, elementType, postsets);
-                return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.units);
+                return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.splitRanges);
             }
 
             private static Type computeElementType(final Expression[] value) {
@@ -697,7 +653,7 @@
 
                 for (int i = 0; i < value.length; i++) {
                     final Expression element = value[i];
-                    if (element == null || objectAsConstant(element) == POSTSET_MARKER) {
+                    if (element == null || !isConstant(element)) {
                         computed[nComputed++] = i;
                     }
                 }
@@ -814,19 +770,19 @@
             this.elementType = Type.UNKNOWN;
             this.presets     = null;
             this.postsets    = null;
-            this.units       = null;
+            this.splitRanges = null;
         }
 
         /**
          * Copy constructor
          * @param node source array literal node
          */
-        private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<ArrayUnit> units) {
+        private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<Splittable.SplitRange> splitRanges) {
             super(node, value);
             this.elementType = elementType;
             this.postsets    = postsets;
             this.presets     = presets;
-            this.units       = units;
+            this.splitRanges = splitRanges;
         }
 
         /**
@@ -917,26 +873,27 @@
         }
 
         /**
-         * Get the array units that make up this ArrayLiteral
-         * @see ArrayUnit
-         * @return list of array units
+         * Get the split ranges for this ArrayLiteral, or null if this array does not have to be split.
+         * @see Splittable.SplitRange
+         * @return list of split ranges
          */
-        public List<ArrayUnit> getUnits() {
-            return units == null ? null : Collections.unmodifiableList(units);
+        @Override
+        public List<Splittable.SplitRange> getSplitRanges() {
+            return splitRanges == null ? null : Collections.unmodifiableList(splitRanges);
         }
 
         /**
-         * Set the ArrayUnits that make up this ArrayLiteral
+         * Set the SplitRanges that make up this ArrayLiteral
          * @param lc lexical context
-         * @see ArrayUnit
-         * @param units list of array units
-         * @return new or changed arrayliteralnode
+         * @see Splittable.SplitRange
+         * @param splitRanges list of split ranges
+         * @return new or changed node
          */
-        public ArrayLiteralNode setUnits(final LexicalContext lc, final List<ArrayUnit> units) {
-            if (this.units == units) {
+        public ArrayLiteralNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) {
+            if (this.splitRanges == splitRanges) {
                 return this;
             }
-            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
+            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
         }
 
         @Override
@@ -958,7 +915,7 @@
             if (this.value == value) {
                 return this;
             }
-            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
+            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
         }
 
         private ArrayLiteralNode setValue(final LexicalContext lc, final List<Expression> value) {
--- a/src/jdk/nashorn/internal/ir/Node.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/Node.java	Thu Oct 29 17:22:12 2015 -0700
@@ -129,9 +129,17 @@
     public abstract Node accept(NodeVisitor<? extends LexicalContext> visitor);
 
     @Override
-    public String toString() {
+    public final String toString() {
+        return toString(true);
+    }
+
+    /*
+     * Return String representation of this Node.
+     * @param includeTypeInfo include type information or not
+     */
+    public final String toString(final boolean includeTypeInfo) {
         final StringBuilder sb = new StringBuilder();
-        toString(sb);
+        toString(sb, includeTypeInfo);
         return sb.toString();
     }
 
--- a/src/jdk/nashorn/internal/ir/ObjectNode.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/ObjectNode.java	Thu Oct 29 17:22:12 2015 -0700
@@ -27,6 +27,7 @@
 
 import java.util.Collections;
 import java.util.List;
+import java.util.RandomAccess;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -35,12 +36,15 @@
  * IR representation of an object literal.
  */
 @Immutable
-public final class ObjectNode extends Expression {
+public final class ObjectNode extends Expression implements LexicalContextNode, Splittable {
     private static final long serialVersionUID = 1L;
 
     /** Literal elements. */
     private final List<PropertyNode> elements;
 
+    /** Ranges for splitting large literals over multiple compile units in codegen. */
+    private final List<Splittable.SplitRange> splitRanges;
+
     /**
      * Constructor
      *
@@ -51,19 +55,27 @@
     public ObjectNode(final long token, final int finish, final List<PropertyNode> elements) {
         super(token, finish);
         this.elements = elements;
+        this.splitRanges = null;
+        assert elements instanceof RandomAccess : "Splitting requires random access lists";
     }
 
-    private ObjectNode(final ObjectNode objectNode, final List<PropertyNode> elements) {
+    private ObjectNode(final ObjectNode objectNode, final List<PropertyNode> elements,
+                       final List<Splittable.SplitRange> splitRanges ) {
         super(objectNode);
         this.elements = elements;
+        this.splitRanges = splitRanges;
     }
 
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        return Acceptor.accept(this, visitor);
+    }
+
+    @Override
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterObjectNode(this)) {
-            return visitor.leaveObjectNode(setElements(Node.accept(visitor, elements)));
+            return visitor.leaveObjectNode(setElements(lc, Node.accept(visitor, elements)));
         }
-
         return this;
     }
 
@@ -102,10 +114,35 @@
         return Collections.unmodifiableList(elements);
     }
 
-    private ObjectNode setElements(final List<PropertyNode> elements) {
+    private ObjectNode setElements(final LexicalContext lc, final List<PropertyNode> elements) {
         if (this.elements == elements) {
             return this;
         }
-        return new ObjectNode(this, elements);
+        return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, this.splitRanges));
     }
+
+    /**
+     * Set the split ranges for this ObjectNode
+     * @see Splittable.SplitRange
+     * @param lc the lexical context
+     * @param splitRanges list of split ranges
+     * @return new or changed object node
+     */
+    public ObjectNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) {
+        if (this.splitRanges == splitRanges) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, splitRanges));
+    }
+
+    /**
+     * Get the split ranges for this ObjectNode, or null if the object is not split.
+     * @see Splittable.SplitRange
+     * @return list of split ranges
+     */
+    @Override
+    public List<Splittable.SplitRange> getSplitRanges() {
+        return splitRanges == null ? null : Collections.unmodifiableList(splitRanges);
+    }
+
 }
--- a/src/jdk/nashorn/internal/ir/RuntimeNode.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java	Thu Oct 29 17:22:12 2015 -0700
@@ -56,6 +56,8 @@
         REFERENCE_ERROR,
         /** Delete operator */
         DELETE(TokenType.DELETE, Type.BOOLEAN, 1),
+        /** Delete operator for slow scopes */
+        SLOW_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false),
         /** Delete operator that always fails -- see Lower */
         FAIL_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false),
         /** === operator with at least one object */
@@ -274,7 +276,7 @@
          *
          * @param request a request
          *
-         * @return the inverted rquest, or null if not applicable
+         * @return the inverted request, or null if not applicable
          */
         public static Request invert(final Request request) {
             switch (request) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/ir/Splittable.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.io.Serializable;
+import java.util.List;
+import jdk.nashorn.internal.codegen.CompileUnit;
+
+/**
+ * An interface for splittable expressions.
+ */
+public interface Splittable {
+
+    /**
+     * Get a list of split ranges for this splittable expression, or null
+     * if the expression should not be split.
+     *
+     * @return a list of split ranges
+     */
+    List<SplitRange> getSplitRanges();
+
+    /**
+     * A SplitRange is a range in a splittable expression. It defines the
+     * boundaries of the split range and provides a compile unit for code generation.
+     */
+    final class SplitRange implements CompileUnitHolder, Serializable {
+        private static final long serialVersionUID = 1L;
+
+        /** Compile unit associated with the postsets range. */
+        private final CompileUnit compileUnit;
+
+        /** postsets range associated with the unit (hi not inclusive). */
+        private final int low, high;
+
+        /**
+         * Constructor
+         * @param compileUnit compile unit
+         * @param low lowest array index in unit
+         * @param high highest array index in unit + 1
+         */
+        public SplitRange(final CompileUnit compileUnit, final int low, final int high) {
+            this.compileUnit = compileUnit;
+            this.low   = low;
+            this.high   = high;
+        }
+
+        /**
+         * Get the high index position of the ArrayUnit (exclusive)
+         * @return high index position
+         */
+        public int getHigh() {
+            return high;
+        }
+
+        /**
+         * Get the low index position of the ArrayUnit (inclusive)
+         * @return low index position
+         */
+        public int getLow() {
+            return low;
+        }
+
+        /**
+         * The array compile unit
+         * @return array compile unit
+         */
+        @Override
+        public CompileUnit getCompileUnit() {
+            return compileUnit;
+        }
+    }
+}
--- a/src/jdk/nashorn/internal/ir/SwitchNode.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/SwitchNode.java	Thu Oct 29 17:22:12 2015 -0700
@@ -53,7 +53,7 @@
     private final boolean uniqueInteger;
 
     /** Tag symbol. */
-    private Symbol tag;
+    private final Symbol tag;
 
     /**
      * Constructor
@@ -71,15 +71,16 @@
         this.cases            = cases;
         this.defaultCaseIndex = defaultCase == null ? -1 : cases.indexOf(defaultCase);
         this.uniqueInteger    = false;
+        this.tag = null;
     }
 
     private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases,
-            final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger) {
+            final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger, final Symbol tag) {
         super(switchNode, conversion);
         this.expression       = expression;
         this.cases            = cases;
         this.defaultCaseIndex = defaultCaseIndex;
-        this.tag              = switchNode.getTag(); //TODO are symbols inherited as references?
+        this.tag              = tag;
         this.uniqueInteger    = uniqueInteger;
     }
 
@@ -89,7 +90,7 @@
         for (final CaseNode caseNode : cases) {
             newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody(), caseNode.getLocalVariableConversion()));
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     @Override
@@ -157,7 +158,7 @@
         if (this.cases == cases) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     /**
@@ -189,7 +190,7 @@
         if (this.expression == expression) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     /**
@@ -204,10 +205,15 @@
     /**
      * Set the tag symbol for this switch. The tag symbol is where
      * the switch expression result is stored
+     * @param lc lexical context
      * @param tag a symbol
+     * @return a switch node with the symbol set
      */
-    public void setTag(final Symbol tag) {
-        this.tag = tag;
+    public SwitchNode setTag(final LexicalContext lc, final Symbol tag) {
+        if (this.tag == tag) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     /**
@@ -229,12 +235,12 @@
         if(this.uniqueInteger == uniqueInteger) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     @Override
     JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
 }
--- a/src/jdk/nashorn/internal/ir/Symbol.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/Symbol.java	Thu Oct 29 17:22:12 2015 -0700
@@ -25,7 +25,10 @@
 
 package jdk.nashorn.internal.ir;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.io.PrintWriter;
+import java.io.Serializable;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.StringTokenizer;
@@ -47,7 +50,9 @@
  * refer to their location.
  */
 
-public final class Symbol implements Comparable<Symbol> {
+public final class Symbol implements Comparable<Symbol>, Cloneable, Serializable {
+    private static final long serialVersionUID = 1L;
+
     /** Is this Global */
     public static final int IS_GLOBAL   = 1;
     /** Is this a variable */
@@ -94,10 +99,10 @@
 
     /** First bytecode method local variable slot for storing the value(s) of this variable. -1 indicates the variable
      * is not stored in local variable slots or it is not yet known. */
-    private int firstSlot = -1;
+    private transient int firstSlot = -1;
 
     /** Field number in scope or property; array index in varargs when not using arguments object. */
-    private int fieldIndex = -1;
+    private transient int fieldIndex = -1;
 
     /** Number of times this symbol is used in code */
     private int useCount;
@@ -144,6 +149,15 @@
         }
     }
 
+    @Override
+    public Symbol clone() {
+        try {
+            return (Symbol)super.clone();
+        } catch (final CloneNotSupportedException e) {
+            throw new AssertionError(e);
+        }
+    }
+
     private static String align(final String string, final int max) {
         final StringBuilder sb = new StringBuilder();
         sb.append(string.substring(0, Math.min(string.length(), max)));
@@ -337,7 +351,7 @@
      * Flag this symbol as scope as described in {@link Symbol#isScope()}
      * @return the symbol
      */
-     public Symbol setIsScope() {
+    public Symbol setIsScope() {
         if (!isScope()) {
             if(shouldTrace()) {
                 trace("SET IS SCOPE");
@@ -609,11 +623,11 @@
 
     /**
      * Increase the symbol's use count by one.
-     * @return the symbol
      */
-    public Symbol increaseUseCount() {
-        useCount++;
-        return this;
+    public void increaseUseCount() {
+        if (isScope()) { // Avoid dirtying a cache line; we only need the use count for scoped symbols
+            useCount++;
+        }
     }
 
     /**
@@ -669,4 +683,10 @@
             new Throwable().printStackTrace(Context.getCurrentErr());
         }
     }
+
+    private void readObject(final ObjectInputStream in) throws ClassNotFoundException, IOException {
+        in.defaultReadObject();
+        firstSlot = -1;
+        fieldIndex = -1;
+    }
 }
--- a/src/jdk/nashorn/internal/ir/TryNode.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/TryNode.java	Thu Oct 29 17:22:12 2015 -0700
@@ -65,7 +65,7 @@
     private final List<Block> inlinedFinallies;
 
     /** Exception symbol. */
-    private Symbol exception;
+    private final Symbol exception;
 
     private final LocalVariableConversion conversion;
 
@@ -86,22 +86,23 @@
         this.finallyBody = finallyBody;
         this.conversion  = null;
         this.inlinedFinallies = Collections.emptyList();
+        this.exception = null;
     }
 
-    private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies) {
+    private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies, final Symbol exception) {
         super(tryNode);
         this.body        = body;
         this.catchBlocks = catchBlocks;
         this.finallyBody = finallyBody;
         this.conversion  = conversion;
         this.inlinedFinallies = inlinedFinallies;
-        this.exception = tryNode.exception;
+        this.exception = exception;
     }
 
     @Override
     public Node ensureUniqueLabels(final LexicalContext lc) {
         //try nodes are never in lex context
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies);
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception);
     }
 
     @Override
@@ -160,7 +161,7 @@
         if (this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new TryNode(this,  body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this,  body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
     }
 
     /**
@@ -197,7 +198,7 @@
         if (this.catchBlocks == catchBlocks) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
     }
 
     /**
@@ -209,12 +210,15 @@
     }
     /**
      * Set the exception symbol for this try block
+     * @param lc lexical context
      * @param exception a symbol for the compiler to store the exception in
      * @return new TryNode or same if unchanged
      */
-    public TryNode setException(final Symbol exception) {
-        this.exception = exception;
-        return this;
+    public TryNode setException(final LexicalContext lc, final Symbol exception) {
+        if (this.exception == exception) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
     }
 
     /**
@@ -277,7 +281,7 @@
         if (this.finallyBody == finallyBody) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
     }
 
     /**
@@ -293,7 +297,7 @@
             return this;
         }
         assert checkInlinedFinallies(inlinedFinallies);
-        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
     }
 
     private static boolean checkInlinedFinallies(final List<Block> inlinedFinallies) {
@@ -314,7 +318,7 @@
         if(this.conversion == conversion) {
             return this;
         }
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies);
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception);
     }
 
     @Override
--- a/src/jdk/nashorn/internal/ir/VarNode.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/VarNode.java	Thu Oct 29 17:22:12 2015 -0700
@@ -262,12 +262,4 @@
     public boolean isFunctionDeclaration() {
         return init instanceof FunctionNode && ((FunctionNode)init).isDeclared();
     }
-
-    /**
-     * Returns true if this is an anonymous function declaration.
-     * @return true if this is an anonymous function declaration.
-     */
-    public boolean isAnonymousFunctionDeclaration() {
-        return isFunctionDeclaration() && ((FunctionNode)init).isAnonymous();
-    }
 }
--- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Thu Oct 29 17:22:12 2015 -0700
@@ -48,7 +48,6 @@
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 import jdk.nashorn.internal.ir.LabelNode;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ObjectNode;
@@ -65,7 +64,7 @@
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.parser.JSONParser;
 import jdk.nashorn.internal.parser.Lexer.RegexToken;
 import jdk.nashorn.internal.parser.Parser;
@@ -77,7 +76,7 @@
 /**
  * This IR writer produces a JSON string that represents AST as a JSON string.
  */
-public final class JSONWriter extends NodeVisitor<LexicalContext> {
+public final class JSONWriter extends SimpleNodeVisitor {
 
     /**
      * Returns AST as JSON compatible string.
@@ -939,7 +938,6 @@
     // Internals below
 
     private JSONWriter(final boolean includeLocation) {
-        super(new LexicalContext());
         this.buf             = new StringBuilder();
         this.includeLocation = includeLocation;
     }
--- a/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java	Thu Oct 29 17:22:12 2015 -0700
@@ -36,7 +36,7 @@
 import jdk.nashorn.internal.ir.debug.NashornTextifier.NashornLabel;
 
 /**
- * Subclass of the ASM classs reader that retains more info, such
+ * Subclass of the ASM class reader that retains more info, such
  * as bytecode offsets
  */
 public class NashornClassReader extends ClassReader {
--- a/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -193,7 +193,7 @@
     }
 
     /**
-     * Get the class histograpm
+     * Get the class histogram
      * @return class histogram element list
      */
     public List<ClassHistogramElement> getClassHistogram() {
--- a/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Thu Oct 29 17:22:12 2015 -0700
@@ -41,7 +41,6 @@
 import jdk.nashorn.internal.ir.JoinPredecessor;
 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 import jdk.nashorn.internal.ir.LabelNode;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LocalVariableConversion;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.SplitNode;
@@ -53,7 +52,7 @@
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 
 /**
  * Print out the AST as human readable source code.
@@ -61,7 +60,7 @@
  *
  * see the flags --print-parse and --print-lower-parse
  */
-public final class PrintVisitor extends NodeVisitor<LexicalContext> {
+public final class PrintVisitor extends SimpleNodeVisitor {
     /** Tab width */
     private static final int TABWIDTH = 4;
 
@@ -96,7 +95,6 @@
      * @param printTypes        should we print optimistic and inferred types?
      */
     public PrintVisitor(final boolean printLineNumbers, final boolean printTypes) {
-        super(new LexicalContext());
         this.EOLN             = System.lineSeparator();
         this.sb               = new StringBuilder();
         this.printLineNumbers = printLineNumbers;
--- a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Thu Oct 29 17:22:12 2015 -0700
@@ -34,7 +34,7 @@
  * Like NodeVisitor but navigating further into operators.
  * @param <T> Lexical context class for this NodeOperatorVisitor
  */
-public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> {
+public abstract class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> {
     /**
      * Constructor
      *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/ir/visitor/SimpleNodeVisitor.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 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.visitor;
+
+import jdk.nashorn.internal.ir.LexicalContext;
+
+/**
+ * Convenience base class for a {@link NodeVisitor} with a plain {@link LexicalContext}.
+ */
+public abstract class SimpleNodeVisitor extends NodeVisitor<LexicalContext> {
+
+    /**
+     * Creates a new simple node visitor.
+     */
+    public SimpleNodeVisitor() {
+        super(new LexicalContext());
+    }
+}
--- a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java	Thu Oct 29 17:22:12 2015 -0700
@@ -131,8 +131,8 @@
     static Object traceReturn(final DebugLogger logger, final Object value) {
         final String str = "    return" +
                 (VOID_TAG.equals(value) ?
-                    ";" :
-                    " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
+                        ";" :
+                            " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
         if (logger == null) {
             err(str);
         } else if (logger.isEnabled()) {
@@ -164,13 +164,13 @@
             }
 
             sb.append('\'').
-                append(stripName(argString(args[i]))).
-                append('\'').
-                append(' ').
-                append('[').
-                append("type=").
-                append(args[i] == null ? "null" : stripName(args[i].getClass())).
-                append(']');
+            append(stripName(argString(args[i]))).
+            append('\'').
+            append(' ').
+            append('[').
+            append("type=").
+            append(args[i] == null ? "null" : stripName(args[i].getClass())).
+            append(']');
 
             if (i + 1 < args.length) {
                 sb.append(", ");
@@ -216,8 +216,8 @@
 
         if (arg instanceof ScriptObject) {
             return arg.toString() +
-                " (map=" + Debug.id(((ScriptObject)arg).getMap()) +
-                ')';
+                    " (map=" + Debug.id(((ScriptObject)arg).getMap()) +
+                    ')';
         }
 
         return arg.toString();
@@ -262,7 +262,7 @@
         return addDebugPrintout(null, Level.OFF, mh, paramStart, printReturnValue, tag);
     }
 
-     /**
+    /**
      * Add a debug printout to a method handle, tracing parameters and return values
      *
      * @param logger a specific logger to which to write the output
@@ -278,7 +278,7 @@
 
         //if there is no logger, or if it's set to log only coarser events
         //than the trace level, skip and return
-        if (logger != null && logger.levelCoarserThan(level)) {
+        if (logger == null || !logger.isLoggable(level)) {
             return mh;
         }
 
@@ -289,9 +289,9 @@
         trace = MethodHandles.foldArguments(
                 mh,
                 trace.asCollector(
-                    Object[].class,
-                    type.parameterCount()).
-                asType(type.changeReturnType(void.class)));
+                        Object[].class,
+                        type.parameterCount()).
+                        asType(type.changeReturnType(void.class)));
 
         final Class<?> retType = type.returnType();
         if (printReturnValue) {
@@ -299,7 +299,7 @@
                 final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN, 0, logger);
                 trace = MethodHandles.filterReturnValue(trace,
                         traceReturn.asType(
-                            traceReturn.type().changeParameterType(0, retType).changeReturnType(retType)));
+                                traceReturn.type().changeParameterType(0, retType).changeReturnType(retType)));
             } else {
                 trace = MethodHandles.filterReturnValue(trace, MethodHandles.insertArguments(TRACE_RETURN_VOID, 0, logger));
             }
@@ -355,9 +355,9 @@
                     sb.append("] ");
                 } else {
                     sb.append(d)
-                        .append('{')
-                        .append(Integer.toHexString(System.identityHashCode(d)))
-                        .append('}');
+                    .append('{')
+                    .append(Integer.toHexString(System.identityHashCode(d)))
+                    .append('}');
                 }
 
                 if (i + 1 < data.length) {
--- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Thu Oct 29 17:22:12 2015 -0700
@@ -192,7 +192,7 @@
         /**
          * Factory method for array data
          *
-         * @param nb    underlying nativebuffer
+         * @param nb    underlying native buffer
          * @param start start element
          * @param end   end element
          *
--- a/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java	Fri Oct 16 12:19:59 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.objects;
-
-import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptFunctionData;
-import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
-
-/**
- * A {@code ScriptFunctionImpl} subclass for functions created using {@code Function.prototype.bind}. Such functions
- * must track their {@code [[TargetFunction]]} property for purposes of correctly implementing {@code [[HasInstance]]};
- * see {@link ScriptFunction#isInstance(ScriptObject)}.
- */
-final class BoundScriptFunctionImpl extends ScriptFunctionImpl {
-    private final ScriptFunction targetFunction;
-
-    BoundScriptFunctionImpl(final ScriptFunctionData data, final ScriptFunction targetFunction) {
-        super(data, Global.instance());
-        setPrototype(ScriptRuntime.UNDEFINED);
-        this.targetFunction = targetFunction;
-    }
-
-    @Override
-    protected ScriptFunction getTargetFunction() {
-        return targetFunction;
-    }
-}
--- a/src/jdk/nashorn/internal/objects/Global.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/Global.java	Thu Oct 29 17:22:12 2015 -0700
@@ -88,14 +88,14 @@
  */
 @ScriptClass("Global")
 public final class Global extends Scope {
-    // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
-    private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
+    // This special value is used to flag a lazily initialized global property.
+    // This also serves as placeholder value used in place of a location property
+    // (__FILE__, __DIR__, __LINE__)
+    private static final Object LAZY_SENTINEL = new Object();
+
     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
 
-    // placeholder value for lazily initialized global objects
-    private static final Object LAZY_SENTINEL = new Object();
-
     /**
      * Optimistic builtin names that require switchpoint invalidation
      * upon assignment. Overly conservative, but works for now, to avoid
@@ -182,15 +182,15 @@
 
     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final double NaN = Double.NaN;
+    public static final double NaN = Double.NaN;
 
     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final double Infinity = Double.POSITIVE_INFINITY;
+    public static final double Infinity = Double.POSITIVE_INFINITY;
 
     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object undefined = UNDEFINED;
+    public static final Object undefined = UNDEFINED;
 
     /** ECMA 15.1.2.1 eval(x) */
     @Property(attributes = Attribute.NOT_ENUMERABLE)
@@ -830,15 +830,15 @@
 
     /** Nashorn extension: current script's file name */
     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
+    public static final Object __FILE__ = LAZY_SENTINEL;
 
     /** Nashorn extension: current script's directory */
     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
+    public static final Object __DIR__ = LAZY_SENTINEL;
 
     /** Nashorn extension: current source line number being executed */
     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
+    public static final Object __LINE__ = LAZY_SENTINEL;
 
     private volatile NativeDate DEFAULT_DATE;
 
@@ -928,8 +928,6 @@
     private ThreadLocal<ScriptContext> scontext;
     // current ScriptEngine associated - can be null.
     private ScriptEngine engine;
-    // initial ScriptContext - can be null
-    private volatile ScriptContext initscontext;
 
     // ES6 global lexical scope.
     private final LexicalScope lexicalScope;
@@ -957,7 +955,7 @@
 
     private ScriptContext currentContext() {
         final ScriptContext sc = scontext != null? scontext.get() : null;
-        return sc == null? initscontext : sc;
+        return (sc != null)? sc : (engine != null? engine.getContext() : null);
     }
 
     @Override
@@ -1067,16 +1065,14 @@
      * of the global scope object.
      *
      * @param eng ScriptEngine to initialize
-     * @param ctxt ScriptContext to initialize
      */
-    public void initBuiltinObjects(final ScriptEngine eng, final ScriptContext ctxt) {
+    public void initBuiltinObjects(final ScriptEngine eng) {
         if (this.builtinObject != null) {
             // already initialized, just return
             return;
         }
 
         this.engine = eng;
-        this.initscontext = ctxt;
         if (this.engine != null) {
             this.scontext = new ThreadLocal<>();
         }
@@ -1583,7 +1579,11 @@
         return ScriptFunction.getPrototype(builtinObject);
     }
 
-    ScriptObject getFunctionPrototype() {
+    /**
+     * Get the builtin Function prototype.
+     * @return the Function.prototype.
+     */
+    public ScriptObject getFunctionPrototype() {
         return ScriptFunction.getPrototype(builtinFunction);
     }
 
@@ -1768,36 +1768,13 @@
         return ScriptFunction.getPrototype(getBuiltinFloat64Array());
     }
 
-    private ScriptFunction getBuiltinArray() {
-        return builtinArray;
-    }
-
-    ScriptFunction getTypeErrorThrower() {
-        return typeErrorThrower;
-    }
-
     /**
-     * Called from compiled script code to test if builtin has been overridden
+     * Return the function that throws TypeError unconditionally. Used as "poison" methods for certain Function properties.
      *
-     * @return true if builtin array has not been overridden
+     * @return the TypeError throwing function
      */
-    public static boolean isBuiltinArray() {
-        final Global instance = Global.instance();
-        return instance.array == instance.getBuiltinArray();
-    }
-
-    private ScriptFunction getBuiltinBoolean() {
-        return builtinBoolean;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin boolean has not been overridden
-     */
-    public static boolean isBuiltinBoolean() {
-        final Global instance = Global.instance();
-        return instance._boolean == instance.getBuiltinBoolean();
+    public ScriptFunction getTypeErrorThrower() {
+        return typeErrorThrower;
     }
 
     private synchronized ScriptFunction getBuiltinDate() {
@@ -1810,30 +1787,6 @@
         return this.builtinDate;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin date has not been overridden
-     */
-    public static boolean isBuiltinDate() {
-        final Global instance = Global.instance();
-        return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate();
-    }
-
-    private ScriptFunction getBuiltinError() {
-        return builtinError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin error has not been overridden
-     */
-    public static boolean isBuiltinError() {
-        final Global instance = Global.instance();
-        return instance.error == instance.getBuiltinError();
-    }
-
     private synchronized ScriptFunction getBuiltinEvalError() {
         if (this.builtinEvalError == null) {
             this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
@@ -1841,31 +1794,11 @@
         return this.builtinEvalError;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin eval error has not been overridden
-     */
-    public static boolean isBuiltinEvalError() {
-        final Global instance = Global.instance();
-        return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError();
-    }
-
     private ScriptFunction getBuiltinFunction() {
         return builtinFunction;
     }
 
     /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin function has not been overridden
-     */
-    public static boolean isBuiltinFunction() {
-        final Global instance = Global.instance();
-        return instance.function == instance.getBuiltinFunction();
-    }
-
-    /**
      * Get the switchpoint used to check property changes for Function.prototype.apply
      * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
      */
@@ -1906,16 +1839,6 @@
         return builtinJSAdapter;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin JSAdapter has not been overridden
-     */
-    public static boolean isBuiltinJSAdapter() {
-        final Global instance = Global.instance();
-        return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter();
-    }
-
     private synchronized ScriptObject getBuiltinJSON() {
         if (this.builtinJSON == null) {
             this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
@@ -1923,44 +1846,6 @@
         return this.builtinJSON;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin JSON has has not been overridden
-     */
-    public static boolean isBuiltinJSON() {
-        final Global instance = Global.instance();
-        return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON();
-    }
-
-    private ScriptObject getBuiltinJava() {
-        return builtinJava;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Java has not been overridden
-     */
-    public static boolean isBuiltinJava() {
-        final Global instance = Global.instance();
-        return instance.java == instance.getBuiltinJava();
-    }
-
-    private ScriptObject getBuiltinJavax() {
-        return builtinJavax;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Javax has not been overridden
-     */
-    public static boolean isBuiltinJavax() {
-        final Global instance = Global.instance();
-        return instance.javax == instance.getBuiltinJavax();
-    }
-
     private synchronized ScriptFunction getBuiltinJavaImporter() {
         if (this.builtinJavaImporter == null) {
             this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
@@ -1975,68 +1860,6 @@
         return this.builtinJavaApi;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Java importer has not been overridden
-     */
-    public static boolean isBuiltinJavaImporter() {
-        final Global instance = Global.instance();
-        return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter();
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin math has not been overridden
-     */
-    public static boolean isBuiltinMath() {
-        final Global instance = Global.instance();
-        return instance.math == instance.builtinMath;
-    }
-
-    private ScriptFunction getBuiltinNumber() {
-        return builtinNumber;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin number has not been overridden
-     */
-    public static boolean isBuiltinNumber() {
-        final Global instance = Global.instance();
-        return instance.number == instance.getBuiltinNumber();
-    }
-
-    private ScriptFunction getBuiltinObject() {
-        return builtinObject;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin object has not been overridden
-     */
-    public static boolean isBuiltinObject() {
-        final Global instance = Global.instance();
-        return instance.object == instance.getBuiltinObject();
-    }
-
-    private ScriptObject getBuiltinPackages() {
-        return builtinPackages;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin package has not been overridden
-     */
-    public static boolean isBuiltinPackages() {
-        final Global instance = Global.instance();
-        return instance.packages == instance.getBuiltinPackages();
-    }
-
     private synchronized ScriptFunction getBuiltinRangeError() {
         if (this.builtinRangeError == null) {
             this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
@@ -2044,30 +1867,6 @@
         return builtinRangeError;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin range error has not been overridden
-     */
-    public static boolean isBuiltinRangeError() {
-        final Global instance = Global.instance();
-        return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError();
-    }
-
-    private synchronized ScriptFunction getBuiltinReferenceError() {
-        return builtinReferenceError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin reference error has not been overridden
-     */
-    public static boolean isBuiltinReferenceError() {
-        final Global instance = Global.instance();
-        return instance.referenceError == instance.getBuiltinReferenceError();
-    }
-
     private synchronized ScriptFunction getBuiltinRegExp() {
         if (this.builtinRegExp == null) {
             this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
@@ -2081,58 +1880,6 @@
         return builtinRegExp;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin regexp has not been overridden
-     */
-    public static boolean isBuiltinRegExp() {
-        final Global instance = Global.instance();
-        return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp();
-    }
-
-    private ScriptFunction getBuiltinString() {
-        return builtinString;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Java has not been overridden
-     */
-    public static boolean isBuiltinString() {
-        final Global instance = Global.instance();
-        return instance.string == instance.getBuiltinString();
-    }
-
-    private ScriptFunction getBuiltinSyntaxError() {
-        return builtinSyntaxError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin syntax error has not been overridden
-     */
-    public static boolean isBuiltinSyntaxError() {
-        final Global instance = Global.instance();
-        return instance.syntaxError == instance.getBuiltinSyntaxError();
-    }
-
-    private ScriptFunction getBuiltinTypeError() {
-        return builtinTypeError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin type error has not been overridden
-     */
-    public static boolean isBuiltinTypeError() {
-        final Global instance = Global.instance();
-        return instance.typeError == instance.getBuiltinTypeError();
-    }
-
     private synchronized ScriptFunction getBuiltinURIError() {
         if (this.builtinURIError == null) {
             this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
@@ -2140,16 +1887,6 @@
         return this.builtinURIError;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin URI error has not been overridden
-     */
-    public static boolean isBuiltinURIError() {
-        final Global instance = Global.instance();
-        return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError();
-    }
-
     @Override
     public String getClassName() {
         return "global";
@@ -2288,7 +2025,7 @@
      * @return true if the value is a placeholder, false otherwise.
      */
     public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
-        return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
+        return placeholder == LAZY_SENTINEL;
     }
 
     /**
@@ -2386,17 +2123,18 @@
             }
         }
 
+        final boolean extensible = isExtensible();
         for (final jdk.nashorn.internal.runtime.Property property : properties) {
             if (property.isLexicalBinding()) {
                 assert lexScope != null;
-                lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property);
+                lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property, true);
 
                 if (ownMap.findProperty(property.getKey()) != null) {
                     // If property exists in the global object invalidate any global constant call sites.
                     invalidateGlobalConstant(property.getKey());
                 }
             } else {
-                ownMap = addBoundProperty(ownMap, source, property);
+                ownMap = addBoundProperty(ownMap, source, property, extensible);
             }
         }
 
@@ -2424,7 +2162,7 @@
 
         // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
         // because those are invalidated per-key in the addBoundProperties method above.
-        // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
+        // We therefore check if the invocation does already have a switchpoint and the property is non-inherited,
         // assuming this only applies to global constants. If other non-inherited properties will
         // start using switchpoints some time in the future we'll have to revisit this.
         if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
@@ -2469,10 +2207,10 @@
      * Adds jjs shell interactive mode builtin functions to global scope.
      */
     public void addShellBuiltins() {
-        Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT);
+        Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT);
         addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
 
-        value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT);
+        value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT);
         addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
     }
 
@@ -2519,35 +2257,35 @@
         this.setInitialProto(getObjectPrototype());
 
         // initialize global function properties
-        this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
-
-        this.parseInt = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
+        this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL);
+
+        this.parseInt = ScriptFunction.createBuiltin("parseInt",   GlobalFunctions.PARSEINT,
                     new Specialization[] {
                     new Specialization(GlobalFunctions.PARSEINT_Z),
                     new Specialization(GlobalFunctions.PARSEINT_I),
                     new Specialization(GlobalFunctions.PARSEINT_J),
                     new Specialization(GlobalFunctions.PARSEINT_OI),
                     new Specialization(GlobalFunctions.PARSEINT_O) });
-        this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
-        this.isNaN = ScriptFunctionImpl.makeFunction("isNaN",   GlobalFunctions.IS_NAN,
+        this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
+        this.isNaN = ScriptFunction.createBuiltin("isNaN",   GlobalFunctions.IS_NAN,
                    new Specialization[] {
                         new Specialization(GlobalFunctions.IS_NAN_I),
                         new Specialization(GlobalFunctions.IS_NAN_J),
                         new Specialization(GlobalFunctions.IS_NAN_D) });
-        this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
-        this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
-        this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
-        this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
-        this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
-        this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
-        this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
-        this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
-        this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
-        this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
-        this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
-        this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
-        this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
-        this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
+        this.parseFloat         = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
+        this.isNaN              = ScriptFunction.createBuiltin("isNaN",      GlobalFunctions.IS_NAN);
+        this.isFinite           = ScriptFunction.createBuiltin("isFinite",   GlobalFunctions.IS_FINITE);
+        this.encodeURI          = ScriptFunction.createBuiltin("encodeURI",  GlobalFunctions.ENCODE_URI);
+        this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
+        this.decodeURI          = ScriptFunction.createBuiltin("decodeURI",  GlobalFunctions.DECODE_URI);
+        this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
+        this.escape             = ScriptFunction.createBuiltin("escape",     GlobalFunctions.ESCAPE);
+        this.unescape           = ScriptFunction.createBuiltin("unescape",   GlobalFunctions.UNESCAPE);
+        this.print              = ScriptFunction.createBuiltin("print",      env._print_no_newline ? PRINT : PRINTLN);
+        this.load               = ScriptFunction.createBuiltin("load",       LOAD);
+        this.loadWithNewGlobal  = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
+        this.exit               = ScriptFunction.createBuiltin("exit",       EXIT);
+        this.quit               = ScriptFunction.createBuiltin("quit",       EXIT);
 
         // built-in constructors
         this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
@@ -2627,7 +2365,7 @@
             // default file name
             addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
             // __noSuchProperty__ hook for ScriptContext search of missing variables
-            final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
+            final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
             addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
         }
     }
@@ -2638,17 +2376,17 @@
         final ScriptObject errorProto = getErrorPrototype();
 
         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
-        final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
-        final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
+        final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK);
+        final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK);
         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
-        final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
-        final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
+        final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER);
+        final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER);
         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
-        final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
-        final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
+        final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER);
+        final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER);
         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
-        final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
-        final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
+        final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME);
+        final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME);
         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
 
         // ECMA 15.11.4.2 Error.prototype.name
@@ -2687,20 +2425,22 @@
     }
 
     private void initScripting(final ScriptEnvironment scriptEnv) {
-        Object value;
-        value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
+        ScriptObject value;
+        value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE);
         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
 
-        value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
+        value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY);
         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
 
         final String execName = ScriptingFunctions.EXEC_NAME;
-        value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
+        value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC);
+        value.addOwnProperty(ScriptingFunctions.THROW_ON_ERROR_NAME, Attribute.NOT_ENUMERABLE, false);
+
         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
 
         // Nashorn extension: global.echo (scripting-mode-only)
         // alias for "print"
-        value = get("print");
+        value = (ScriptObject)get("print");
         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
 
         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
@@ -2876,7 +2616,7 @@
         this.builtinFunction = initConstructor("Function", ScriptFunction.class);
 
         // create global anonymous function
-        final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
+        final ScriptFunction anon = ScriptFunction.createAnonymous();
         // need to copy over members of Function.prototype to anon function
         anon.addBoundProperties(getFunctionPrototype());
 
@@ -2888,10 +2628,7 @@
         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
 
         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
-        this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
-        typeErrorThrower.setPrototype(UNDEFINED);
-        // Non-constructor built-in functions do not have "prototype" property
-        typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
+        this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER);
         typeErrorThrower.preventExtensions();
 
         // now initialize Object
@@ -2902,8 +2639,8 @@
 
         // ES6 draft compliant __proto__ property of Object.prototype
         // accessors on Object.prototype for "__proto__"
-        final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
-        final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
+        final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__);
+        final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__);
         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
 
         // Function valued properties of Function.prototype were not properly
@@ -2999,9 +2736,9 @@
         }
 
         @Override
-        protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
+        protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property, final boolean extensible) {
             // We override this method just to make it callable by Global
-            return super.addBoundProperty(propMap, source, property);
+            return super.addBoundProperty(propMap, source, property, extensible);
         }
 
         private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
--- a/src/jdk/nashorn/internal/objects/NativeDataView.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeDataView.java	Thu Oct 29 17:22:12 2015 -0700
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package jdk.nashorn.internal.objects;
 
 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
--- a/src/jdk/nashorn/internal/objects/NativeDebug.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeDebug.java	Thu Oct 29 17:22:12 2015 -0700
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.objects;
 
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
 import java.io.PrintWriter;
 import java.util.LinkedList;
 import java.util.Objects;
@@ -246,7 +247,7 @@
         final PrintWriter out = Context.getCurrentErr();
 
         out.println("ScriptObject count " + ScriptObject.getCount());
-        out.println("Scope count " + Scope.getCount());
+        out.println("Scope count " + Scope.getScopeCount());
         out.println("ScriptObject listeners added " + PropertyListeners.getListenersAdded());
         out.println("ScriptObject listeners removed " + PropertyListeners.getListenersRemoved());
         out.println("ScriptFunction constructor calls " + ScriptFunction.getConstructorCount());
--- a/src/jdk/nashorn/internal/objects/NativeError.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeError.java	Thu Oct 29 17:22:12 2015 -0700
@@ -150,8 +150,8 @@
         initException(sobj);
         sobj.delete(STACK, false);
         if (! sobj.has("stack")) {
-            final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK);
-            final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK);
+            final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", GET_STACK);
+            final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", SET_STACK);
             sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
         }
         return UNDEFINED;
--- a/src/jdk/nashorn/internal/objects/NativeFunction.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeFunction.java	Thu Oct 29 17:22:12 2015 -0700
@@ -108,7 +108,7 @@
         throw new AssertionError("Should not reach here");
     }
 
-     /**
+    /**
      * Given an array-like object, converts it into a Java object array suitable for invocation of ScriptRuntime.apply
      * or for direct invocation of the applied function.
      * @param array the array-like object. Can be null in which case a zero-length array is created.
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Thu Oct 29 17:22:12 2015 -0700
@@ -621,13 +621,13 @@
             if (find != null) {
                 final Object value = find.getObjectValue();
                 if (value instanceof ScriptFunction) {
-                    final ScriptFunctionImpl func = (ScriptFunctionImpl)value;
+                    final ScriptFunction func = (ScriptFunction)value;
                     // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound
                     // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
                     return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
-                            func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
+                            func.createBound(this, new Object[] { name })), 0, Object.class),
                             testJSAdaptor(adaptee, null, null, null),
-                            adaptee.getProtoSwitchPoint(__call__, find.getOwner()));
+                            adaptee.getProtoSwitchPoints(__call__, find.getOwner()), null);
                 }
             }
             throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
@@ -698,7 +698,7 @@
                     return new GuardedInvocation(
                             methodHandle,
                             testJSAdaptor(adaptee, findData.getGetter(Object.class, INVALID_PROGRAM_POINT, null), findData.getOwner(), func),
-                            adaptee.getProtoSwitchPoint(hook, findData.getOwner()));
+                            adaptee.getProtoSwitchPoints(hook, findData.getOwner()), null);
                 }
              }
         }
@@ -710,7 +710,7 @@
             final MethodHandle methodHandle = hook.equals(__put__) ?
             MH.asType(Lookup.EMPTY_SETTER, type) :
             Lookup.emptyGetter(type.returnType());
-            return new GuardedInvocation(methodHandle, testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoint(hook, null));
+            return new GuardedInvocation(methodHandle, testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoints(hook, null), null);
         }
     }
 
--- a/src/jdk/nashorn/internal/objects/NativeJava.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeJava.java	Thu Oct 29 17:22:12 2015 -0700
@@ -93,7 +93,7 @@
     @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
         if (func instanceof ScriptFunction) {
-            return ((ScriptFunction)func).makeSynchronizedFunction(obj);
+            return ((ScriptFunction)func).createSynchronized(obj);
         }
 
         throw typeError("not.a.function", ScriptRuntime.safeToString(func));
@@ -342,7 +342,8 @@
     /**
      * Given a script object and a Java type, converts the script object into the desired Java type. Currently it
      * performs shallow creation of Java arrays, as well as wrapping of objects in Lists, Dequeues, Queues,
-     * and Collections. Example:
+     * and Collections. If conversion is not possible or fails for some reason, TypeError is thrown.
+     * Example:
      * <pre>
      * var anArray = [1, "13", false]
      * var javaIntArray = Java.to(anArray, "int[]")
@@ -386,7 +387,11 @@
         }
 
         if(targetClass.isArray()) {
-            return JSType.toJavaArray(obj, targetClass.getComponentType());
+            try {
+                return JSType.toJavaArray(obj, targetClass.getComponentType());
+            } catch (final Exception exp) {
+                throw typeError(exp, "java.array.conversion.failed", targetClass.getName());
+            }
         }
 
         if (targetClass == List.class || targetClass == Deque.class || targetClass == Queue.class || targetClass == Collection.class) {
--- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Thu Oct 29 17:22:12 2015 -0700
@@ -134,7 +134,7 @@
     }
 
     @Override
-    protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+    protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) {
         final Object retval = createProperty(name);
         if (isValid(programPoint)) {
             throw new UnwarrantedOptimismException(retval, programPoint);
--- a/src/jdk/nashorn/internal/objects/NativeNumber.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeNumber.java	Thu Oct 29 17:22:12 2015 -0700
@@ -33,6 +33,7 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.math.RoundingMode;
 import java.text.NumberFormat;
 import java.util.Locale;
 import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -187,6 +188,7 @@
         format.setMinimumFractionDigits(fractionDigits);
         format.setMaximumFractionDigits(fractionDigits);
         format.setGroupingUsed(false);
+        format.setRoundingMode(RoundingMode.HALF_UP);
 
         return format.format(x);
     }
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java	Thu Oct 29 17:22:12 2015 -0700
@@ -728,7 +728,7 @@
          *
          * $$ -> $
          * $& -> the matched substring
-         * $` -> the portion of string that preceeds matched substring
+         * $` -> the portion of string that precedes matched substring
          * $' -> the portion of string that follows the matched substring
          * $n -> the nth capture, where n is [1-9] and $n is NOT followed by a decimal digit
          * $nn -> the nnth capture, where nn is a two digit decimal number [01-99].
--- a/src/jdk/nashorn/internal/objects/PrototypeObject.java	Fri Oct 16 12:19:59 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.objects;
-
-import static jdk.nashorn.internal.lookup.Lookup.MH;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import jdk.nashorn.internal.runtime.AccessorProperty;
-import jdk.nashorn.internal.runtime.Property;
-import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptObject;
-
-/**
- * Instances of this class serve as "prototype" object for script functions.
- * The purpose is to expose "constructor" property from "prototype". Also, nasgen
- * generated prototype classes extend from this class.
- *
- */
-public class PrototypeObject extends ScriptObject {
-    private static final PropertyMap map$;
-
-    private Object constructor;
-
-    private static final MethodHandle GET_CONSTRUCTOR = findOwnMH("getConstructor", Object.class, Object.class);
-    private static final MethodHandle SET_CONSTRUCTOR = findOwnMH("setConstructor", void.class, Object.class, Object.class);
-
-    static {
-        final ArrayList<Property> properties = new ArrayList<>(1);
-        properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR));
-        map$ = PropertyMap.newMap(properties);
-    }
-
-    private PrototypeObject(final Global global, final PropertyMap map) {
-        super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$);
-    }
-
-    PrototypeObject() {
-        this(Global.instance(), map$);
-    }
-
-    /**
-     * PropertyObject constructor
-     *
-     * @param map property map
-     */
-    PrototypeObject(final PropertyMap map) {
-        this(Global.instance(), map);
-    }
-
-    PrototypeObject(final ScriptFunction func) {
-        this(Global.instance(), map$);
-        this.constructor = func;
-    }
-
-    /**
-     * Get the constructor for this {@code PrototypeObject}
-     * @param self self reference
-     * @return constructor, probably, but not necessarily, a {@link ScriptFunction}
-     */
-    static Object getConstructor(final Object self) {
-        return (self instanceof PrototypeObject) ?
-            ((PrototypeObject)self).getConstructor() :
-            UNDEFINED;
-    }
-
-    /**
-     * Reset the constructor for this {@code PrototypeObject}
-     * @param self self reference
-     * @param constructor constructor, probably, but not necessarily, a {@link ScriptFunction}
-     */
-    static void setConstructor(final Object self, final Object constructor) {
-        if (self instanceof PrototypeObject) {
-            ((PrototypeObject)self).setConstructor(constructor);
-        }
-    }
-
-    private Object getConstructor() {
-        return constructor;
-    }
-
-    private void setConstructor(final Object constructor) {
-        this.constructor = constructor;
-    }
-
-    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-        return MH.findStatic(MethodHandles.lookup(), PrototypeObject.class, name, MH.type(rtype, types));
-    }
-}
--- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Fri Oct 16 12:19:59 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,313 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.objects;
-
-import static jdk.nashorn.internal.lookup.Lookup.MH;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
-import java.lang.invoke.MethodHandle;
-import java.util.ArrayList;
-import jdk.nashorn.internal.runtime.AccessorProperty;
-import jdk.nashorn.internal.runtime.GlobalFunctions;
-import jdk.nashorn.internal.runtime.Property;
-import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
-import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptFunctionData;
-import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.Specialization;
-
-/**
- * Concrete implementation of ScriptFunction. This sets correct map for the
- * function objects -- to expose properties like "prototype", "length" etc.
- */
-public class ScriptFunctionImpl extends ScriptFunction {
-
-    /** Reference to constructor prototype. */
-    private Object prototype;
-
-    // property map for strict mode functions
-    private static final PropertyMap strictmodemap$;
-    // property map for bound functions
-    private static final PropertyMap boundfunctionmap$;
-    // property map for non-strict, non-bound functions.
-    private static final PropertyMap map$;
-
-    // Marker object for lazily initialized prototype object
-    private static final Object LAZY_PROTOTYPE = new Object();
-
-    private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs, final Global global) {
-        super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
-        init(global);
-    }
-
-    /**
-     * Constructor called by Nasgen generated code, no membercount, use the default map.
-     * Creates builtin functions only.
-     *
-     * @param name name of function
-     * @param invokeHandle handle for invocation
-     * @param specs specialized versions of this method, if available, null otherwise
-     */
-    ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs) {
-        this(name, invokeHandle, specs, Global.instance());
-    }
-
-    private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs, final Global global) {
-        super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
-        init(global);
-    }
-
-    /**
-     * Constructor called by Nasgen generated code, no membercount, use the map passed as argument.
-     * Creates builtin functions only.
-     *
-     * @param name name of function
-     * @param invokeHandle handle for invocation
-     * @param map initial property map
-     * @param specs specialized versions of this method, if available, null otherwise
-     */
-    ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) {
-        this(name, invokeHandle, map, specs, Global.instance());
-    }
-
-    private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags, final Global global) {
-        super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags);
-        init(global);
-    }
-
-    /**
-     * Constructor called by Global.newScriptFunction (runtime).
-     *
-     * @param name name of function
-     * @param methodHandle handle for invocation
-     * @param scope scope object
-     * @param specs specialized versions of this method, if available, null otherwise
-     * @param flags {@link ScriptFunctionData} flags
-     */
-    ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags) {
-        this(name, methodHandle, scope, specs, flags, Global.instance());
-    }
-
-    private ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope, final Global global) {
-        super(data, getMap(data.isStrict()), scope);
-        init(global);
-    }
-
-    /**
-     * Factory method called by compiler generated code for functions that need parent scope.
-     *
-     * @param constants the generated class' constant array
-     * @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array.
-     * @param scope the parent scope object
-     * @return a newly created function object
-     */
-    public static ScriptFunction create(final Object[] constants, final int index, final ScriptObject scope) {
-        return new ScriptFunctionImpl((RecompilableScriptFunctionData)constants[index], scope, Global.instance());
-    }
-
-    /**
-     * Factory method called by compiler generated code for functions that don't need parent scope.
-     *
-     * @param constants the generated class' constant array
-     * @param index the index of the {@code RecompilableScriptFunctionData} object in the constants array.
-     * @return a newly created function object
-     */
-    public static ScriptFunction create(final Object[] constants, final int index) {
-        return create(constants, index, null);
-    }
-
-    /**
-     * Only invoked internally from {@link BoundScriptFunctionImpl} constructor.
-     * @param data the script function data for the bound function.
-     * @param global the global object
-     */
-    ScriptFunctionImpl(final ScriptFunctionData data, final Global global) {
-        super(data, boundfunctionmap$, null);
-        init(global);
-    }
-
-    static {
-        final ArrayList<Property> properties = new ArrayList<>(3);
-        properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE));
-        properties.add(AccessorProperty.create("length",  Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null));
-        properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null));
-        map$ = PropertyMap.newMap(properties);
-        strictmodemap$ = createStrictModeMap(map$);
-        boundfunctionmap$ = createBoundFunctionMap(strictmodemap$);
-    }
-
-    private static PropertyMap createStrictModeMap(final PropertyMap map) {
-        final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
-        PropertyMap newMap = map;
-        // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
-        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags));
-        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags));
-        return newMap;
-    }
-
-    private static boolean isStrict(final int flags) {
-        return (flags & ScriptFunctionData.IS_STRICT) != 0;
-    }
-
-    // Choose the map based on strict mode!
-    private static PropertyMap getMap(final boolean strict) {
-        return strict ? strictmodemap$ : map$;
-    }
-
-    private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) {
-        // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see
-        // ECMAScript 5.1 section 15.3.4.5
-        return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype"));
-    }
-
-    // Instance of this class is used as global anonymous function which
-    // serves as Function.prototype object.
-    private static class AnonymousFunction extends ScriptFunctionImpl {
-        private static final PropertyMap anonmap$ = PropertyMap.newMap();
-
-        AnonymousFunction() {
-            super("", GlobalFunctions.ANONYMOUS, anonmap$, null);
-        }
-    }
-
-    static ScriptFunctionImpl newAnonymousFunction() {
-        return new AnonymousFunction();
-    }
-
-    private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) {
-        final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags);
-        func.setPrototype(UNDEFINED);
-        // Non-constructor built-in functions do not have "prototype" property
-        func.deleteOwnProperty(func.getMap().findProperty("prototype"));
-
-        return func;
-    }
-
-    /**
-     * Factory method for non-constructor built-in functions
-     *
-     * @param name   function name
-     * @param methodHandle handle for invocation
-     * @param specs  specialized versions of function if available, null otherwise
-     * @return new ScriptFunction
-     */
-    static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs) {
-        return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN);
-    }
-
-    /**
-     * Factory method for non-constructor built-in, strict functions
-     *
-     * @param name   function name
-     * @param methodHandle handle for invocation
-     * @return new ScriptFunction
-     */
-    static ScriptFunction makeStrictFunction(final String name, final MethodHandle methodHandle) {
-        return makeFunction(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT );
-    }
-
-    /**
-     * Factory method for non-constructor built-in functions
-     *
-     * @param name   function name
-     * @param methodHandle handle for invocation
-     * @return new ScriptFunction
-     */
-    static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle) {
-        return makeFunction(name, methodHandle, null);
-    }
-
-    @Override
-    public ScriptFunction makeSynchronizedFunction(final Object sync) {
-        final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync);
-        return makeFunction(getName(), mh);
-    }
-
-    /**
-     * Same as {@link ScriptFunction#makeBoundFunction(Object, Object[])}. The only reason we override it is so that we
-     * can expose it.
-     * @param self the self to bind to this function. Can be null (in which case, null is bound as this).
-     * @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments.
-     * @return a function with the specified self and parameters bound.
-     */
-    @Override
-    public ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
-        return super.makeBoundFunction(self, args);
-    }
-
-    /**
-     * This method is used to create a bound function based on this function.
-     *
-     * @param data the {@code ScriptFunctionData} specifying the functions immutable portion.
-     * @return a function initialized from the specified data. Its parent scope will be set to null, therefore the
-     * passed in data should not expect a callee.
-     */
-    @Override
-    protected ScriptFunction makeBoundFunction(final ScriptFunctionData data) {
-        return new BoundScriptFunctionImpl(data, getTargetFunction());
-    }
-
-    // return Object.prototype - used by "allocate"
-    @Override
-    protected final ScriptObject getObjectPrototype() {
-        return Global.objectPrototype();
-    }
-
-    @Override
-    public final Object getPrototype() {
-        if (prototype == LAZY_PROTOTYPE) {
-            prototype = new PrototypeObject(this);
-        }
-        return prototype;
-    }
-
-    @Override
-    public final void setPrototype(final Object newProto) {
-        if (newProto instanceof ScriptObject && newProto != this.prototype && allocatorMap != null) {
-            // Replace our current allocator map with one that is associated with the new prototype.
-            allocatorMap = allocatorMap.changeProto((ScriptObject)newProto);
-        }
-        this.prototype = newProto;
-    }
-
-    // Internals below..
-    private void init(final Global global) {
-        this.setInitialProto(global.getFunctionPrototype());
-        this.prototype = LAZY_PROTOTYPE;
-
-        // We have to fill user accessor functions late as these are stored
-        // in this object rather than in the PropertyMap of this object.
-        assert objectSpill == null;
-        final ScriptFunction typeErrorThrower = global.getTypeErrorThrower();
-        if (findProperty("arguments", true) != null) {
-            initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
-        }
-        if (findProperty("caller", true) != null) {
-            initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
-       }
-    }
-}
--- a/src/jdk/nashorn/internal/parser/Lexer.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/parser/Lexer.java	Thu Oct 29 17:22:12 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, 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
@@ -1451,9 +1451,22 @@
                 skip(3);
             }
 
-            // Scan identifier.
+            // Scan identifier. It might be quoted, indicating that no string editing should take place.
+            final char quoteChar = ch0;
+            final boolean noStringEditing = quoteChar == '"' || quoteChar == '\'';
+            if (noStringEditing) {
+                skip(1);
+            }
             final int identStart = position;
             final int identLength = scanIdentifier();
+            if (noStringEditing) {
+                if (ch0 != quoteChar) {
+                    error(Lexer.message("here.non.matching.delimiter"), last, position, position);
+                    restoreState(saved);
+                    return false;
+                }
+                skip(1);
+            }
 
             // Check for identifier.
             if (identLength == 0) {
@@ -1523,7 +1536,7 @@
             }
 
             // Edit string if appropriate.
-            if (scripting && !stringState.isEmpty()) {
+            if (!noStringEditing && !stringState.isEmpty()) {
                 editString(STRING, stringState);
             } else {
                 // Add here string.
@@ -1640,9 +1653,9 @@
             //and new Color(float, float, float) will get ambiguous for cases like
             //new Color(1.0, 1.5, 1.5) if we don't respect the decimal point.
             //yet we don't want e.g. 1e6 to be a double unnecessarily
-            if (JSType.isRepresentableAsInt(value) && !JSType.isNegativeZero(value)) {
+            if (JSType.isStrictlyRepresentableAsInt(value)) {
                 return (int)value;
-            } else if (JSType.isRepresentableAsLong(value) && !JSType.isNegativeZero(value)) {
+            } else if (JSType.isStrictlyRepresentableAsLong(value)) {
                 return (long)value;
             }
             return value;
--- a/src/jdk/nashorn/internal/parser/Parser.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/parser/Parser.java	Thu Oct 29 17:22:12 2015 -0700
@@ -84,7 +84,6 @@
 import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
@@ -513,8 +512,7 @@
 
         return lc.pop(functionNode).
             setBody(lc, newBody).
-            setLastToken(lc, lastToken).
-            setState(lc, errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED);
+            setLastToken(lc, lastToken);
     }
 
     /**
@@ -805,7 +803,7 @@
                                 if (!oldStrictMode && directiveStmts != null) {
                                     // check that directives preceding this one do not violate strictness
                                     for (final Node statement : directiveStmts) {
-                                        // the get value will force unescape of preceeding
+                                        // the get value will force unescape of preceding
                                         // escaped string directives
                                         getValue(statement.getToken());
                                     }
@@ -2469,7 +2467,7 @@
         //         run: function() { println("run"); }
         //     };
         //
-        // The object literal following the "new Constructor()" expresssion
+        // The object literal following the "new Constructor()" expression
         // is passed as an additional (last) argument to the constructor.
         if (!env._no_syntax_extensions && type == LBRACE) {
             arguments.add(objectLiteral());
@@ -2720,6 +2718,11 @@
         }
 
         if (isStatement) {
+            if (isAnonymous) {
+                appendStatement(new ExpressionStatement(functionLine, functionToken, finish, functionNode));
+                return functionNode;
+            }
+
             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
             final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags);
             if (topLevel) {
--- a/src/jdk/nashorn/internal/runtime/AllocationStrategy.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java	Thu Oct 29 17:22:12 2015 -0700
@@ -29,6 +29,7 @@
 import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.lang.ref.WeakReference;
 import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
@@ -53,6 +54,9 @@
     /** lazily generated allocator */
     private transient MethodHandle allocator;
 
+    /** Last used allocator map */
+    private transient AllocatorMap lastMap;
+
     /**
      * Construct an allocation strategy with the given map and class name.
      * @param fieldCount number of fields in the allocated object
@@ -71,11 +75,49 @@
         return allocatorClassName;
     }
 
-    PropertyMap getAllocatorMap() {
-        // Create a new map for each function instance
-        return PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0);
+    /**
+     * Get the property map for the allocated object.
+     * @param prototype the prototype object
+     * @return the property map
+     */
+    synchronized PropertyMap getAllocatorMap(final ScriptObject prototype) {
+        assert prototype != null;
+        final PropertyMap protoMap = prototype.getMap();
+
+        if (lastMap != null) {
+            if (!lastMap.hasSharedProtoMap()) {
+                if (lastMap.hasSamePrototype(prototype)) {
+                    return lastMap.allocatorMap;
+                }
+                if (lastMap.hasSameProtoMap(protoMap) && lastMap.hasUnchangedProtoMap()) {
+                    // Convert to shared prototype map. Allocated objects will use the same property map
+                    // that can be used as long as none of the prototypes modify the shared proto map.
+                    final PropertyMap allocatorMap = PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0);
+                    final SharedPropertyMap sharedProtoMap = new SharedPropertyMap(protoMap);
+                    allocatorMap.setSharedProtoMap(sharedProtoMap);
+                    prototype.setMap(sharedProtoMap);
+                    lastMap = new AllocatorMap(prototype, protoMap, allocatorMap);
+                    return allocatorMap;
+                }
+            }
+
+            if (lastMap.hasValidSharedProtoMap() && lastMap.hasSameProtoMap(protoMap)) {
+                prototype.setMap(lastMap.getSharedProtoMap());
+                return lastMap.allocatorMap;
+            }
+        }
+
+        final PropertyMap allocatorMap = PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0);
+        lastMap = new AllocatorMap(prototype, protoMap, allocatorMap);
+
+        return allocatorMap;
     }
 
+    /**
+     * Allocate an object with the given property map
+     * @param map the property map
+     * @return the allocated object
+     */
     ScriptObject allocate(final PropertyMap map) {
         try {
             if (allocator == null) {
@@ -94,4 +136,43 @@
     public String toString() {
         return "AllocationStrategy[fieldCount=" + fieldCount + "]";
     }
+
+    static class AllocatorMap {
+        final private WeakReference<ScriptObject> prototype;
+        final private WeakReference<PropertyMap> prototypeMap;
+
+        private PropertyMap allocatorMap;
+
+        AllocatorMap(final ScriptObject prototype, final PropertyMap protoMap, final PropertyMap allocMap) {
+            this.prototype = new WeakReference<>(prototype);
+            this.prototypeMap = new WeakReference<>(protoMap);
+            this.allocatorMap = allocMap;
+        }
+
+        boolean hasSamePrototype(final ScriptObject proto) {
+            return prototype.get() == proto;
+        }
+
+        boolean hasSameProtoMap(final PropertyMap protoMap) {
+            return prototypeMap.get() == protoMap || allocatorMap.getSharedProtoMap() == protoMap;
+        }
+
+        boolean hasUnchangedProtoMap() {
+            final ScriptObject proto = prototype.get();
+            return proto != null && proto.getMap() == prototypeMap.get();
+        }
+
+        boolean hasSharedProtoMap() {
+            return getSharedProtoMap() != null;
+        }
+
+        boolean hasValidSharedProtoMap() {
+            return hasSharedProtoMap() && getSharedProtoMap().isValidSharedProtoMap();
+        }
+
+        PropertyMap getSharedProtoMap() {
+            return allocatorMap.getSharedProtoMap();
+        }
+
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/runtime/AstSerializer.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.  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 java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.runtime.options.Options;
+
+/**
+ * This static utility class performs serialization of FunctionNode ASTs to a byte array.
+ * The format is a standard Java serialization stream, deflated.
+ */
+final class AstSerializer {
+    // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed
+    // and size.
+    private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4);
+    static byte[] serialize(final FunctionNode fn) {
+        final ByteArrayOutputStream out = new ByteArrayOutputStream();
+        final Deflater deflater = new Deflater(COMPRESSION_LEVEL);
+        try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) {
+            oout.writeObject(fn);
+        } catch (final IOException e) {
+            throw new AssertionError("Unexpected exception serializing function", e);
+        } finally {
+            deflater.end();
+        }
+        return out.toByteArray();
+    }
+}
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Thu Oct 29 17:22:12 2015 -0700
@@ -38,15 +38,14 @@
  * The compiler still retains most of the state around code emission
  * and management internally, so this is to avoid passing around any
  * logic that isn't directly related to installing a class
- * @param <T> owner class type for this code installer
  *
  */
-public interface CodeInstaller<T> {
+public interface CodeInstaller {
     /**
-     * Return the owner for the CodeInstaller, e.g. a {@link Context}
-     * @return owner
+     * Return the {@link Context} associated with this code installer.
+     * @return the context.
      */
-    public T getOwner();
+    public Context getContext();
 
     /**
      * Install a class.
@@ -106,7 +105,7 @@
      * new, independent class loader.
      * @return a new code installer with a new independent class loader.
      */
-    public CodeInstaller<T> withNewLoader();
+    public CodeInstaller withNewLoader();
 
     /**
      * Returns true if this code installer is compatible with the other code installer. Compatibility is expected to be
@@ -115,6 +114,6 @@
      * @param other the other code installer tested for compatibility with this code installer.
      * @return true if this code installer is compatible with the other code installer.
      */
-    public boolean isCompatibleWith(CodeInstaller<T> other);
+    public boolean isCompatibleWith(CodeInstaller other);
 
 }
--- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Thu Oct 29 17:22:12 2015 -0700
@@ -27,6 +27,7 @@
 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;
@@ -101,7 +102,7 @@
             /*
              * An optimistic builtin with isOptimistic=true works like any optimistic generated function, i.e. it
              * can throw unwarranted optimism exceptions. As native functions trivially can't have parts of them
-             * regenerated as restof methods, this only works if the methods are atomic/functional in their behavior
+             * regenerated as "restOf" methods, this only works if the methods are atomic/functional in their behavior
              * and doesn't modify state before an UOE can be thrown. If they aren't, we can reexecute a wider version
              * of the same builtin in a recompilation handler for FinalScriptFunctionData. There are several
              * candidate methods in Native* that would benefit from this, but I haven't had time to implement any
@@ -566,7 +567,7 @@
             return handle;
         }
 
-        // Otherwise, we need a new level of indirection; need to introduce a mutable call site that can relink itslef
+        // Otherwise, we need a new level of indirection; need to introduce a mutable call site that can relink itself
         // to the compiled function's changed target whenever the optimistic assumptions are invalidated.
         final CallSite cs = new MutableCallSite(handle.type());
         relinkComposableInvoker(cs, this, isConstructor);
@@ -820,7 +821,7 @@
         // isn't available, we'll use the old one bound into the call site.
         final OptimismInfo effectiveOptInfo = currentOptInfo != null ? currentOptInfo : oldOptInfo;
         FunctionNode fn = effectiveOptInfo.reparse();
-        final boolean serialized = effectiveOptInfo.isSerialized();
+        final boolean cached = fn.isCached();
         final Compiler compiler = effectiveOptInfo.getCompiler(fn, ct, re); //set to non rest-of
 
         if (!shouldRecompile) {
@@ -828,11 +829,11 @@
             // recompiled a deoptimized version for an inner invocation.
             // We still need to do the rest of from the beginning
             logRecompile("Rest-of compilation [STANDALONE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
-            return restOfHandle(effectiveOptInfo, compiler.compile(fn, serialized ? CompilationPhases.COMPILE_SERIALIZED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
+            return restOfHandle(effectiveOptInfo, compiler.compile(fn, cached ? CompilationPhases.COMPILE_CACHED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
         }
 
         logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
-        fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
+        fn = compiler.compile(fn, cached ? CompilationPhases.RECOMPILE_CACHED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
         log.fine("Reusable IR generated");
 
         // compile the rest of the function, and install it
@@ -956,10 +957,6 @@
         FunctionNode reparse() {
             return data.reparse();
         }
-
-        boolean isSerialized() {
-            return data.isSerialized();
-        }
     }
 
     @SuppressWarnings("unused")
--- a/src/jdk/nashorn/internal/runtime/Context.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/Context.java	Thu Oct 29 17:22:12 2015 -0700
@@ -153,7 +153,7 @@
      * Currently we are conservative and associate the name of a builtin class with all
      * its properties, so it's enough to invalidate a property to break all assumptions
      * about a prototype. This can be changed to a more fine grained approach, but no one
-     * ever needs this, given the very rare occurance of swapping out only parts of
+     * ever needs this, given the very rare occurrence of swapping out only parts of
      * a builtin v.s. the entire builtin object
      */
     private final Map<String, SwitchPoint> builtinSwitchPoints = new HashMap<>();
@@ -167,7 +167,7 @@
      * ContextCodeInstaller that has the privilege of installing classes in the Context.
      * Can only be instantiated from inside the context and is opaque to other classes
      */
-    public static class ContextCodeInstaller implements CodeInstaller<ScriptEnvironment> {
+    public static class ContextCodeInstaller implements CodeInstaller {
         private final Context      context;
         private final ScriptLoader loader;
         private final CodeSource   codeSource;
@@ -185,13 +185,9 @@
             this.codeSource = codeSource;
         }
 
-        /**
-         * Return the script environment for this installer
-         * @return ScriptEnvironment
-         */
         @Override
-        public ScriptEnvironment getOwner() {
-            return context.env;
+        public Context getContext() {
+            return context;
         }
 
         @Override
@@ -254,7 +250,7 @@
         }
 
         @Override
-        public CodeInstaller<ScriptEnvironment> withNewLoader() {
+        public CodeInstaller withNewLoader() {
             // Reuse this installer if we're within our limits.
             if (usageCount < MAX_USAGES && bytesDefined < MAX_BYTES_DEFINED) {
                 return this;
@@ -263,7 +259,7 @@
         }
 
         @Override
-        public boolean isCompatibleWith(final CodeInstaller<ScriptEnvironment> other) {
+        public boolean isCompatibleWith(final CodeInstaller other) {
             if (other instanceof ContextCodeInstaller) {
                 final ContextCodeInstaller cci = (ContextCodeInstaller)other;
                 return cci.context == context && cci.codeSource == codeSource;
@@ -987,6 +983,16 @@
     }
 
     /**
+     * Is {@code className} the name of a structure class?
+     *
+     * @param className a class name
+     * @return true if className is a structure class name
+     */
+    public static boolean isStructureClass(final String className) {
+        return StructureLoader.isStructureClass(className);
+    }
+
+    /**
      * Checks that the given Class can be accessed from no permissions context.
      *
      * @param clazz Class object
@@ -1129,17 +1135,16 @@
      *
      * @param global the global
      * @param engine the associated ScriptEngine instance, can be null
-     * @param ctxt the initial ScriptContext, can be null
      * @return the initialized global scope object.
      */
-    public Global initGlobal(final Global global, final ScriptEngine engine, final ScriptContext ctxt) {
+    public Global initGlobal(final Global global, final ScriptEngine engine) {
         // Need only minimal global object, if we are just compiling.
         if (!env._compile_only) {
             final Global oldGlobal = Context.getGlobal();
             try {
                 Context.setGlobal(global);
                 // initialize global scope with builtin global objects
-                global.initBuiltinObjects(engine, ctxt);
+                global.initBuiltinObjects(engine);
             } finally {
                 Context.setGlobal(oldGlobal);
             }
@@ -1155,7 +1160,7 @@
      * @return the initialized global scope object.
      */
     public Global initGlobal(final Global global) {
-        return initGlobal(global, null, null);
+        return initGlobal(global, null);
     }
 
     /**
@@ -1300,14 +1305,12 @@
         final URL          url    = source.getURL();
         final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
         final CodeSource   cs     = new CodeSource(url, (CodeSigner[])null);
-        final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
+        final CodeInstaller installer = new ContextCodeInstaller(this, loader, cs);
 
         if (storedScript == null) {
             final CompilationPhases phases = Compiler.CompilationPhases.COMPILE_ALL;
 
-            final Compiler compiler = new Compiler(
-                    this,
-                    env,
+            final Compiler compiler = Compiler.forInitialCompilation(
                     installer,
                     source,
                     errMan,
@@ -1456,7 +1459,7 @@
      * @param level            log level
      * @param mh               method handle
      * @param paramStart       first parameter to print
-     * @param printReturnValue should we print the return vaulue?
+     * @param printReturnValue should we print the return value?
      * @param text             debug printout to add
      *
      * @return instrumented method handle, or null if logger not enabled
--- a/src/jdk/nashorn/internal/runtime/Debug.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/Debug.java	Thu Oct 29 17:22:12 2015 -0700
@@ -26,6 +26,8 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.parser.TokenType.EOF;
+
+import jdk.nashorn.api.scripting.NashornException;
 import jdk.nashorn.internal.parser.Lexer;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenStream;
@@ -63,6 +65,15 @@
     }
 
     /**
+     * Return a formatted script stack trace string with frames information separated by '\n'.
+     * This is a shortcut for {@code NashornException.getScriptStackString(new Throwable())}.
+     * @return formatted stack trace string
+     */
+    public static String scriptStack() {
+        return NashornException.getScriptStackString(new Throwable());
+    }
+
+    /**
      * Return the system identity hashcode for an object as a human readable
      * string
      *
--- a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java	Thu Oct 29 17:22:12 2015 -0700
@@ -27,6 +27,7 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -72,11 +73,6 @@
     }
 
     @Override
-    boolean isRecompilable() {
-        return false;
-    }
-
-    @Override
     protected boolean needsCallee() {
         final boolean needsCallee = code.getFirst().needsCallee();
         assert allNeedCallee(needsCallee);
@@ -93,6 +89,20 @@
     }
 
     @Override
+    CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
+        assert isValidCallSite(callSiteType) : callSiteType;
+
+        CompiledFunction best = null;
+        for (final CompiledFunction candidate: code) {
+            if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) {
+                best = candidate;
+            }
+        }
+
+        return best;
+    }
+
+    @Override
     MethodType getGenericType() {
         // We need to ask the code for its generic type. We can't just rely on this function data's arity, as it's not
         // actually correct for lots of built-ins. E.g. ECMAScript 5.1 section 15.5.3.2 prescribes that
--- a/src/jdk/nashorn/internal/runtime/FindProperty.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/FindProperty.java	Thu Oct 29 17:22:12 2015 -0700
@@ -297,4 +297,3 @@
     }
 
 }
-
--- a/src/jdk/nashorn/internal/runtime/GlobalConstants.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java	Thu Oct 29 17:22:12 2015 -0700
@@ -67,7 +67,7 @@
  *
  * Thus everything registered as a global constant gets an extra chance. Set once,
  * reregister the switchpoint. Set twice or more - don't try again forever, or we'd
- * just end up relinking our way into megamorphisism.
+ * just end up relinking our way into megamorphism.
  *
  * Also it has to be noted that this kind of linking creates a coupling between a Global
  * and the call sites in compiled code belonging to the Context. For this reason, the
--- a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java	Thu Oct 29 17:22:12 2015 -0700
@@ -187,14 +187,14 @@
 
         double result = 0.0;
         int digit;
-        // we should see atleast one valid digit
+        // we should see at least one valid digit
         boolean entered = false;
         while (idx < length) {
             digit = fastDigit(str.charAt(idx++), radix);
             if (digit < 0) {
                 break;
             }
-            // we have seen atleast one valid digit in the specified radix
+            // we have seen at least one valid digit in the specified radix
             entered = true;
             result *= radix;
             result += digit;
--- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java	Thu Oct 29 17:22:12 2015 -0700
@@ -26,7 +26,6 @@
 package jdk.nashorn.internal.runtime;
 
 import java.lang.invoke.MethodHandle;
-import java.util.Iterator;
 import java.util.concurrent.Callable;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.JSONParser;
@@ -104,16 +103,28 @@
         final Object val = holder.get(name);
         if (val instanceof ScriptObject) {
             final ScriptObject     valueObj = (ScriptObject)val;
-            final Iterator<String> iter     = valueObj.propertyIterator();
+            if (valueObj.isArray()) {
+                final int length = JSType.toInteger(valueObj.getLength());
+                for (int i = 0; i < length; i++) {
+                    final String key = Integer.toString(i);
+                    final Object newElement = walk(valueObj, key, reviver);
 
-            while (iter.hasNext()) {
-                final String key        = iter.next();
-                final Object newElement = walk(valueObj, key, reviver);
+                    if (newElement == ScriptRuntime.UNDEFINED) {
+                        valueObj.delete(i, false);
+                    } else {
+                        setPropertyValue(valueObj, key, newElement);
+                    }
+                }
+            } else {
+                final String[] keys = valueObj.getOwnKeys(false);
+                for (final String key : keys) {
+                    final Object newElement = walk(valueObj, key, reviver);
 
-                if (newElement == ScriptRuntime.UNDEFINED) {
-                    valueObj.delete(key, false);
-                } else {
-                    setPropertyValue(valueObj, key, newElement);
+                    if (newElement == ScriptRuntime.UNDEFINED) {
+                        valueObj.delete(key, false);
+                    } else {
+                        setPropertyValue(valueObj, key, newElement);
+                    }
                 }
             }
         }
--- a/src/jdk/nashorn/internal/runtime/JSType.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/JSType.java	Thu Oct 29 17:22:12 2015 -0700
@@ -377,8 +377,8 @@
     }
 
     /**
-     * Returns true if double number can be represented as an int. Note that it returns true for negative zero. If you
-     * need to exclude negative zero, combine this check with {@link #isNegativeZero(double)}.
+     * Returns true if double number can be represented as an int. Note that it returns true for negative
+     * zero. If you need to exclude negative zero, use {@link #isStrictlyRepresentableAsInt(double)}.
      *
      * @param number a double to inspect
      *
@@ -389,6 +389,18 @@
     }
 
     /**
+     * Returns true if double number can be represented as an int. Note that it returns false for negative
+     * zero. If you don't need to distinguish negative zero, use {@link #isRepresentableAsInt(double)}.
+     *
+     * @param number a double to inspect
+     *
+     * @return true for int representable doubles
+     */
+    public static boolean isStrictlyRepresentableAsInt(final double number) {
+        return isRepresentableAsInt(number) && isNotNegativeZero(number);
+    }
+
+    /**
      * Returns true if Object can be represented as an int
      *
      * @param obj an object to inspect
@@ -403,8 +415,8 @@
     }
 
     /**
-     * Returns true if double number can be represented as a long. Note that it returns true for negative zero. If you
-     * need to exclude negative zero, combine this check with {@link #isNegativeZero(double)}.
+     * Returns true if double number can be represented as a long. Note that it returns true for negative
+     * zero. If you need to exclude negative zero, use {@link #isStrictlyRepresentableAsLong(double)}.
      *
      * @param number a double to inspect
      * @return true for long representable doubles
@@ -414,6 +426,18 @@
     }
 
     /**
+     * Returns true if double number can be represented as a long. Note that it returns false for negative
+     * zero. If you don't need to distinguish negative zero, use {@link #isRepresentableAsLong(double)}.
+     *
+     * @param number a double to inspect
+     *
+     * @return true for long representable doubles
+     */
+    public static boolean isStrictlyRepresentableAsLong(final double number) {
+        return isRepresentableAsLong(number) && isNotNegativeZero(number);
+    }
+
+    /**
      * Returns true if Object can be represented as a long
      *
      * @param obj an object to inspect
@@ -428,12 +452,12 @@
     }
 
     /**
-     * Returns true if the number is the negative zero ({@code -0.0d}).
+     * Returns true if the number is not the negative zero ({@code -0.0d}).
      * @param number the number to test
-     * @return true if it is the negative zero, false otherwise.
+     * @return true if it is not the negative zero, false otherwise.
      */
-    public static boolean isNegativeZero(final double number) {
-        return number == 0.0d && Double.doubleToRawLongBits(number) == 0x8000000000000000L;
+    private static boolean isNotNegativeZero(final double number) {
+        return Double.doubleToRawLongBits(number) != 0x8000000000000000L;
     }
 
     /**
@@ -1944,7 +1968,7 @@
     /**
      * Get the unboxed (primitive) type for an object
      * @param o object
-     * @return primive type or Object.class if not primitive
+     * @return primitive type or Object.class if not primitive
      */
     public static Class<?> unboxedFieldType(final Object o) {
         if (o == null) {
--- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Thu Oct 29 17:22:12 2015 -0700
@@ -206,7 +206,7 @@
     }
 
     @Override
-    protected Object invokeNoSuchProperty(final String key, final int programPoint) {
+    protected Object invokeNoSuchProperty(final String key, final boolean isScope, final int programPoint) {
         final Object retval = createProperty(key);
         if (isValid(programPoint)) {
             throw new UnwarrantedOptimismException(retval, programPoint);
--- a/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java	Thu Oct 29 17:22:12 2015 -0700
@@ -184,7 +184,7 @@
 
     @SuppressWarnings("unused")
     private static int ensureInt(final double arg, final int programPoint) {
-        if (JSType.isRepresentableAsInt(arg) && !JSType.isNegativeZero(arg)) {
+        if (JSType.isStrictlyRepresentableAsInt(arg)) {
             return (int)arg;
         }
         throw new UnwarrantedOptimismException(arg, programPoint);
@@ -206,7 +206,7 @@
         // Long into the exception.
         if (isPrimitiveNumberWrapper(arg)) {
             final double d = ((Number)arg).doubleValue();
-            if (JSType.isRepresentableAsInt(d) && !JSType.isNegativeZero(d)) {
+            if (JSType.isStrictlyRepresentableAsInt(d)) {
                 return (int)d;
             }
         }
@@ -239,7 +239,7 @@
     }
 
     private static long ensureLong(final double arg, final int programPoint) {
-        if (JSType.isRepresentableAsLong(arg) && !JSType.isNegativeZero(arg)) {
+        if (JSType.isStrictlyRepresentableAsLong(arg)) {
             return (long)arg;
         }
         throw new UnwarrantedOptimismException(arg, programPoint);
--- a/src/jdk/nashorn/internal/runtime/ParserException.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/ParserException.java	Thu Oct 29 17:22:12 2015 -0700
@@ -38,7 +38,7 @@
     private final Source source;
     // token responsible for this exception
     private final long token;
-    // if this is traslated as ECMA error, which type should be used?
+    // if this is translated as ECMA error, which type should be used?
     private final JSErrorType errorType;
 
     /**
--- a/src/jdk/nashorn/internal/runtime/Property.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/Property.java	Thu Oct 29 17:22:12 2015 -0700
@@ -562,8 +562,8 @@
 
     @Override
     public int hashCode() {
-        final Class<?> type = getLocalType();
-        return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode());
+        final Class<?> t = getLocalType();
+        return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (t == null ? 0 : t.hashCode());
     }
 
     @Override
@@ -588,7 +588,7 @@
                 getKey().equals(otherProperty.getKey());
     }
 
-    private static final String type(final Class<?> type) {
+    private static String type(final Class<?> type) {
         if (type == null) {
             return "undef";
         } else if (type == int.class) {
@@ -608,8 +608,8 @@
      */
     public final String toStringShort() {
         final StringBuilder sb   = new StringBuilder();
-        final Class<?>      type = getLocalType();
-        sb.append(getKey()).append(" (").append(type(type)).append(')');
+        final Class<?>      t = getLocalType();
+        sb.append(getKey()).append(" (").append(type(t)).append(')');
         return sb.toString();
     }
 
@@ -625,7 +625,7 @@
     @Override
     public String toString() {
         final StringBuilder sb   = new StringBuilder();
-        final Class<?>      type = getLocalType();
+        final Class<?>      t = getLocalType();
 
         sb.append(indent(getKey(), 20)).
             append(" id=").
@@ -635,7 +635,7 @@
             append(") ").
             append(getClass().getSimpleName()).
             append(" {").
-            append(indent(type(type), 5)).
+            append(indent(type(t), 5)).
             append('}');
 
         if (slot != -1) {
--- a/src/jdk/nashorn/internal/runtime/PropertyListeners.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/PropertyListeners.java	Thu Oct 29 17:22:12 2015 -0700
@@ -28,6 +28,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
+import java.util.concurrent.atomic.LongAdder;
 
 /**
  * Helper class to manage property listeners and notification.
@@ -37,8 +38,15 @@
     private Map<String, WeakPropertyMapSet> listeners;
 
     // These counters are updated in debug mode
-    private static int listenersAdded;
-    private static int listenersRemoved;
+    private static LongAdder listenersAdded;
+    private static LongAdder listenersRemoved;
+
+    static {
+        if (Context.DEBUG) {
+            listenersAdded = new LongAdder();
+            listenersRemoved = new LongAdder();
+        }
+    }
 
     /**
      * Copy constructor
@@ -54,29 +62,33 @@
      * Return aggregate listeners added to all PropertyListenerManagers
      * @return the listenersAdded
      */
-    public static int getListenersAdded() {
-        return listenersAdded;
+    public static long getListenersAdded() {
+        return listenersAdded.longValue();
     }
 
     /**
      * Return aggregate listeners removed from all PropertyListenerManagers
      * @return the listenersRemoved
      */
-    public static int getListenersRemoved() {
-        return listenersRemoved;
+    public static long getListenersRemoved() {
+        return listenersRemoved.longValue();
     }
 
     /**
-     * Return listeners added to this ScriptObject.
+     * Return number of listeners added to a ScriptObject.
      * @param obj the object
      * @return the listener count
      */
     public static int getListenerCount(final ScriptObject obj) {
-        final PropertyListeners propertyListeners = obj.getMap().getListeners();
-        if (propertyListeners != null) {
-            return propertyListeners.listeners == null ? 0 : propertyListeners.listeners.size();
-        }
-        return 0;
+        return obj.getMap().getListenerCount();
+    }
+
+    /**
+     * Return the number of listeners added to this PropertyListeners instance.
+     * @return the listener count;
+     */
+    public int getListenerCount() {
+        return listeners == null ? 0 : listeners.size();
     }
 
     // Property listener management methods
@@ -122,7 +134,7 @@
      */
     synchronized final void addListener(final String key, final PropertyMap propertyMap) {
         if (Context.DEBUG) {
-            listenersAdded++;
+            listenersAdded.increment();
         }
         if (listeners == null) {
             listeners = new WeakHashMap<>();
@@ -148,9 +160,12 @@
             final WeakPropertyMapSet set = listeners.get(prop.getKey());
             if (set != null) {
                 for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.propertyAdded(prop);
+                    propertyMap.propertyAdded(prop, false);
                 }
                 listeners.remove(prop.getKey());
+                if (Context.DEBUG) {
+                    listenersRemoved.increment();
+                }
             }
         }
     }
@@ -165,9 +180,12 @@
             final WeakPropertyMapSet set = listeners.get(prop.getKey());
             if (set != null) {
                 for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.propertyDeleted(prop);
+                    propertyMap.propertyDeleted(prop, false);
                 }
                 listeners.remove(prop.getKey());
+                if (Context.DEBUG) {
+                    listenersRemoved.increment();
+                }
             }
         }
     }
@@ -184,9 +202,12 @@
             final WeakPropertyMapSet set = listeners.get(oldProp.getKey());
             if (set != null) {
                 for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.propertyModified(oldProp, newProp);
+                    propertyMap.propertyModified(oldProp, newProp, false);
                 }
                 listeners.remove(oldProp.getKey());
+                if (Context.DEBUG) {
+                    listenersRemoved.increment();
+                }
             }
         }
     }
@@ -198,7 +219,7 @@
         if (listeners != null) {
             for (final WeakPropertyMapSet set : listeners.values()) {
                 for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.protoChanged();
+                    propertyMap.protoChanged(false);
                 }
             }
             listeners.clear();
--- a/src/jdk/nashorn/internal/runtime/PropertyMap.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java	Thu Oct 29 17:22:12 2015 -0700
@@ -34,7 +34,9 @@
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.lang.invoke.SwitchPoint;
+import java.lang.ref.Reference;
 import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Collection;
@@ -42,6 +44,8 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.WeakHashMap;
+import java.util.concurrent.atomic.LongAdder;
+import jdk.nashorn.internal.runtime.options.Options;
 import jdk.nashorn.internal.scripts.JO;
 
 /**
@@ -53,35 +57,49 @@
  * All property maps are immutable. If a property is added, modified or removed, the mutator
  * will return a new map.
  */
-public final class PropertyMap implements Iterable<Object>, Serializable {
+public class PropertyMap implements Iterable<Object>, Serializable {
+    private static final int INITIAL_SOFT_REFERENCE_DERIVATION_LIMIT =
+            Math.max(0, Options.getIntProperty("nashorn.propertyMap.softReferenceDerivationLimit", 32));
+
     /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
-    public static final int NOT_EXTENSIBLE        = 0b0000_0001;
+    private static final int NOT_EXTENSIBLE         = 0b0000_0001;
     /** Does this map contain valid array keys? */
-    public static final int CONTAINS_ARRAY_KEYS   = 0b0000_0010;
+    private static final int CONTAINS_ARRAY_KEYS    = 0b0000_0010;
 
     /** Map status flags. */
-    private int flags;
+    private final int flags;
 
     /** Map of properties. */
     private transient PropertyHashMap properties;
 
     /** Number of fields in use. */
-    private int fieldCount;
+    private final int fieldCount;
 
     /** Number of fields available. */
     private final int fieldMaximum;
 
     /** Length of spill in use. */
-    private int spillLength;
+    private final int spillLength;
 
     /** Structure class name */
-    private String className;
+    private final String className;
+
+    /**
+     * Countdown of number of times this property map has been derived from another property map. When it
+     * reaches zero, the property map will start using weak references instead of soft references to hold on
+     * to its history elements.
+     */
+    private final int softReferenceDerivationLimit;
+
+    /** A reference to the expected shared prototype property map. If this is set this
+     * property map should only be used if it the same as the actual prototype map. */
+    private transient SharedPropertyMap sharedProtoMap;
 
     /** {@link SwitchPoint}s for gets on inherited properties. */
-    private transient HashMap<String, SwitchPoint> protoGetSwitches;
+    private transient HashMap<String, SwitchPoint> protoSwitches;
 
     /** History of maps, used to limit map duplication. */
-    private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
+    private transient WeakHashMap<Property, Reference<PropertyMap>> history;
 
     /** History of prototypes, used to limit map duplication. */
     private transient WeakHashMap<ScriptObject, SoftReference<PropertyMap>> protoHistory;
@@ -94,59 +112,60 @@
     private static final long serialVersionUID = -7041836752008732533L;
 
     /**
-     * Constructor.
+     * Constructs a new property map.
      *
      * @param properties   A {@link PropertyHashMap} with initial contents.
      * @param fieldCount   Number of fields in use.
      * @param fieldMaximum Number of fields available.
      * @param spillLength  Number of spill slots used.
-     * @param containsArrayKeys True if properties contain numeric keys
      */
-    private PropertyMap(final PropertyHashMap properties, final String className, final int fieldCount,
-                        final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) {
+    private PropertyMap(final PropertyHashMap properties, final int flags, final String className,
+                        final int fieldCount, final int fieldMaximum, final int spillLength) {
         this.properties   = properties;
         this.className    = className;
         this.fieldCount   = fieldCount;
         this.fieldMaximum = fieldMaximum;
         this.spillLength  = spillLength;
-        if (containsArrayKeys) {
-            setContainsArrayKeys();
-        }
+        this.flags        = flags;
+        this.softReferenceDerivationLimit = INITIAL_SOFT_REFERENCE_DERIVATION_LIMIT;
 
         if (Context.DEBUG) {
-            count++;
+            count.increment();
         }
     }
 
     /**
-     * Cloning constructor.
+     * Constructs a clone of {@code propertyMap} with changed properties, flags, or boundaries.
      *
      * @param propertyMap Existing property map.
      * @param properties  A {@link PropertyHashMap} with a new set of properties.
      */
-    private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) {
+    private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties, final int flags, final int fieldCount, final int spillLength, final int softReferenceDerivationLimit) {
         this.properties   = properties;
-        this.flags        = propertyMap.flags;
-        this.spillLength  = propertyMap.spillLength;
-        this.fieldCount   = propertyMap.fieldCount;
+        this.flags        = flags;
+        this.spillLength  = spillLength;
+        this.fieldCount   = fieldCount;
         this.fieldMaximum = propertyMap.fieldMaximum;
+        this.className    = propertyMap.className;
         // We inherit the parent property listeners instance. It will be cloned when a new listener is added.
         this.listeners    = propertyMap.listeners;
         this.freeSlots    = propertyMap.freeSlots;
+        this.sharedProtoMap = propertyMap.sharedProtoMap;
+        this.softReferenceDerivationLimit = softReferenceDerivationLimit;
 
         if (Context.DEBUG) {
-            count++;
-            clonedCount++;
+            count.increment();
+            clonedCount.increment();
         }
     }
 
     /**
-     * Cloning constructor.
+     * Constructs an exact clone of {@code propertyMap}.
      *
      * @param propertyMap Existing property map.
       */
-    private PropertyMap(final PropertyMap propertyMap) {
-        this(propertyMap, propertyMap.properties);
+    protected PropertyMap(final PropertyMap propertyMap) {
+        this(propertyMap, propertyMap.properties, propertyMap.flags, propertyMap.fieldCount, propertyMap.spillLength, propertyMap.softReferenceDerivationLimit);
     }
 
     private void writeObject(final ObjectOutputStream out) throws IOException {
@@ -182,7 +201,7 @@
      */
     public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum,  final int spillLength) {
         final PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
-        return new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength, false);
+        return new PropertyMap(newProperties, 0, className, fieldCount, fieldMaximum, spillLength);
     }
 
     /**
@@ -204,7 +223,7 @@
      * @return New empty {@link PropertyMap}.
      */
     public static PropertyMap newMap(final Class<? extends ScriptObject> clazz) {
-        return new PropertyMap(EMPTY_HASHMAP, clazz.getName(), 0, 0, 0, false);
+        return new PropertyMap(EMPTY_HASHMAP, 0, clazz.getName(), 0, 0, 0);
     }
 
     /**
@@ -226,12 +245,12 @@
     }
 
     /**
-     * Get the listeners of this map, or null if none exists
+     * Get the number of listeners of this map
      *
-     * @return the listeners
+     * @return the number of listeners
      */
-    public PropertyListeners getListeners() {
-        return listeners;
+    public int getListenerCount() {
+        return listeners == null ? 0 : listeners.getListenerCount();
     }
 
     /**
@@ -252,9 +271,12 @@
      * A new property is being added.
      *
      * @param property The new Property added.
+     * @param isSelf was the property added to this map?
      */
-    public void propertyAdded(final Property property) {
-        invalidateProtoGetSwitchPoint(property);
+    public void propertyAdded(final Property property, final boolean isSelf) {
+        if (!isSelf) {
+            invalidateProtoSwitchPoint(property.getKey());
+        }
         if (listeners != null) {
             listeners.propertyAdded(property);
         }
@@ -264,9 +286,12 @@
      * An existing property is being deleted.
      *
      * @param property The property being deleted.
+     * @param isSelf was the property deleted from this map?
      */
-    public void propertyDeleted(final Property property) {
-        invalidateProtoGetSwitchPoint(property);
+    public void propertyDeleted(final Property property, final boolean isSelf) {
+        if (!isSelf) {
+            invalidateProtoSwitchPoint(property.getKey());
+        }
         if (listeners != null) {
             listeners.propertyDeleted(property);
         }
@@ -277,9 +302,12 @@
      *
      * @param oldProperty The old property
      * @param newProperty The new property
+     * @param isSelf was the property modified on this map?
      */
-    public void propertyModified(final Property oldProperty, final Property newProperty) {
-        invalidateProtoGetSwitchPoint(oldProperty);
+    public void propertyModified(final Property oldProperty, final Property newProperty, final boolean isSelf) {
+        if (!isSelf) {
+            invalidateProtoSwitchPoint(oldProperty.getKey());
+        }
         if (listeners != null) {
             listeners.propertyModified(oldProperty, newProperty);
         }
@@ -287,9 +315,15 @@
 
     /**
      * The prototype of an object associated with this {@link PropertyMap} is changed.
+     *
+     * @param isSelf was the prototype changed on the object using this map?
      */
-    public void protoChanged() {
-        invalidateAllProtoGetSwitchPoints();
+    public void protoChanged(final boolean isSelf) {
+        if (!isSelf) {
+            invalidateAllProtoSwitchPoints();
+        } else if (sharedProtoMap != null) {
+            sharedProtoMap.invalidateSwitchPoint();
+        }
         if (listeners != null) {
             listeners.protoChanged();
         }
@@ -302,14 +336,14 @@
      * @return A shared {@link SwitchPoint} for the property.
      */
     public synchronized SwitchPoint getSwitchPoint(final String key) {
-        if (protoGetSwitches == null) {
-            protoGetSwitches = new HashMap<>();
+        if (protoSwitches == null) {
+            protoSwitches = new HashMap<>();
         }
 
-        SwitchPoint switchPoint = protoGetSwitches.get(key);
+        SwitchPoint switchPoint = protoSwitches.get(key);
         if (switchPoint == null) {
             switchPoint = new SwitchPoint();
-            protoGetSwitches.put(key, switchPoint);
+            protoSwitches.put(key, switchPoint);
         }
 
         return switchPoint;
@@ -318,19 +352,17 @@
     /**
      * Indicate that a prototype property has changed.
      *
-     * @param property {@link Property} to invalidate.
+     * @param key {@link Property} key to invalidate.
      */
-    synchronized void invalidateProtoGetSwitchPoint(final Property property) {
-        if (protoGetSwitches != null) {
-
-            final String key = property.getKey();
-            final SwitchPoint sp = protoGetSwitches.get(key);
+    synchronized void invalidateProtoSwitchPoint(final String key) {
+        if (protoSwitches != null) {
+            final SwitchPoint sp = protoSwitches.get(key);
             if (sp != null) {
-                protoGetSwitches.remove(key);
+                protoSwitches.remove(key);
                 if (Context.DEBUG) {
-                    protoInvalidations++;
+                    protoInvalidations.increment();
                 }
-                SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
+                SwitchPoint.invalidateAll(new SwitchPoint[]{sp});
             }
         }
     }
@@ -338,15 +370,15 @@
     /**
      * Indicate that proto itself has changed in hierarchy somewhere.
      */
-    synchronized void invalidateAllProtoGetSwitchPoints() {
-        if (protoGetSwitches != null) {
-            final int size = protoGetSwitches.size();
+    synchronized void invalidateAllProtoSwitchPoints() {
+        if (protoSwitches != null) {
+            final int size = protoSwitches.size();
             if (size > 0) {
                 if (Context.DEBUG) {
-                    protoInvalidations += size;
+                    protoInvalidations.add(size);
                 }
-                SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[size]));
-                protoGetSwitches.clear();
+                SwitchPoint.invalidateAll(protoSwitches.values().toArray(new SwitchPoint[size]));
+                protoSwitches.clear();
             }
         }
     }
@@ -362,7 +394,7 @@
      * @return New {@link PropertyMap} with {@link Property} added.
      */
     PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) {
-        // No need to store bound property in the history as bound properties can't be reused.
+        // We must not store bound property in the history as bound properties can't be reused.
         return addPropertyNoHistory(new AccessorProperty(property, bindTo));
     }
 
@@ -375,16 +407,16 @@
         return property.isSpill() ? slot + fieldMaximum : slot;
     }
 
-    // Update boundaries and flags after a property has been added
-    private void updateFlagsAndBoundaries(final Property newProperty) {
-        if(newProperty.isSpill()) {
-            spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
-        } else {
-            fieldCount = Math.max(fieldCount, newProperty.getSlot() + 1);
-        }
-        if (isValidArrayIndex(getArrayIndex(newProperty.getKey()))) {
-            setContainsArrayKeys();
-        }
+    private int newSpillLength(final Property newProperty) {
+        return newProperty.isSpill() ? Math.max(spillLength, newProperty.getSlot() + 1) : spillLength;
+    }
+
+    private int newFieldCount(final Property newProperty) {
+        return !newProperty.isSpill() ? Math.max(fieldCount, newProperty.getSlot() + 1) : fieldCount;
+    }
+
+    private int newFlags(final Property newProperty) {
+        return isValidArrayIndex(getArrayIndex(newProperty.getKey())) ? flags | CONTAINS_ARRAY_KEYS : flags;
     }
 
     // Update the free slots bitmap for a property that has been deleted and/or added. This method is not synchronized
@@ -419,16 +451,9 @@
      * @param property {@link Property} being added.
      * @return New {@link PropertyMap} with {@link Property} added.
      */
-    public PropertyMap addPropertyNoHistory(final Property property) {
-        if (listeners != null) {
-            listeners.propertyAdded(property);
-        }
-        final PropertyHashMap newProperties = properties.immutableAdd(property);
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
-        newMap.updateFlagsAndBoundaries(property);
-        newMap.updateFreeSlots(null, property);
-
-        return newMap;
+    public final PropertyMap addPropertyNoHistory(final Property property) {
+        propertyAdded(property, true);
+        return addPropertyInternal(property);
     }
 
     /**
@@ -438,23 +463,29 @@
      *
      * @return New {@link PropertyMap} with {@link Property} added.
      */
-    public synchronized PropertyMap addProperty(final Property property) {
-        if (listeners != null) {
-            listeners.propertyAdded(property);
-        }
+    public final synchronized PropertyMap addProperty(final Property property) {
+        propertyAdded(property, true);
         PropertyMap newMap = checkHistory(property);
 
         if (newMap == null) {
-            final PropertyHashMap newProperties = properties.immutableAdd(property);
-            newMap = new PropertyMap(this, newProperties);
-            newMap.updateFlagsAndBoundaries(property);
-            newMap.updateFreeSlots(null, property);
+            newMap = addPropertyInternal(property);
             addToHistory(property, newMap);
         }
 
         return newMap;
     }
 
+    private PropertyMap deriveMap(final PropertyHashMap newProperties, final int newFlags, final int newFieldCount, final int newSpillLength) {
+        return new PropertyMap(this, newProperties, newFlags, newFieldCount, newSpillLength, softReferenceDerivationLimit == 0 ? 0 : softReferenceDerivationLimit - 1);
+    }
+
+    private PropertyMap addPropertyInternal(final Property property) {
+        final PropertyHashMap newProperties = properties.immutableAdd(property);
+        final PropertyMap newMap = deriveMap(newProperties, newFlags(property), newFieldCount(property), newSpillLength(property));
+        newMap.updateFreeSlots(null, property);
+        return newMap;
+    }
+
     /**
      * Remove a property from a map. Cloning or using an existing map if available.
      *
@@ -462,10 +493,8 @@
      *
      * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found.
      */
-    public synchronized PropertyMap deleteProperty(final Property property) {
-        if (listeners != null) {
-            listeners.propertyDeleted(property);
-        }
+    public final synchronized PropertyMap deleteProperty(final Property property) {
+        propertyDeleted(property, true);
         PropertyMap newMap = checkHistory(property);
         final String key = property.getKey();
 
@@ -476,13 +505,13 @@
             // If deleted property was last field or spill slot we can make it reusable by reducing field/slot count.
             // Otherwise mark it as free in free slots bitset.
             if (isSpill && slot >= 0 && slot == spillLength - 1) {
-                newMap = new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength - 1, containsArrayKeys());
+                newMap = deriveMap(newProperties, flags, fieldCount, spillLength - 1);
                 newMap.freeSlots = freeSlots;
             } else if (!isSpill && slot >= 0 && slot == fieldCount - 1) {
-                newMap = new PropertyMap(newProperties, className, fieldCount - 1, fieldMaximum, spillLength, containsArrayKeys());
+                newMap = deriveMap(newProperties, flags, fieldCount - 1, spillLength);
                 newMap.freeSlots = freeSlots;
             } else {
-                newMap = new PropertyMap(this, newProperties);
+                newMap = deriveMap(newProperties, flags, fieldCount, spillLength);
                 newMap.updateFreeSlots(property, null);
             }
             addToHistory(property, newMap);
@@ -499,13 +528,8 @@
      *
      * @return New {@link PropertyMap} with {@link Property} replaced.
      */
-    public PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
-        if (listeners != null) {
-            listeners.propertyModified(oldProperty, newProperty);
-        }
-        // Add replaces existing property.
-        final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
+    public final PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
+        propertyModified(oldProperty, newProperty, true);
         /*
          * See ScriptObject.modifyProperty and ScriptObject.setUserAccessors methods.
          *
@@ -527,14 +551,17 @@
                 newProperty instanceof UserAccessorProperty :
             "arbitrary replaceProperty attempted " + sameType + " oldProperty=" + oldProperty.getClass() + " newProperty=" + newProperty.getClass() + " [" + oldProperty.getLocalType() + " => " + newProperty.getLocalType() + "]";
 
-        newMap.flags = flags;
-
         /*
          * spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
          * to add spill count of the newly added UserAccessorProperty property.
          */
+        final int newSpillLength = sameType ? spillLength : Math.max(spillLength, newProperty.getSlot() + 1);
+
+        // Add replaces existing property.
+        final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
+        final PropertyMap newMap = deriveMap(newProperties, flags, fieldCount, newSpillLength);
+
         if (!sameType) {
-            newMap.spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
             newMap.updateFreeSlots(oldProperty, newProperty);
         }
         return newMap;
@@ -550,7 +577,7 @@
      * @param propertyFlags attribute flags of the property
      * @return the newly created UserAccessorProperty
      */
-    public UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
+    public final UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
         return new UserAccessorProperty(key, propertyFlags, getFreeSpillSlot());
     }
 
@@ -561,7 +588,7 @@
      *
      * @return {@link Property} matching key.
      */
-    public Property findProperty(final String key) {
+    public final Property findProperty(final String key) {
         return properties.find(key);
     }
 
@@ -572,12 +599,12 @@
      *
      * @return New {@link PropertyMap} with added properties.
      */
-    public PropertyMap addAll(final PropertyMap other) {
+    public final PropertyMap addAll(final PropertyMap other) {
         assert this != other : "adding property map to itself";
         final Property[] otherProperties = other.properties.getProperties();
         final PropertyHashMap newProperties = properties.immutableAdd(otherProperties);
 
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
+        final PropertyMap newMap = deriveMap(newProperties, flags, fieldCount, spillLength);
         for (final Property property : otherProperties) {
             // This method is only safe to use with non-slotted, native getter/setter properties
             assert property.getSlot() == -1;
@@ -592,19 +619,26 @@
      *
      * @return Properties as an array.
      */
-    public Property[] getProperties() {
+    public final Property[] getProperties() {
         return properties.getProperties();
     }
 
     /**
+     * Return the name of the class of objects using this property map.
+     *
+     * @return class name of owner objects.
+     */
+    public final String getClassName() {
+        return className;
+    }
+
+    /**
      * Prevents the map from having additional properties.
      *
      * @return New map with {@link #NOT_EXTENSIBLE} flag set.
      */
     PropertyMap preventExtensions() {
-        final PropertyMap newMap = new PropertyMap(this);
-        newMap.flags |= NOT_EXTENSIBLE;
-        return newMap;
+        return deriveMap(properties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
     }
 
     /**
@@ -620,10 +654,7 @@
             newProperties = newProperties.immutableAdd(oldProperty.addFlags(Property.NOT_CONFIGURABLE));
         }
 
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
-        newMap.flags |= NOT_EXTENSIBLE;
-
-        return newMap;
+        return deriveMap(newProperties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
     }
 
     /**
@@ -645,10 +676,7 @@
             newProperties = newProperties.immutableAdd(oldProperty.addFlags(propertyFlags));
         }
 
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
-        newMap.flags |= NOT_EXTENSIBLE;
-
-        return newMap;
+        return deriveMap(newProperties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
     }
 
     /**
@@ -704,7 +732,7 @@
         }
 
         if (Context.DEBUG && cachedMap != null) {
-            protoHistoryHit++;
+            protoHistoryHit.increment();
         }
 
         return cachedMap;
@@ -735,7 +763,7 @@
             history = new WeakHashMap<>();
         }
 
-        history.put(property, new SoftReference<>(newMap));
+        history.put(property, softReferenceDerivationLimit == 0 ? new WeakReference<>(newMap) : new SoftReference<>(newMap));
     }
 
     /**
@@ -748,12 +776,12 @@
     private PropertyMap checkHistory(final Property property) {
 
         if (history != null) {
-            final SoftReference<PropertyMap> ref = history.get(property);
+            final Reference<PropertyMap> ref = history.get(property);
             final PropertyMap historicMap = ref == null ? null : ref.get();
 
             if (historicMap != null) {
                 if (Context.DEBUG) {
-                    historyHit++;
+                    historyHit.increment();
                 }
 
                 return historicMap;
@@ -820,13 +848,6 @@
     }
 
     /**
-     * Flag this object as having array keys in defined properties
-     */
-    private void setContainsArrayKeys() {
-        flags |= CONTAINS_ARRAY_KEYS;
-    }
-
-    /**
      * Test to see if {@link PropertyMap} is extensible.
      *
      * @return {@code true} if {@link PropertyMap} can be added to.
@@ -901,15 +922,75 @@
         }
 
         if (Context.DEBUG) {
-            setProtoNewMapCount++;
+            setProtoNewMapCount.increment();
         }
 
-        final PropertyMap newMap = new PropertyMap(this);
+        final PropertyMap newMap = makeUnsharedCopy();
         addToProtoHistory(newProto, newMap);
 
         return newMap;
     }
 
+    /**
+     * Make a copy of this property map with the shared prototype field set to null. Note that this is
+     * only necessary for shared maps of top-level objects. Shared prototype maps represented by
+     * {@link SharedPropertyMap} are automatically converted to plain property maps when they evolve.
+     *
+     * @return a copy with the shared proto map unset
+     */
+    PropertyMap makeUnsharedCopy() {
+        final PropertyMap newMap = new PropertyMap(this);
+        newMap.sharedProtoMap = null;
+        return newMap;
+    }
+
+    /**
+     * Set a reference to the expected parent prototype map. This is used for class-like
+     * structures where we only want to use a top-level property map if all of the
+     * prototype property maps have not been modified.
+     *
+     * @param protoMap weak reference to the prototype property map
+     */
+    void setSharedProtoMap(final SharedPropertyMap protoMap) {
+        sharedProtoMap = protoMap;
+    }
+
+    /**
+     * Get the expected prototype property map if it is known, or null.
+     *
+     * @return parent map or null
+     */
+    public PropertyMap getSharedProtoMap() {
+        return sharedProtoMap;
+    }
+
+    /**
+     * Returns {@code true} if this map has been used as a shared prototype map (i.e. as a prototype
+     * for a JavaScript constructor function) and has not had properties added, deleted or replaced since then.
+     * @return true if this is a valid shared prototype map
+     */
+    boolean isValidSharedProtoMap() {
+        return false;
+    }
+
+    /**
+     * Returns the shared prototype switch point, or null if this is not a shared prototype map.
+     * @return the shared prototype switch point, or null
+     */
+    SwitchPoint getSharedProtoSwitchPoint() {
+        return null;
+    }
+
+    /**
+     * Return true if this map has a shared prototype map which has either been invalidated or does
+     * not match the map of {@code proto}.
+     * @param prototype the prototype object
+     * @return true if this is an invalid shared map for {@code prototype}
+     */
+    boolean isInvalidSharedMapFor(final ScriptObject prototype) {
+        return sharedProtoMap != null
+                && (!sharedProtoMap.isValidSharedProtoMap() || prototype == null || sharedProtoMap != prototype.getMap());
+    }
 
     /**
      * {@link PropertyMap} iterator.
@@ -990,10 +1071,10 @@
            for (final Property p : map0.getProperties()) {
                final Property p2 = map1.findProperty(p.getKey());
                if (p2 == null) {
-                   sb.append("FIRST ONLY : [" + p + "]");
+                   sb.append("FIRST ONLY : [").append(p).append("]");
                    found = true;
                } else if (p2 != p) {
-                   sb.append("DIFFERENT  : [" + p + "] != [" + p2 + "]");
+                   sb.append("DIFFERENT  : [").append(p).append("] != [").append(p2).append("]");
                    found = true;
                }
            }
@@ -1001,7 +1082,7 @@
            for (final Property p2 : map1.getProperties()) {
                final Property p1 = map0.findProperty(p2.getKey());
                if (p1 == null) {
-                   sb.append("SECOND ONLY: [" + p2 + "]");
+                   sb.append("SECOND ONLY: [").append(p2).append("]");
                    found = true;
                }
            }
@@ -1021,52 +1102,62 @@
     }
 
     // counters updated only in debug mode
-    private static int count;
-    private static int clonedCount;
-    private static int historyHit;
-    private static int protoInvalidations;
-    private static int protoHistoryHit;
-    private static int setProtoNewMapCount;
+    private static LongAdder count;
+    private static LongAdder clonedCount;
+    private static LongAdder historyHit;
+    private static LongAdder protoInvalidations;
+    private static LongAdder protoHistoryHit;
+    private static LongAdder setProtoNewMapCount;
+    static {
+        if (Context.DEBUG) {
+            count = new LongAdder();
+            clonedCount = new LongAdder();
+            historyHit = new LongAdder();
+            protoInvalidations = new LongAdder();
+            protoHistoryHit = new LongAdder();
+            setProtoNewMapCount = new LongAdder();
+        }
+    }
 
     /**
      * @return Total number of maps.
      */
-    public static int getCount() {
-        return count;
+    public static long getCount() {
+        return count.longValue();
     }
 
     /**
      * @return The number of maps that were cloned.
      */
-    public static int getClonedCount() {
-        return clonedCount;
+    public static long getClonedCount() {
+        return clonedCount.longValue();
     }
 
     /**
      * @return The number of times history was successfully used.
      */
-    public static int getHistoryHit() {
-        return historyHit;
+    public static long getHistoryHit() {
+        return historyHit.longValue();
     }
 
     /**
      * @return The number of times prototype changes caused invalidation.
      */
-    public static int getProtoInvalidations() {
-        return protoInvalidations;
+    public static long getProtoInvalidations() {
+        return protoInvalidations.longValue();
     }
 
     /**
      * @return The number of times proto history was successfully used.
      */
-    public static int getProtoHistoryHit() {
-        return protoHistoryHit;
+    public static long getProtoHistoryHit() {
+        return protoHistoryHit.longValue();
     }
 
     /**
      * @return The number of times prototypes were modified.
      */
-    public static int getSetProtoNewMapCount() {
-        return setProtoNewMapCount;
+    public static long getSetProtoNewMapCount() {
+        return setProtoNewMapCount.longValue();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/runtime/PrototypeObject.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,118 @@
+/*
+ * 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.runtime;
+
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import jdk.nashorn.internal.objects.Global;
+
+/**
+ * Instances of this class serve as "prototype" object for script functions.
+ * The purpose is to expose "constructor" property from "prototype". Also, nasgen
+ * generated prototype classes extend from this class.
+ */
+public class PrototypeObject extends ScriptObject {
+    private static final PropertyMap map$;
+
+    private Object constructor;
+
+    private static final MethodHandle GET_CONSTRUCTOR = findOwnMH("getConstructor", Object.class, Object.class);
+    private static final MethodHandle SET_CONSTRUCTOR = findOwnMH("setConstructor", void.class, Object.class, Object.class);
+
+    static {
+        final ArrayList<Property> properties = new ArrayList<>(1);
+        properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR));
+        map$ = PropertyMap.newMap(properties);
+    }
+
+    private PrototypeObject(final Global global, final PropertyMap map) {
+        super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$);
+    }
+
+    /**
+     * Prototype constructor
+     */
+    protected PrototypeObject() {
+        this(Global.instance(), map$);
+    }
+
+    /**
+     * PropertyObject constructor
+     *
+     * @param map property map
+     */
+    protected PrototypeObject(final PropertyMap map) {
+        this(Global.instance(), map);
+    }
+
+    /**
+     * PropertyObject constructor
+     *
+     * @param func constructor function
+     */
+    protected PrototypeObject(final ScriptFunction func) {
+        this(Global.instance(), map$);
+        this.constructor = func;
+    }
+
+    /**
+     * Get the constructor for this {@code PrototypeObject}
+     * @param self self reference
+     * @return constructor, probably, but not necessarily, a {@link ScriptFunction}
+     */
+    public static Object getConstructor(final Object self) {
+        return (self instanceof PrototypeObject) ?
+            ((PrototypeObject)self).getConstructor() :
+            UNDEFINED;
+    }
+
+    /**
+     * Reset the constructor for this {@code PrototypeObject}
+     * @param self self reference
+     * @param constructor constructor, probably, but not necessarily, a {@link ScriptFunction}
+     */
+    public static void setConstructor(final Object self, final Object constructor) {
+        if (self instanceof PrototypeObject) {
+            ((PrototypeObject)self).setConstructor(constructor);
+        }
+    }
+
+    private Object getConstructor() {
+        return constructor;
+    }
+
+    private void setConstructor(final Object constructor) {
+        this.constructor = constructor;
+    }
+
+    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), PrototypeObject.class, name, MH.type(rtype, types));
+    }
+}
--- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu Oct 29 17:22:12 2015 -0700
@@ -26,16 +26,25 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+
 import java.io.IOException;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 import jdk.internal.dynalink.support.NameCodec;
 import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
@@ -45,9 +54,16 @@
 import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
 import jdk.nashorn.internal.codegen.TypeMap;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.Parser;
 import jdk.nashorn.internal.parser.Token;
@@ -55,6 +71,7 @@
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
+import jdk.nashorn.internal.runtime.options.Options;
 /**
  * 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.
@@ -66,6 +83,8 @@
     /** Prefix used for all recompiled script classes */
     public static final String RECOMPILATION_PREFIX = "Recompilation$";
 
+    private static final ExecutorService astSerializerExecutorService = createAstSerializerExecutorService();
+
     /** Unique function node id for this function node */
     private final int functionNodeId;
 
@@ -77,8 +96,12 @@
     /** Source from which FunctionNode was parsed. */
     private transient Source source;
 
-    /** Serialized, compressed form of the AST. Used by split functions as they can't be reparsed from source. */
-    private final byte[] serializedAst;
+    /**
+     * Cached form of the AST. Either a {@code SerializedAst} object used by split functions as they can't be
+     * reparsed from source, or a soft reference to a {@code FunctionNode} for other functions (it is safe
+     * to be cleared as they can be reparsed).
+     */
+    private volatile Object cachedAst;
 
     /** Token of this function within the source. */
     private final long token;
@@ -97,7 +120,7 @@
     private final Object endParserState;
 
     /** Code installer used for all further recompilation/specialization of this ScriptFunction */
-    private transient CodeInstaller<ScriptEnvironment> installer;
+    private transient CodeInstaller installer;
 
     private final Map<Integer, RecompilableScriptFunctionData> nestedFunctions;
 
@@ -128,16 +151,14 @@
      * @param nestedFunctions     nested function map
      * @param externalScopeDepths external scope depths
      * @param internalSymbols     internal symbols to method, defined in its scope
-     * @param serializedAst       a serialized AST representation. Normally only used for split functions.
      */
     public RecompilableScriptFunctionData(
         final FunctionNode functionNode,
-        final CodeInstaller<ScriptEnvironment> installer,
+        final CodeInstaller installer,
         final AllocationStrategy allocationStrategy,
         final Map<Integer, RecompilableScriptFunctionData> nestedFunctions,
         final Map<String, Integer> externalScopeDepths,
-        final Set<String> internalSymbols,
-        final byte[] serializedAst) {
+        final Set<String> internalSymbols) {
 
         super(functionName(functionNode),
               Math.min(functionNode.getParameters().size(), MAX_ARITY),
@@ -161,7 +182,6 @@
             nfn.setParent(this);
         }
 
-        this.serializedAst = serializedAst;
         createLogger();
     }
 
@@ -244,7 +264,7 @@
      * @return parent data, or null if non exists and also null IF UNKNOWN.
      */
     public RecompilableScriptFunctionData getParent() {
-       return parent;
+        return parent;
     }
 
     void setParent(final RecompilableScriptFunctionData parent) {
@@ -266,7 +286,7 @@
      * @param src source
      * @param inst code installer
      */
-    public void initTransients(final Source src, final CodeInstaller<ScriptEnvironment> inst) {
+    public void initTransients(final Source src, final CodeInstaller inst) {
         if (this.source == null && this.installer == null) {
             this.source    = src;
             this.installer = inst;
@@ -349,8 +369,8 @@
     }
 
     @Override
-    PropertyMap getAllocatorMap() {
-        return allocationStrategy.getAllocatorMap();
+    PropertyMap getAllocatorMap(final ScriptObject prototype) {
+        return allocationStrategy.getAllocatorMap(prototype);
     }
 
     @Override
@@ -358,13 +378,11 @@
         return allocationStrategy.allocate(map);
     }
 
-    boolean isSerialized() {
-        return serializedAst != null;
-    }
-
     FunctionNode reparse() {
-        if (isSerialized()) {
-            return deserialize();
+        final FunctionNode cachedFunction = getCachedAst();
+        if (cachedFunction != null) {
+            assert cachedFunction.isCached();
+            return cachedFunction;
         }
 
         final int descPosition = Token.descPosition(token);
@@ -391,8 +409,105 @@
         return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName);
     }
 
-    private FunctionNode deserialize() {
-        final ScriptEnvironment env = installer.getOwner();
+    private FunctionNode getCachedAst() {
+        final Object lCachedAst = cachedAst;
+        // Are we softly caching the AST?
+        if (lCachedAst instanceof Reference<?>) {
+            final FunctionNode fn = (FunctionNode)((Reference<?>)lCachedAst).get();
+            if (fn != null) {
+                // Yes we are - this is fast
+                return cloneSymbols(fn);
+            }
+        // Are we strongly caching a serialized AST (for split functions only)?
+        } else if (lCachedAst instanceof SerializedAst) {
+            final SerializedAst serializedAst = (SerializedAst)lCachedAst;
+            // Even so, are we also softly caching the AST?
+            final FunctionNode cachedFn = serializedAst.cachedAst.get();
+            if (cachedFn != null) {
+                // Yes we are - this is fast
+                return cloneSymbols(cachedFn);
+            }
+            final FunctionNode deserializedFn = deserialize(serializedAst.serializedAst);
+            // Softly cache after deserialization, maybe next time we won't need to deserialize
+            serializedAst.cachedAst = new SoftReference<>(deserializedFn);
+            return deserializedFn;
+        }
+        // No cached representation; return null for reparsing
+        return null;
+    }
+
+    /**
+     * Sets the AST to cache in this function
+     * @param astToCache the new AST to cache
+     */
+    public void setCachedAst(final FunctionNode astToCache) {
+        assert astToCache.getId() == functionNodeId; // same function
+        assert !(cachedAst instanceof SerializedAst); // Can't overwrite serialized AST
+
+        final boolean isSplit = astToCache.isSplit();
+        // If we're caching a split function, we're doing it in the eager pass, hence there can be no other
+        // cached representation already. In other words, isSplit implies cachedAst == null.
+        assert !isSplit || cachedAst == null; //
+
+        final FunctionNode symbolClonedAst = cloneSymbols(astToCache);
+        final Reference<FunctionNode> ref = new SoftReference<>(symbolClonedAst);
+        cachedAst = ref;
+
+        // Asynchronously serialize split functions.
+        if (isSplit) {
+            astSerializerExecutorService.execute(new Runnable() {
+                @Override
+                public void run() {
+                    cachedAst = new SerializedAst(symbolClonedAst, ref);
+                }
+            });
+        }
+    }
+
+    /**
+     * Creates the AST serializer executor service used for in-memory serialization of split functions' ASTs.
+     * It is created with an unbounded queue (so it can queue any number of pending tasks). Its core and max
+     * threads is the same, but they are all allowed to time out so when there's no work, they can all go
+     * away. The threads will be daemons, and they will time out if idle for a minute. Their priority is also
+     * slightly lower than normal priority as we'd prefer the CPU to keep running the program; serializing
+     * split function is a memory conservation measure (it allows us to release the AST), it can wait a bit.
+     * @return an executor service with above described characteristics.
+     */
+    private static ExecutorService createAstSerializerExecutorService() {
+        final int threads = Math.max(1, Options.getIntProperty("nashorn.serialize.threads", Runtime.getRuntime().availableProcessors() / 2));
+        final ThreadPoolExecutor service = new ThreadPoolExecutor(threads, threads, 1L, TimeUnit.MINUTES, new LinkedBlockingDeque<Runnable>(),
+                new ThreadFactory() {
+                    @Override
+                    public Thread newThread(final Runnable r) {
+                        final Thread t = new Thread(r, "Nashorn AST Serializer");
+                        t.setDaemon(true);
+                        t.setPriority(Thread.NORM_PRIORITY - 1);
+                        return t;
+                    }
+                });
+        service.allowCoreThreadTimeOut(true);
+        return service;
+    }
+
+    /**
+     * A tuple of a serialized AST and a soft reference to a deserialized AST. This is used to cache split
+     * functions. Since split functions are altered from their source form, they can't be reparsed from
+     * source. While we could just use the {@code byte[]} representation in {@link RecompilableScriptFunctionData#cachedAst}
+     * we're using this tuple instead to also keep a deserialized AST around in memory to cut down on
+     * deserialization costs.
+     */
+    private static class SerializedAst {
+        private final byte[] serializedAst;
+        private volatile Reference<FunctionNode> cachedAst;
+
+        SerializedAst(final FunctionNode fn, final Reference<FunctionNode> cachedAst) {
+            this.serializedAst = AstSerializer.serialize(fn);
+            this.cachedAst = cachedAst;
+        }
+    }
+
+    private FunctionNode deserialize(final byte[] serializedAst) {
+        final ScriptEnvironment env = installer.getContext().getEnv();
         final Timing timing = env._timing;
         final long t1 = System.nanoTime();
         try {
@@ -402,6 +517,107 @@
         }
     }
 
+    private FunctionNode cloneSymbols(final FunctionNode fn) {
+        final IdentityHashMap<Symbol, Symbol> symbolReplacements = new IdentityHashMap<>();
+        final boolean cached = fn.isCached();
+        // blockDefinedSymbols is used to re-mark symbols defined outside the function as global. We only
+        // need to do this when we cache an eagerly parsed function (which currently means a split one, as we
+        // don't cache non-split functions from the eager pass); those already cached, or those not split
+        // don't need this step.
+        final Set<Symbol> blockDefinedSymbols = fn.isSplit() && !cached ? Collections.newSetFromMap(new IdentityHashMap<Symbol, Boolean>()) : null;
+        FunctionNode newFn = (FunctionNode)fn.accept(new SimpleNodeVisitor() {
+
+            private Symbol getReplacement(final Symbol original) {
+                if (original == null) {
+                    return null;
+                }
+                final Symbol existingReplacement = symbolReplacements.get(original);
+                if (existingReplacement != null) {
+                    return existingReplacement;
+                }
+                final Symbol newReplacement = original.clone();
+                symbolReplacements.put(original, newReplacement);
+                return newReplacement;
+            }
+
+            @Override
+            public Node leaveIdentNode(final IdentNode identNode) {
+                final Symbol oldSymbol = identNode.getSymbol();
+                if (oldSymbol != null) {
+                    final Symbol replacement = getReplacement(oldSymbol);
+                    return identNode.setSymbol(replacement);
+                }
+                return identNode;
+            }
+
+            @Override
+            public Node leaveForNode(final ForNode forNode) {
+                return ensureUniqueLabels(forNode.setIterator(lc, getReplacement(forNode.getIterator())));
+            }
+
+            @Override
+            public Node leaveSwitchNode(final SwitchNode switchNode) {
+                return ensureUniqueLabels(switchNode.setTag(lc, getReplacement(switchNode.getTag())));
+            }
+
+            @Override
+            public Node leaveTryNode(final TryNode tryNode) {
+                return ensureUniqueLabels(tryNode.setException(lc, getReplacement(tryNode.getException())));
+            }
+
+            @Override
+            public boolean enterBlock(final Block block) {
+                for(final Symbol symbol: block.getSymbols()) {
+                    final Symbol replacement = getReplacement(symbol);
+                    if (blockDefinedSymbols != null) {
+                        blockDefinedSymbols.add(replacement);
+                    }
+                }
+                return true;
+            }
+
+            @Override
+            public Node leaveBlock(final Block block) {
+                return ensureUniqueLabels(block.replaceSymbols(lc, symbolReplacements));
+            }
+
+            @Override
+            public Node leaveFunctionNode(final FunctionNode functionNode) {
+                return functionNode.setParameters(lc, functionNode.visitParameters(this));
+            }
+
+            @Override
+            protected Node leaveDefault(final Node node) {
+                return ensureUniqueLabels(node);
+            };
+
+            private Node ensureUniqueLabels(final Node node) {
+                // If we're returning a cached AST, we must also ensure unique labels
+                return cached ? node.ensureUniqueLabels(lc) : node;
+            }
+        });
+
+        if (blockDefinedSymbols != null) {
+            // Mark all symbols not defined in blocks as globals
+            Block newBody = null;
+            for(final Symbol symbol: symbolReplacements.values()) {
+                if(!blockDefinedSymbols.contains(symbol)) {
+                    assert symbol.isScope(); // must be scope
+                    assert externalScopeDepths.containsKey(symbol.getName()); // must be known to us as an external
+                    // Register it in the function body symbol table as a new global symbol
+                    symbol.setFlags((symbol.getFlags() & ~Symbol.KINDMASK) | Symbol.IS_GLOBAL);
+                    if (newBody == null) {
+                        newBody = newFn.getBody().copyWithNewSymbols();
+                        newFn = newFn.setBody(null, newBody);
+                    }
+                    assert newBody.getExistingSymbol(symbol.getName()) == null; // must not be defined in the body already
+                    newBody.putSymbol(symbol);
+                }
+            }
+        }
+        return newFn.setCached(null);
+    }
+
     private boolean getFunctionFlag(final int flag) {
         return (functionFlags & flag) != 0;
     }
@@ -438,8 +654,8 @@
      * a new class loader with optimistic typing so that deoptimized code can get reclaimed by GC.
      * @return a code installer for installing new code.
      */
-    private CodeInstaller<ScriptEnvironment> getInstallerForNewCode() {
-        final ScriptEnvironment env = installer.getOwner();
+    private CodeInstaller getInstallerForNewCode() {
+        final ScriptEnvironment env = installer.getContext().getEnv();
         return env._optimistic_types || env._loader_per_compile ? installer.withNewLoader() : installer;
     }
 
@@ -449,15 +665,10 @@
         final TypeMap typeMap = typeMap(actualCallSiteType);
         final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
         final Object typeInformationFile = OptimisticTypesPersistence.getLocationDescriptor(source, functionNodeId, paramTypes);
-        final Context context = Context.getContextTrusted();
-        return new Compiler(
-                context,
-                context.getEnv(),
+        return Compiler.forOnDemandCompilation(
                 getInstallerForNewCode(),
                 functionNode.getSource(),  // source
-                context.getErrorManager(),
                 isStrict() | functionNode.isStrict(), // is strict
-                true,       // is on demand
                 this,       // compiledFunction, i.e. this RecompilableScriptFunctionData
                 typeMap,    // type map
                 getEffectiveInvalidatedProgramPoints(invalidatedProgramPoints, typeInformationFile), // invalidated program points
@@ -500,7 +711,7 @@
             final TypeMap typeMap = typeMap(actualCallSiteType);
             final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
             cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes);
-            final CodeInstaller<ScriptEnvironment> newInstaller = getInstallerForNewCode();
+            final CodeInstaller newInstaller = getInstallerForNewCode();
             final StoredScript script = newInstaller.loadScript(source, cacheKey);
 
             if (script != null) {
@@ -512,16 +723,16 @@
         final FunctionNode fn = reparse();
         final Compiler compiler = getCompiler(fn, actualCallSiteType, runtimeScope);
         final FunctionNode compiledFn = compiler.compile(fn,
-                isSerialized() ? CompilationPhases.COMPILE_ALL_SERIALIZED : CompilationPhases.COMPILE_ALL);
+                fn.isCached() ? CompilationPhases.COMPILE_ALL_CACHED : CompilationPhases.COMPILE_ALL);
 
-        if (persist && !compiledFn.getFlag(FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION)) {
+        if (persist && !compiledFn.hasApplyToCallSpecialization()) {
             compiler.persistClassInfo(cacheKey, compiledFn);
         }
         return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
     }
 
     boolean usePersistentCodeCache() {
-        return installer != null && installer.getOwner()._persistent_cache;
+        return installer != null && installer.getContext().getEnv()._persistent_cache;
     }
 
     private MethodType explicitParams(final MethodType callSiteType) {
@@ -553,7 +764,7 @@
 
     private FunctionNode extractFunctionFromScript(final FunctionNode script) {
         final Set<FunctionNode> fns = new HashSet<>();
-        script.getBody().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        script.getBody().accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterFunctionNode(final FunctionNode fn) {
                 fns.add(fn);
@@ -617,6 +828,7 @@
     private CompiledFunction addCode(final MethodHandle target, final Map<Integer, Type> invalidatedProgramPoints,
                                      final MethodType callSiteType, final int fnFlags) {
         final CompiledFunction cfn = new CompiledFunction(target, this, invalidatedProgramPoints, callSiteType, fnFlags);
+        assert noDuplicateCode(cfn) : "duplicate code";
         code.add(cfn);
         return cfn;
     }
@@ -683,14 +895,17 @@
 
     @Override
     synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
-        CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope, forbidden);
+        assert isValidCallSite(callSiteType) : callSiteType;
+
+        CompiledFunction existingBest = pickFunction(callSiteType, false);
+        if (existingBest == null) {
+            existingBest = pickFunction(callSiteType, true); // try vararg last
+        }
         if (existingBest == null) {
             existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, true), callSiteType);
         }
 
         assert existingBest != null;
-        //we are calling a vararg method with real args
-        boolean varArgWithRealArgs = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType);
 
         //if the best one is an apply to call, it has to match the callsite exactly
         //or we need to regenerate
@@ -699,27 +914,18 @@
             if (best != null) {
                 return best;
             }
-            varArgWithRealArgs = true;
-        }
 
-        if (varArgWithRealArgs) {
             // special case: we had an apply to call, but we failed to make it fit.
             // Try to generate a specialized one for this callsite. It may
             // be another apply to call specialization, or it may not, but whatever
             // it is, it is a specialization that is guaranteed to fit
-            final FunctionInitializer fnInit = compileTypeSpecialization(callSiteType, runtimeScope, false);
-            existingBest = addCode(fnInit, callSiteType);
+            existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, false), callSiteType);
         }
 
         return existingBest;
     }
 
     @Override
-    boolean isRecompilable() {
-        return true;
-    }
-
-    @Override
     public boolean needsCallee() {
         return getFunctionFlag(FunctionNode.NEEDS_CALLEE);
     }
@@ -827,6 +1033,16 @@
         return newFn;
     }
 
+    // Make sure code does not contain a compiled function with the same signature as compiledFunction
+    private boolean noDuplicateCode(final CompiledFunction compiledFunction) {
+        for (final CompiledFunction cf : code) {
+            if (cf.type().equals(compiledFunction.type())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
         createLogger();
--- a/src/jdk/nashorn/internal/runtime/Scope.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/Scope.java	Thu Oct 29 17:22:12 2015 -0700
@@ -27,6 +27,7 @@
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
 
+import java.util.concurrent.atomic.LongAdder;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 
 /**
@@ -38,7 +39,7 @@
     private int splitState = -1;
 
     /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created that are scope */
-    private static int count;
+    private static final LongAdder count = Context.DEBUG ? new LongAdder() : null;
 
     /** Method handle that points to {@link Scope#getSplitState}. */
     public static final CompilerConstants.Call GET_SPLIT_STATE = virtualCallNoLookup(Scope.class, "getSplitState", int.class);
@@ -52,9 +53,7 @@
      */
     public Scope(final PropertyMap map) {
         super(map);
-        if (Context.DEBUG) {
-            count++;
-        }
+        incrementCount();
     }
 
     /**
@@ -65,9 +64,7 @@
      */
     public Scope(final ScriptObject proto, final PropertyMap map) {
         super(proto, map);
-        if (Context.DEBUG) {
-            count++;
-        }
+        incrementCount();
     }
 
     /**
@@ -79,9 +76,7 @@
      */
     public Scope(final PropertyMap map, final long[] primitiveSpill, final Object[] objectSpill) {
         super(map, primitiveSpill, objectSpill);
-        if (Context.DEBUG) {
-            count++;
-        }
+        incrementCount();
     }
 
     @Override
@@ -123,7 +118,13 @@
      *
      * @return number of scope ScriptObjects created
      */
-    public static int getScopeCount() {
-        return count;
+    public static long getScopeCount() {
+        return count != null ? count.sum() : 0;
+    }
+
+    private static void incrementCount() {
+        if (Context.DEBUG) {
+            count.increment();
+        }
     }
 }
--- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Thu Oct 29 17:22:12 2015 -0700
@@ -46,6 +46,11 @@
  * and output and error writers, top level Namespace etc.
  */
 public final class ScriptEnvironment {
+    // Primarily intended to be used in test environments so that eager compilation tests work without an
+    // error when tested with optimistic compilation.
+    private static final boolean ALLOW_EAGER_COMPILATION_SILENT_OVERRIDE = Options.getBooleanProperty(
+            "nashorn.options.allowEagerCompilationSilentOverride", false);
+
     /** Output writer for this environment */
     private final PrintWriter out;
 
@@ -237,8 +242,20 @@
         }
         _fx                   = options.getBoolean("fx");
         _global_per_engine    = options.getBoolean("global.per.engine");
-        _lazy_compilation     = options.getBoolean("lazy.compilation");
         _optimistic_types     = options.getBoolean("optimistic.types");
+        final boolean lazy_compilation = options.getBoolean("lazy.compilation");
+        if (!lazy_compilation && _optimistic_types) {
+            if (!ALLOW_EAGER_COMPILATION_SILENT_OVERRIDE) {
+                throw new IllegalStateException(
+                        ECMAErrors.getMessage(
+                                "config.error.eagerCompilationConflictsWithOptimisticTypes",
+                                options.getOptionTemplateByKey("lazy.compilation").getName(),
+                                options.getOptionTemplateByKey("optimistic.types").getName()));
+            }
+            _lazy_compilation = true;
+        } else {
+            _lazy_compilation = lazy_compilation;
+        }
         _loader_per_compile   = options.getBoolean("loader.per.compile");
         _no_java              = options.getBoolean("no.java");
         _no_syntax_extensions = options.getBoolean("no.syntax.extensions");
--- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Thu Oct 29 17:22:12 2015 -0700
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
@@ -40,6 +39,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.concurrent.atomic.LongAdder;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
@@ -55,38 +55,54 @@
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 
 /**
- * Runtime representation of a JavaScript function.
+ * Runtime representation of a JavaScript function. This class has only private
+ * and protected constructors. There are no *public* constructors - but only
+ * factory methods that follow the naming pattern "createXYZ".
  */
-public abstract class ScriptFunction extends ScriptObject {
+public class ScriptFunction extends ScriptObject {
 
-    /** Method handle for prototype getter for this ScriptFunction */
+    /**
+     * Method handle for prototype getter for this ScriptFunction
+     */
     public static final MethodHandle G$PROTOTYPE = findOwnMH_S("G$prototype", Object.class, Object.class);
 
-    /** Method handle for prototype setter for this ScriptFunction */
+    /**
+     * Method handle for prototype setter for this ScriptFunction
+     */
     public static final MethodHandle S$PROTOTYPE = findOwnMH_S("S$prototype", void.class, Object.class, Object.class);
 
-    /** Method handle for length getter for this ScriptFunction */
+    /**
+     * Method handle for length getter for this ScriptFunction
+     */
     public static final MethodHandle G$LENGTH = findOwnMH_S("G$length", int.class, Object.class);
 
-    /** Method handle for name getter for this ScriptFunction */
+    /**
+     * Method handle for name getter for this ScriptFunction
+     */
     public static final MethodHandle G$NAME = findOwnMH_S("G$name", Object.class, Object.class);
 
-    /** Method handle used for implementing sync() in mozilla_compat */
+    /**
+     * Method handle used for implementing sync() in mozilla_compat
+     */
     public static final MethodHandle INVOKE_SYNC = findOwnMH_S("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class);
 
-    /** Method handle for allocate function for this ScriptFunction */
+    /**
+     * Method handle for allocate function for this ScriptFunction
+     */
     static final MethodHandle ALLOCATE = findOwnMH_V("allocate", Object.class);
 
     private static final MethodHandle WRAPFILTER = findOwnMH_S("wrapFilter", Object.class, Object.class);
 
     private static final MethodHandle SCRIPTFUNCTION_GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class);
 
-    /** method handle to scope getter for this ScriptFunction */
+    /**
+     * method handle to scope getter for this ScriptFunction
+     */
     public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class);
 
-    private static final MethodHandle IS_FUNCTION_MH  = findOwnMH_S("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class);
+    private static final MethodHandle IS_FUNCTION_MH = findOwnMH_S("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class);
 
-    private static final MethodHandle IS_APPLY_FUNCTION  = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class);
+    private static final MethodHandle IS_APPLY_FUNCTION = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class);
 
     private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH_S("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class);
 
@@ -94,55 +110,298 @@
 
     private static final MethodHandle WRAP_THIS = MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, "wrapThis", MH.type(Object.class, Object.class));
 
-    /** The parent scope. */
+    // various property maps used for different kinds of functions
+    // property map for anonymous function that serves as Function.prototype
+    private static final PropertyMap anonmap$;
+    // property map for strict mode functions
+    private static final PropertyMap strictmodemap$;
+    // property map for bound functions
+    private static final PropertyMap boundfunctionmap$;
+    // property map for non-strict, non-bound functions.
+    private static final PropertyMap map$;
+
+    // Marker object for lazily initialized prototype object
+    private static final Object LAZY_PROTOTYPE = new Object();
+
+    private static PropertyMap createStrictModeMap(final PropertyMap map) {
+        final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
+        PropertyMap newMap = map;
+        // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
+        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags));
+        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags));
+        return newMap;
+    }
+
+    private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) {
+        // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see
+        // ECMAScript 5.1 section 15.3.4.5
+        return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype"));
+    }
+
+    static {
+        anonmap$ = PropertyMap.newMap();
+        final ArrayList<Property> properties = new ArrayList<>(3);
+        properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE));
+        properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null));
+        properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null));
+        map$ = PropertyMap.newMap(properties);
+        strictmodemap$ = createStrictModeMap(map$);
+        boundfunctionmap$ = createBoundFunctionMap(strictmodemap$);
+    }
+
+    private static boolean isStrict(final int flags) {
+        return (flags & ScriptFunctionData.IS_STRICT) != 0;
+    }
+
+    // Choose the map based on strict mode!
+    private static PropertyMap getMap(final boolean strict) {
+        return strict ? strictmodemap$ : map$;
+    }
+
+    /**
+     * The parent scope.
+     */
     private final ScriptObject scope;
 
     private final ScriptFunctionData data;
 
-    /** The property map used for newly allocated object when function is used as constructor. */
+    /**
+     * The property map used for newly allocated object when function is used as
+     * constructor.
+     */
     protected PropertyMap allocatorMap;
 
     /**
+     * Reference to constructor prototype.
+     */
+    protected Object prototype;
+
+    /**
      * Constructor
      *
-     * @param name          function name
-     * @param methodHandle  method handle to function (if specializations are present, assumed to be most generic)
-     * @param map           property map
-     * @param scope         scope
-     * @param specs         specialized version of this function - other method handles
-     * @param flags         {@link ScriptFunctionData} flags
+     * @param data static function data
+     * @param map property map
+     * @param scope scope
      */
-    protected ScriptFunction(
+    private ScriptFunction(
+            final ScriptFunctionData data,
+            final PropertyMap map,
+            final ScriptObject scope,
+            final Global global) {
+
+        super(map);
+
+        if (Context.DEBUG) {
+            constructorCount.increment();
+        }
+
+        this.data = data;
+        this.scope = scope;
+        this.setInitialProto(global.getFunctionPrototype());
+        this.prototype = LAZY_PROTOTYPE;
+
+        // We have to fill user accessor functions late as these are stored
+        // in this object rather than in the PropertyMap of this object.
+        assert objectSpill == null;
+        if (isStrict() || isBoundFunction()) {
+            final ScriptFunction typeErrorThrower = global.getTypeErrorThrower();
+            initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+            initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+        }
+    }
+
+    /**
+     * Constructor
+     *
+     * @param name function name
+     * @param methodHandle method handle to function (if specializations are
+     * present, assumed to be most generic)
+     * @param map property map
+     * @param scope scope
+     * @param specs specialized version of this function - other method handles
+     * @param flags {@link ScriptFunctionData} flags
+     */
+    private ScriptFunction(
             final String name,
             final MethodHandle methodHandle,
             final PropertyMap map,
             final ScriptObject scope,
             final Specialization[] specs,
-            final int flags) {
-
-        this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope);
+            final int flags,
+            final Global global) {
+        this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope, global);
     }
 
     /**
      * Constructor
      *
-     * @param data          static function data
-     * @param map           property map
-     * @param scope         scope
+     * @param name name of function
+     * @param methodHandle handle for invocation
+     * @param scope scope object
+     * @param specs specialized versions of this method, if available, null
+     * otherwise
+     * @param flags {@link ScriptFunctionData} flags
+     */
+    private ScriptFunction(
+            final String name,
+            final MethodHandle methodHandle,
+            final ScriptObject scope,
+            final Specialization[] specs,
+            final int flags) {
+        this(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags, Global.instance());
+    }
+
+    /**
+     * Constructor called by Nasgen generated code, zero added members, use the
+     * default map. Creates builtin functions only.
+     *
+     * @param name name of function
+     * @param invokeHandle handle for invocation
+     * @param specs specialized versions of this method, if available, null
+     * otherwise
+     */
+    protected ScriptFunction(final String name, final MethodHandle invokeHandle, final Specialization[] specs) {
+        this(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR, Global.instance());
+    }
+
+    /**
+     * Constructor called by Nasgen generated code, non zero member count, use
+     * the map passed as argument. Creates builtin functions only.
+     *
+     * @param name name of function
+     * @param invokeHandle handle for invocation
+     * @param map initial property map
+     * @param specs specialized versions of this method, if available, null
+     * otherwise
+     */
+    protected ScriptFunction(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) {
+        this(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR, Global.instance());
+    }
+
+    // Factory methods to create various functions
+    /**
+     * Factory method called by compiler generated code for functions that need
+     * parent scope.
+     *
+     * @param constants the generated class' constant array
+     * @param index the index of the {@code RecompilableScriptFunctionData}
+     * object in the constants array.
+     * @param scope the parent scope object
+     * @return a newly created function object
      */
-    protected ScriptFunction(
-            final ScriptFunctionData data,
-            final PropertyMap map,
-            final ScriptObject scope) {
+    public static ScriptFunction create(final Object[] constants, final int index, final ScriptObject scope) {
+        final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constants[index];
+        return new ScriptFunction(data, getMap(data.isStrict()), scope, Global.instance());
+    }
+
+    /**
+     * Factory method called by compiler generated code for functions that don't
+     * need parent scope.
+     *
+     * @param constants the generated class' constant array
+     * @param index the index of the {@code RecompilableScriptFunctionData}
+     * object in the constants array.
+     * @return a newly created function object
+     */
+    public static ScriptFunction create(final Object[] constants, final int index) {
+        return create(constants, index, null);
+    }
+
+    /**
+     * Create anonymous function that serves as Function.prototype
+     *
+     * @return anonymous function object
+     */
+    public static ScriptFunction createAnonymous() {
+        return new ScriptFunction("", GlobalFunctions.ANONYMOUS, anonmap$, null);
+    }
+
+    // builtin function create helper factory
+    private static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) {
+        final ScriptFunction func = new ScriptFunction(name, methodHandle, null, specs, flags);
+        func.setPrototype(UNDEFINED);
+        // Non-constructor built-in functions do not have "prototype" property
+        func.deleteOwnProperty(func.getMap().findProperty("prototype"));
+
+        return func;
+    }
 
-        super(map);
+    /**
+     * Factory method for non-constructor built-in functions
+     *
+     * @param name function name
+     * @param methodHandle handle for invocation
+     * @param specs specialized versions of function if available, null
+     * otherwise
+     * @return new ScriptFunction
+     */
+    public static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle, final Specialization[] specs) {
+        return ScriptFunction.createBuiltin(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN);
+    }
 
-        if (Context.DEBUG) {
-            constructorCount++;
+    /**
+     * Factory method for non-constructor built-in functions
+     *
+     * @param name function name
+     * @param methodHandle handle for invocation
+     * @return new ScriptFunction
+     */
+    public static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle) {
+        return ScriptFunction.createBuiltin(name, methodHandle, null);
+    }
+
+    /**
+     * Factory method for non-constructor built-in, strict functions
+     *
+     * @param name function name
+     * @param methodHandle handle for invocation
+     * @return new ScriptFunction
+     */
+    public static ScriptFunction createStrictBuiltin(final String name, final MethodHandle methodHandle) {
+        return ScriptFunction.createBuiltin(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT);
+    }
+
+    // Subclass to represent bound functions
+    private static class Bound extends ScriptFunction {
+        private final ScriptFunction target;
+
+        Bound(final ScriptFunctionData boundData, final ScriptFunction target) {
+            super(boundData, boundfunctionmap$, null, Global.instance());
+            setPrototype(ScriptRuntime.UNDEFINED);
+            this.target = target;
         }
 
-        this.data  = data;
-        this.scope = scope;
+        @Override
+        protected ScriptFunction getTargetFunction() {
+            return target;
+        }
+    }
+
+    /**
+     * Creates a version of this function bound to a specific "self" and other
+     * arguments, as per {@code Function.prototype.bind} functionality in
+     * ECMAScript 5.1 section 15.3.4.5.
+     *
+     * @param self the self to bind to this function. Can be null (in which
+     * case, null is bound as this).
+     * @param args additional arguments to bind to this function. Can be null or
+     * empty to not bind additional arguments.
+     * @return a function with the specified self and parameters bound.
+     */
+    public final ScriptFunction createBound(final Object self, final Object[] args) {
+        return new Bound(data.makeBoundFunctionData(this, self, args), getTargetFunction());
+    }
+
+    /**
+     * Create a function that invokes this function synchronized on {@code sync}
+     * or the self object of the invocation.
+     *
+     * @param sync the Object to synchronize on, or undefined
+     * @return synchronized function
+     */
+    public final ScriptFunction createSynchronized(final Object sync) {
+        final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync);
+        return createBuiltin(getName(), mh);
     }
 
     @Override
@@ -151,8 +410,8 @@
     }
 
     /**
-     * ECMA 15.3.5.3 [[HasInstance]] (V)
-     * Step 3 if "prototype" value is not an Object, throw TypeError
+     * ECMA 15.3.5.3 [[HasInstance]] (V) Step 3 if "prototype" value is not an
+     * Object, throw TypeError
      */
     @Override
     public boolean isInstance(final ScriptObject instance) {
@@ -171,22 +430,25 @@
     }
 
     /**
-     * Returns the target function for this function. If the function was not created using
-     * {@link #makeBoundFunction(Object, Object[])}, its target function is itself. If it is bound, its target function
-     * is the target function of the function it was made from (therefore, the target function is always the final,
-     * unbound recipient of the calls).
+     * Returns the target function for this function. If the function was not
+     * created using {@link #createBound(Object, Object[])}, its target
+     * function is itself. If it is bound, its target function is the target
+     * function of the function it was made from (therefore, the target function
+     * is always the final, unbound recipient of the calls).
+     *
      * @return the target function for this function.
      */
     protected ScriptFunction getTargetFunction() {
         return this;
     }
 
-    boolean isBoundFunction() {
+    final boolean isBoundFunction() {
         return getTargetFunction() != this;
     }
 
     /**
      * Set the arity of this ScriptFunction
+     *
      * @param arity arity
      */
     public final void setArity(final int arity) {
@@ -195,125 +457,121 @@
 
     /**
      * Is this a ECMAScript 'use strict' function?
+     *
      * @return true if function is in strict mode
      */
-    public boolean isStrict() {
+    public final boolean isStrict() {
         return data.isStrict();
     }
 
     /**
-     * Returns true if this is a non-strict, non-built-in function that requires non-primitive this argument
-     * according to ECMA 10.4.3.
+     * Returns true if this is a non-strict, non-built-in function that requires
+     * non-primitive this argument according to ECMA 10.4.3.
+     *
      * @return true if this argument must be an object
      */
-    public boolean needsWrappedThis() {
+    public final boolean needsWrappedThis() {
         return data.needsWrappedThis();
     }
 
     private static boolean needsWrappedThis(final Object fn) {
-        return fn instanceof ScriptFunction ? ((ScriptFunction)fn).needsWrappedThis() : false;
+        return fn instanceof ScriptFunction ? ((ScriptFunction) fn).needsWrappedThis() : false;
     }
 
     /**
      * Execute this script function.
-     * @param self  Target object.
-     * @param arguments  Call arguments.
+     *
+     * @param self Target object.
+     * @param arguments Call arguments.
      * @return ScriptFunction result.
-     * @throws Throwable if there is an exception/error with the invocation or thrown from it
+     * @throws Throwable if there is an exception/error with the invocation or
+     * thrown from it
      */
-    Object invoke(final Object self, final Object... arguments) throws Throwable {
+    final Object invoke(final Object self, final Object... arguments) throws Throwable {
         if (Context.DEBUG) {
-            invokes++;
+            invokes.increment();
         }
         return data.invoke(this, self, arguments);
     }
 
     /**
      * Execute this script function as a constructor.
-     * @param arguments  Call arguments.
+     *
+     * @param arguments Call arguments.
      * @return Newly constructed result.
-     * @throws Throwable if there is an exception/error with the invocation or thrown from it
+     * @throws Throwable if there is an exception/error with the invocation or
+     * thrown from it
      */
-    Object construct(final Object... arguments) throws Throwable {
+    final Object construct(final Object... arguments) throws Throwable {
         return data.construct(this, arguments);
     }
 
     /**
-     * Allocate function. Called from generated {@link ScriptObject} code
-     * for allocation as a factory method
+     * Allocate function. Called from generated {@link ScriptObject} code for
+     * allocation as a factory method
      *
-     * @return a new instance of the {@link ScriptObject} whose allocator this is
+     * @return a new instance of the {@link ScriptObject} whose allocator this
+     * is
      */
     @SuppressWarnings("unused")
     private Object allocate() {
         if (Context.DEBUG) {
-            allocations++;
+            allocations.increment();
         }
 
         assert !isBoundFunction(); // allocate never invoked on bound functions
 
-        final ScriptObject object = data.allocate(getAllocatorMap());
+        final ScriptObject prototype = getAllocatorPrototype();
+        final ScriptObject object = data.allocate(getAllocatorMap(prototype));
 
         if (object != null) {
-            final Object prototype = getPrototype();
-            if (prototype instanceof ScriptObject) {
-                object.setInitialProto((ScriptObject)prototype);
-            }
-
-            if (object.getProto() == null) {
-                object.setInitialProto(getObjectPrototype());
-            }
+            object.setInitialProto(prototype);
         }
 
         return object;
     }
 
-    private PropertyMap getAllocatorMap() {
-        if (allocatorMap == null) {
-            allocatorMap = data.getAllocatorMap();
+    /**
+     * Get the property map used by "allocate"
+     * @param prototype actual prototype object
+     * @return property map
+     */
+    private synchronized PropertyMap getAllocatorMap(final ScriptObject prototype) {
+        if (allocatorMap == null || allocatorMap.isInvalidSharedMapFor(prototype)) {
+            // The prototype map has changed since this function was last used as constructor.
+            // Get a new allocator map.
+            allocatorMap = data.getAllocatorMap(prototype);
         }
         return allocatorMap;
     }
 
     /**
-     * Return Object.prototype - used by "allocate"
-     * @return Object.prototype
-     */
-    protected abstract ScriptObject getObjectPrototype();
-
-    /**
-     * Creates a version of this function bound to a specific "self" and other arguments, as per
-     * {@code Function.prototype.bind} functionality in ECMAScript 5.1 section 15.3.4.5.
-     * @param self the self to bind to this function. Can be null (in which case, null is bound as this).
-     * @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments.
-     * @return a function with the specified self and parameters bound.
+     * Return the actual prototype used by "allocate"
+     * @return allocator prototype
      */
-    protected ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
-        return makeBoundFunction(data.makeBoundFunctionData(this, self, args));
+    private ScriptObject getAllocatorPrototype() {
+        final Object prototype = getPrototype();
+        if (prototype instanceof ScriptObject) {
+            return (ScriptObject) prototype;
+        }
+        return Global.objectPrototype();
     }
 
-    /**
-     * Create a version of this function as in {@link ScriptFunction#makeBoundFunction(Object, Object[])},
-     * but using a {@link ScriptFunctionData} for the bound data.
-     *
-     * @param boundData ScriptFuntionData for the bound function
-     * @return a function with the bindings performed according to the given data
-     */
-    protected abstract ScriptFunction makeBoundFunction(ScriptFunctionData boundData);
-
     @Override
     public final String safeToString() {
         return toSource();
     }
 
     @Override
-    public String toString() {
+    public final String toString() {
         return data.toString();
     }
 
     /**
-     * Get this function as a String containing its source code. If no source code
-     * exists in this ScriptFunction, its contents will be displayed as {@code [native code]}
+     * Get this function as a String containing its source code. If no source
+     * code exists in this ScriptFunction, its contents will be displayed as
+     * {@code [native code]}
+     *
      * @return string representation of this function's source
      */
     public final String toSource() {
@@ -322,27 +580,32 @@
 
     /**
      * Get the prototype object for this function
+     *
      * @return prototype
      */
-    public abstract Object getPrototype();
+    public final Object getPrototype() {
+        if (prototype == LAZY_PROTOTYPE) {
+            prototype = new PrototypeObject(this);
+        }
+        return prototype;
+    }
 
     /**
      * Set the prototype object for this function
-     * @param prototype new prototype object
+     *
+     * @param newPrototype new prototype object
      */
-    public abstract void setPrototype(Object prototype);
+    public synchronized final void setPrototype(final Object newPrototype) {
+        if (newPrototype instanceof ScriptObject && newPrototype != this.prototype && allocatorMap != null) {
+            // Unset allocator map to be replaced with one matching the new prototype.
+            allocatorMap = null;
+        }
+        this.prototype = newPrototype;
+    }
 
     /**
-     * Create a function that invokes this function synchronized on {@code sync} or the self object
-     * of the invocation.
-     * @param sync the Object to synchronize on, or undefined
-     * @return synchronized function
-     */
-   public abstract ScriptFunction makeSynchronizedFunction(Object sync);
-
-    /**
-     * Return the invoke handle bound to a given ScriptObject self reference.
-     * If callee parameter is required result is rebound to this.
+     * Return the invoke handle bound to a given ScriptObject self reference. If
+     * callee parameter is required result is rebound to this.
      *
      * @param self self reference
      * @return bound invoke handle
@@ -352,9 +615,12 @@
     }
 
     /**
-     * Bind the method handle to this {@code ScriptFunction} instance if it needs a callee parameter. If this function's
-     * method handles don't have a callee parameter, the handle is returned unchanged.
-     * @param methodHandle the method handle to potentially bind to this function instance.
+     * Bind the method handle to this {@code ScriptFunction} instance if it
+     * needs a callee parameter. If this function's method handles don't have a
+     * callee parameter, the handle is returned unchanged.
+     *
+     * @param methodHandle the method handle to potentially bind to this
+     * function instance.
      * @return the potentially bound method handle
      */
     private MethodHandle bindToCalleeIfNeeded(final MethodHandle methodHandle) {
@@ -364,15 +630,16 @@
 
     /**
      * Get the name for this function
+     *
      * @return the name
      */
     public final String getName() {
         return data.getName();
     }
 
-
     /**
      * Get the scope for this function
+     *
      * @return the scope
      */
     public final ScriptObject getScope() {
@@ -383,36 +650,37 @@
      * Prototype getter for this ScriptFunction - follows the naming convention
      * used by Nasgen and the code generator
      *
-     * @param self  self reference
+     * @param self self reference
      * @return self's prototype
      */
     public static Object G$prototype(final Object self) {
-        return self instanceof ScriptFunction ?
-            ((ScriptFunction)self).getPrototype() :
-            UNDEFINED;
+        return self instanceof ScriptFunction
+                ? ((ScriptFunction) self).getPrototype()
+                : UNDEFINED;
     }
 
     /**
      * Prototype setter for this ScriptFunction - follows the naming convention
      * used by Nasgen and the code generator
      *
-     * @param self  self reference
+     * @param self self reference
      * @param prototype prototype to set
      */
     public static void S$prototype(final Object self, final Object prototype) {
         if (self instanceof ScriptFunction) {
-            ((ScriptFunction)self).setPrototype(prototype);
+            ((ScriptFunction) self).setPrototype(prototype);
         }
     }
 
     /**
      * Length getter - ECMA 15.3.3.2: Function.length
+     *
      * @param self self reference
      * @return length
      */
     public static int G$length(final Object self) {
         if (self instanceof ScriptFunction) {
-            return ((ScriptFunction)self).data.getArity();
+            return ((ScriptFunction) self).data.getArity();
         }
 
         return 0;
@@ -420,12 +688,13 @@
 
     /**
      * Name getter - ECMA Function.name
+     *
      * @param self self refence
      * @return the name, or undefined if none
      */
     public static Object G$name(final Object self) {
         if (self instanceof ScriptFunction) {
-            return ((ScriptFunction)self).getName();
+            return ((ScriptFunction) self).getName();
         }
 
         return UNDEFINED;
@@ -433,6 +702,7 @@
 
     /**
      * Get the prototype for this ScriptFunction
+     *
      * @param constructor constructor
      * @return prototype, or null if given constructor is not a ScriptFunction
      */
@@ -440,7 +710,7 @@
         if (constructor != null) {
             final Object proto = constructor.getPrototype();
             if (proto instanceof ScriptObject) {
-                return (ScriptObject)proto;
+                return (ScriptObject) proto;
             }
         }
 
@@ -448,29 +718,37 @@
     }
 
     // These counters are updated only in debug mode.
-    private static int constructorCount;
-    private static int invokes;
-    private static int allocations;
+    private static LongAdder constructorCount;
+    private static LongAdder invokes;
+    private static LongAdder allocations;
+
+    static {
+        if (Context.DEBUG) {
+            constructorCount = new LongAdder();
+            invokes = new LongAdder();
+            allocations = new LongAdder();
+        }
+    }
 
     /**
      * @return the constructorCount
      */
-    public static int getConstructorCount() {
-        return constructorCount;
+    public static long getConstructorCount() {
+        return constructorCount.longValue();
     }
 
     /**
      * @return the invokes
      */
-    public static int getInvokes() {
-        return invokes;
+    public static long getInvokes() {
+        return invokes.longValue();
     }
 
     /**
      * @return the allocations
      */
-    public static int getAllocations() {
-        return allocations;
+    public static long getAllocations() {
+        return allocations.longValue();
     }
 
     @Override
@@ -490,7 +768,6 @@
         return Context.getGlobal().wrapAsObject(obj);
     }
 
-
     @SuppressWarnings("unused")
     private static Object globalFilter(final Object object) {
         // replace whatever we get with the current global object
@@ -498,14 +775,16 @@
     }
 
     /**
-     * Some receivers are primitive, in that case, according to the Spec we create a new
-     * native object per callsite with the wrap filter. We can only apply optimistic builtins
-     * if there is no per instance state saved for these wrapped objects (e.g. currently NativeStrings),
-     * otherwise we can't create optimistic versions
+     * Some receivers are primitive, in that case, according to the Spec we
+     * create a new native object per callsite with the wrap filter. We can only
+     * apply optimistic builtins if there is no per instance state saved for
+     * these wrapped objects (e.g. currently NativeStrings), otherwise we can't
+     * create optimistic versions
      *
-     * @param self            receiver
-     * @param linkLogicClass  linkLogicClass, or null if no link logic exists
-     * @return link logic instance, or null if one could not be constructed for this receiver
+     * @param self receiver
+     * @param linkLogicClass linkLogicClass, or null if no link logic exists
+     * @return link logic instance, or null if one could not be constructed for
+     * this receiver
      */
     private static LinkLogic getLinkLogic(final Object self, final Class<? extends LinkLogic> linkLogicClass) {
         if (linkLogicClass == null) {
@@ -518,25 +797,25 @@
 
         final Object wrappedSelf = wrapFilter(self);
         if (wrappedSelf instanceof OptimisticBuiltins) {
-            if (wrappedSelf != self && ((OptimisticBuiltins)wrappedSelf).hasPerInstanceAssumptions()) {
+            if (wrappedSelf != self && ((OptimisticBuiltins) wrappedSelf).hasPerInstanceAssumptions()) {
                 return null; //pessimistic - we created a wrapped object different from the primitive, but the assumptions have instance state
             }
-            return ((OptimisticBuiltins)wrappedSelf).getLinkLogic(linkLogicClass);
+            return ((OptimisticBuiltins) wrappedSelf).getLinkLogic(linkLogicClass);
         }
         return null;
     }
 
     /**
-     * dyn:call call site signature: (callee, thiz, [args...])
-     * generated method signature:   (callee, thiz, [args...])
+     * dyn:call call site signature: (callee, thiz, [args...]) generated method
+     * signature: (callee, thiz, [args...])
      *
      * cases:
      * (a) method has callee parameter
-     *   (1) for local/scope calls, we just bind thiz and drop the second argument.
-     *   (2) for normal this-calls, we have to swap thiz and callee to get matching signatures.
+     *     (1) for local/scope calls, we just bind thiz and drop the second argument.
+     *     (2) for normal this-calls, we have to swap thiz and callee to get matching signatures.
      * (b) method doesn't have callee parameter (builtin functions)
-     *   (3) for local/scope calls, bind thiz and drop both callee and thiz.
-     *   (4) for normal this-calls, drop callee.
+     *     (3) for local/scope calls, bind thiz and drop both callee and thiz.
+     *     (4) for normal this-calls, drop callee.
      *
      * @return guarded invocation for call
      */
@@ -544,11 +823,11 @@
     protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final MethodType type = desc.getMethodType();
 
-        final String  name       = getName();
+        final String name = getName();
         final boolean isUnstable = request.isCallSiteUnstable();
-        final boolean scopeCall  = NashornCallSiteDescriptor.isScope(desc);
-        final boolean isCall     = !scopeCall && data.isBuiltin() && "call".equals(name);
-        final boolean isApply    = !scopeCall && data.isBuiltin() && "apply".equals(name);
+        final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
+        final boolean isCall = !scopeCall && data.isBuiltin() && "call".equals(name);
+        final boolean isApply = !scopeCall && data.isBuiltin() && "apply".equals(name);
 
         final boolean isApplyOrCall = isCall | isApply;
 
@@ -569,7 +848,7 @@
             return new GuardedInvocation(
                     handle,
                     null,
-                    (SwitchPoint)null,
+                    (SwitchPoint) null,
                     ClassCastException.class);
         }
 
@@ -672,14 +951,14 @@
                                 this,
                                 cf.getFlags()) :
                         guard,
-                        spsArray,
+                spsArray,
                 exceptionGuard);
     }
 
     private GuardedInvocation createApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc, final LinkRequest request, final Object[] args) {
         final MethodType descType = desc.getMethodType();
         final int paramCount = descType.parameterCount();
-        if(descType.parameterType(paramCount - 1).isArray()) {
+        if (descType.parameterType(paramCount - 1).isArray()) {
             // This is vararg invocation of apply or call. This can normally only happen when we do a recursive
             // invocation of createApplyOrCallCall (because we're doing apply-of-apply). In this case, create delegate
             // linkage by unpacking the vararg invocation and use pairArguments to introduce the necessary spreader.
@@ -786,7 +1065,7 @@
                 inv = MH.filterArguments(inv, 2, NativeFunction.TO_APPLY_ARGS);
             } else {
                 // If the original call site doesn't pass argArray, pass in an empty array
-                inv = MH.insertArguments(inv, 2, (Object)ScriptRuntime.EMPTY_ARRAY);
+                inv = MH.insertArguments(inv, 2, (Object) ScriptRuntime.EMPTY_ARRAY);
             }
         }
 
@@ -851,7 +1130,7 @@
             final LinkRequest request, final Object[] args) {
         final MethodType descType = desc.getMethodType();
         final int paramCount = descType.parameterCount();
-        final Object[] varArgs = (Object[])args[paramCount - 1];
+        final Object[] varArgs = (Object[]) args[paramCount - 1];
         // -1 'cause we're not passing the vararg array itself
         final int copiedArgCount = args.length - 1;
         final int varArgCount = varArgs.length;
@@ -893,7 +1172,7 @@
         // If the last parameter type of the guard is an array, then it is already itself a guard for a vararg apply
         // invocation. We must filter the last argument with toApplyArgs otherwise deeper levels of nesting will fail
         // with ClassCastException of NativeArray to Object[].
-        if(guardType.parameterType(guardParamCount - 1).isArray()) {
+        if (guardType.parameterType(guardParamCount - 1).isArray()) {
             arrayConvertingGuard = MH.filterArguments(guard, guardParamCount - 1, NativeFunction.TO_APPLY_ARGS);
         } else {
             arrayConvertingGuard = guard;
@@ -903,19 +1182,20 @@
     }
 
     private static MethodHandle bindImplicitThis(final Object fn, final MethodHandle mh) {
-         final MethodHandle bound;
-         if(fn instanceof ScriptFunction && ((ScriptFunction)fn).needsWrappedThis()) {
-             bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER);
-         } else {
-             bound = mh;
-         }
-         return MH.insertArguments(bound, 1, ScriptRuntime.UNDEFINED);
-     }
+        final MethodHandle bound;
+        if (fn instanceof ScriptFunction && ((ScriptFunction) fn).needsWrappedThis()) {
+            bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER);
+        } else {
+            bound = mh;
+        }
+        return MH.insertArguments(bound, 1, ScriptRuntime.UNDEFINED);
+    }
 
     /**
      * Used for noSuchMethod/noSuchProperty and JSAdapter hooks.
      *
-     * These don't want a callee parameter, so bind that. Name binding is optional.
+     * These don't want a callee parameter, so bind that. Name binding is
+     * optional.
      */
     MethodHandle getCallMethodHandle(final MethodType type, final String bindName) {
         return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(data.getGenericInvoker(scope)), bindName), type);
@@ -939,10 +1219,11 @@
     }
 
     /**
-     * Get the guard that checks if a {@link ScriptFunction} is equal to
-     * a known ScriptFunction, using reference comparison
+     * Get the guard that checks if a {@link ScriptFunction} is equal to a known
+     * ScriptFunction, using reference comparison
      *
-     * @param function The ScriptFunction to check against. This will be bound to the guard method handle
+     * @param function The ScriptFunction to check against. This will be bound
+     * to the guard method handle
      *
      * @return method handle for guard
      */
@@ -957,11 +1238,12 @@
     }
 
     /**
-     * Get a guard that checks if a {@link ScriptFunction} is equal to
-     * a known ScriptFunction using reference comparison, and whether the type of
-     * the second argument (this-object) is not a JavaScript primitive type.
+     * Get a guard that checks if a {@link ScriptFunction} is equal to a known
+     * ScriptFunction using reference comparison, and whether the type of the
+     * second argument (this-object) is not a JavaScript primitive type.
      *
-     * @param function The ScriptFunction to check against. This will be bound to the guard method handle
+     * @param function The ScriptFunction to check against. This will be bound
+     * to the guard method handle
      *
      * @return method handle for guard
      */
@@ -972,12 +1254,12 @@
 
     @SuppressWarnings("unused")
     private static boolean isFunctionMH(final Object self, final ScriptFunctionData data) {
-        return self instanceof ScriptFunction && ((ScriptFunction)self).data == data;
+        return self instanceof ScriptFunction && ((ScriptFunction) self).data == data;
     }
 
     @SuppressWarnings("unused")
     private static boolean isNonStrictFunction(final Object self, final Object arg, final ScriptFunctionData data) {
-        return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject;
+        return self instanceof ScriptFunction && ((ScriptFunction) self).data == data && arg instanceof ScriptObject;
     }
 
     //TODO this can probably be removed given that we have builtin switchpoints in the context
@@ -990,7 +1272,7 @@
     @SuppressWarnings("unused")
     private static Object[] addZerothElement(final Object[] args, final Object value) {
         // extends input array with by adding new zeroth element
-        final Object[] src = args == null? ScriptRuntime.EMPTY_ARRAY : args;
+        final Object[] src = args == null ? ScriptRuntime.EMPTY_ARRAY : args;
         final Object[] result = new Object[src.length + 1];
         System.arraycopy(src, 0, result, 1, src.length);
         result[0] = value;
@@ -1014,4 +1296,3 @@
         return MH.findVirtual(MethodHandles.lookup(), ScriptFunction.class, name, MH.type(rtype, types));
     }
 }
-
--- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Thu Oct 29 17:22:12 2015 -0700
@@ -151,7 +151,7 @@
      * Is this a ScriptFunction generated with strict semantics?
      * @return true if strict, false otherwise
      */
-    public boolean isStrict() {
+    public final boolean isStrict() {
         return (flags & IS_STRICT) != 0;
     }
 
@@ -164,11 +164,11 @@
         return getName();
     }
 
-    boolean isBuiltin() {
+    final boolean isBuiltin() {
         return (flags & IS_BUILTIN) != 0;
     }
 
-    boolean isConstructor() {
+    final boolean isConstructor() {
         return (flags & IS_CONSTRUCTOR) != 0;
     }
 
@@ -179,7 +179,7 @@
      * according to ECMA 10.4.3.
      * @return true if this argument must be an object
      */
-    boolean needsWrappedThis() {
+    final boolean needsWrappedThis() {
         return (flags & USES_THIS) != 0 && (flags & IS_STRICT_OR_BUILTIN) == 0;
     }
 
@@ -318,7 +318,7 @@
      * Used to find an apply to call version that fits this callsite.
      * We cannot just, as in the normal matcher case, return e.g. (Object, Object, int)
      * for (Object, Object, int, int, int) or we will destroy the semantics and get
-     * a function that, when padded with undefineds, behaves differently
+     * a function that, when padded with undefined values, behaves differently
      * @param type actual call site type
      * @return apply to call that perfectly fits this callsite or null if none found
      */
@@ -359,31 +359,13 @@
      * scope is not known, but that might cause compilation of code that will need more deoptimization passes.
      * @return the best function for the specified call site type.
      */
-    CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
-        assert callSiteType.parameterCount() >= 2 : callSiteType; // Must have at least (callee, this)
-        assert callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class) : callSiteType; // Callee must be assignable from script function
-
-        if (isRecompilable()) {
-            final CompiledFunction candidate = pickFunction(callSiteType, false);
-            if (candidate != null) {
-                return candidate;
-            }
-            return pickFunction(callSiteType, true); //try vararg last
-        }
+    abstract CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden);
 
-        CompiledFunction best = null;
-        for (final CompiledFunction candidate: code) {
-            if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) {
-                best = candidate;
-            }
-        }
-
-        return best;
+    boolean isValidCallSite(final MethodType callSiteType) {
+        return callSiteType.parameterCount() >= 2  && // Must have at least (callee, this)
+               callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class); // Callee must be assignable from script function
     }
 
-
-    abstract boolean isRecompilable();
-
     CompiledFunction getGeneric(final ScriptObject runtimeScope) {
         return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS);
     }
@@ -407,15 +389,16 @@
     /**
      * Get the property map to use for objects allocated by this function.
      *
+     * @param prototype the prototype of the allocated object
      * @return the property map for allocated objects.
      */
-    PropertyMap getAllocatorMap() {
+    PropertyMap getAllocatorMap(final ScriptObject prototype) {
         return null;
     }
 
     /**
      * This method is used to create the immutable portion of a bound function.
-     * See {@link ScriptFunction#makeBoundFunction(Object, Object[])}
+     * See {@link ScriptFunction#createBound(Object, Object[])}
      *
      * @param fn the original function being bound
      * @param self this reference to bind. Can be null.
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Oct 29 17:22:12 2015 -0700
@@ -64,6 +64,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.LongAdder;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
@@ -148,7 +149,7 @@
     /** Method handle to retrieve prototype of this object */
     public static final MethodHandle GETPROTO      = findOwnMH_V("getProto", ScriptObject.class);
 
-    static final MethodHandle MEGAMORPHIC_GET    = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class);
+    static final MethodHandle MEGAMORPHIC_GET    = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.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);
 
@@ -211,7 +212,7 @@
     */
     public ScriptObject(final PropertyMap map) {
         if (Context.DEBUG) {
-            ScriptObject.count++;
+            ScriptObject.count.increment();
         }
         this.arrayData = ArrayData.EMPTY_ARRAY;
         this.setMap(map == null ? PropertyMap.newMap() : map);
@@ -224,7 +225,7 @@
      * same combination of prototype and property map.
      *
      * @param proto the prototype object
-     * @param map intial {@link PropertyMap}
+     * @param map initial {@link PropertyMap}
      */
     protected ScriptObject(final ScriptObject proto, final PropertyMap map) {
         this(map);
@@ -287,9 +288,10 @@
      */
     public void addBoundProperties(final ScriptObject source, final Property[] properties) {
         PropertyMap newMap = this.getMap();
+        final boolean extensible = newMap.isExtensible();
 
         for (final Property property : properties) {
-            newMap = addBoundProperty(newMap, source, property);
+            newMap = addBoundProperty(newMap, source, property, extensible);
         }
 
         this.setMap(newMap);
@@ -302,13 +304,18 @@
      * @param propMap the property map
      * @param source the source object
      * @param property the property to be added
+     * @param extensible whether the current object is extensible or not
      * @return the new property map
      */
-    protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property) {
+    protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property, final boolean extensible) {
         PropertyMap newMap = propMap;
         final String key = property.getKey();
         final Property oldProp = newMap.findProperty(key);
         if (oldProp == null) {
+            if (! extensible) {
+                throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
+            }
+
             if (property instanceof UserAccessorProperty) {
                 // Note: we copy accessor functions to this object which is semantically different from binding.
                 final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
@@ -337,11 +344,15 @@
      */
     public void addBoundProperties(final Object source, final AccessorProperty[] properties) {
         PropertyMap newMap = this.getMap();
+        final boolean extensible = newMap.isExtensible();
 
         for (final AccessorProperty property : properties) {
             final String key = property.getKey();
 
             if (newMap.findProperty(key) == null) {
+                if (! extensible) {
+                    throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
+                }
                 newMap = newMap.addPropertyBind(property, source);
             }
         }
@@ -699,8 +710,7 @@
         final long longIndex = ArrayIndex.toLongIndex(index);
         final long oldLength = getArray().length();
         if (longIndex >= oldLength) {
-            setArray(getArray().ensure(longIndex));
-            doesNotHaveEnsureDelete(longIndex, oldLength, false);
+            setArray(getArray().ensure(longIndex).safeDelete(oldLength, longIndex - 1, false));
         }
         setArray(getArray().set(index, value, false));
     }
@@ -798,9 +808,11 @@
 
         if (deep) {
             final ScriptObject myProto = getProto();
-            if (myProto != null) {
-                return myProto.findProperty(key, deep, start);
-            }
+            final FindProperty find = myProto == null ? null : myProto.findProperty(key, true, start);
+            // checkSharedProtoMap must be invoked after myProto.checkSharedProtoMap to propagate
+            // shared proto invalidation up the prototype chain. It also must be invoked when prototype is null.
+            checkSharedProtoMap();
+            return find;
         }
 
         return null;
@@ -821,7 +833,7 @@
         if (deep) {
             final ScriptObject myProto = getProto();
             if (myProto != null) {
-                return myProto.hasProperty(key, deep);
+                return myProto.hasProperty(key, true);
             }
         }
 
@@ -1247,11 +1259,8 @@
         if (oldProto != newProto) {
             proto = newProto;
 
-            // Let current listeners know that the protototype has changed and set our map
-            final PropertyListeners listeners = getMap().getListeners();
-            if (listeners != null) {
-                listeners.protoChanged();
-            }
+            // Let current listeners know that the prototype has changed
+            getMap().protoChanged(true);
             // Replace our current allocator map with one that is associated with the new prototype.
             setMap(getMap().changeProto(newProto));
         }
@@ -1303,7 +1312,7 @@
                 }
                 p = p.getProto();
             }
-            setProto((ScriptObject)newProto);
+            setProto((ScriptObject) newProto);
         } else {
             throw typeError("cant.set.proto.to.non.object", ScriptRuntime.safeToString(this), ScriptRuntime.safeToString(newProto));
         }
@@ -1442,7 +1451,7 @@
      * in {@link ScriptFunction} for hasInstance implementation, walks
      * the proto chain
      *
-     * @param instance instace to check
+     * @param instance instance to check
      * @return true if 'instance' is an instance of this object
      */
     public boolean isInstance(final ScriptObject instance) {
@@ -1849,7 +1858,7 @@
      * @return GuardedInvocation to be invoked at call site.
      */
     protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
-        return notAFunction();
+        return notAFunction(desc);
     }
 
     /**
@@ -1859,14 +1868,14 @@
      * @param desc    the call site descriptor.
      * @param request the link request
      *
-     * @return GuardedInvocation to be invoed at call site.
+     * @return GuardedInvocation to be invoked at call site.
      */
     protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
-        return notAFunction();
+        return notAFunction(desc);
     }
 
-    private GuardedInvocation notAFunction() {
-        throw typeError("not.a.function", ScriptRuntime.safeToString(this));
+    private GuardedInvocation notAFunction(final CallSiteDescriptor desc) {
+        throw typeError("not.a.function", NashornCallSiteDescriptor.getFunctionErrorMessage(desc, this));
     }
 
     /**
@@ -1986,11 +1995,11 @@
         final ScriptObject owner = find.getOwner();
         final Class<ClassCastException> exception = explicitInstanceOfCheck ? null : ClassCastException.class;
 
-        final SwitchPoint protoSwitchPoint;
+        final SwitchPoint[] protoSwitchPoints;
 
         if (mh == null) {
             mh = Lookup.emptyGetter(returnType);
-            protoSwitchPoint = getProtoSwitchPoint(name, owner);
+            protoSwitchPoints = getProtoSwitchPoints(name, owner);
         } else if (!find.isSelf()) {
             assert mh.type().returnType().equals(returnType) :
                     "return type mismatch for getter " + mh.type().returnType() + " != " + returnType;
@@ -1998,30 +2007,30 @@
                 // Add a filter that replaces the self object with the prototype owning the property.
                 mh = addProtoFilter(mh, find.getProtoChainLength());
             }
-            protoSwitchPoint = getProtoSwitchPoint(name, owner);
+            protoSwitchPoints = getProtoSwitchPoints(name, owner);
         } else {
-            protoSwitchPoint = null;
+            protoSwitchPoints = null;
         }
 
-        final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoint, exception);
+        final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoints, exception);
         return inv.addSwitchPoint(findBuiltinSwitchPoint(name));
     }
 
     private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
         Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
-        final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
+        final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, NashornCallSiteDescriptor.isScope(desc));
         final MethodHandle guard   = getScriptObjectGuard(desc.getMethodType(), true);
         return new GuardedInvocation(invoker, guard);
     }
 
     @SuppressWarnings("unused")
-    private Object megamorphicGet(final String key, final boolean isMethod) {
+    private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
         final FindProperty find = findProperty(key, true);
         if (find != null) {
             return find.getObjectValue();
         }
 
-        return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
+        return isMethod ? getNoSuchMethod(key, isScope, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, isScope, INVALID_PROGRAM_POINT);
     }
 
     // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST
@@ -2102,17 +2111,32 @@
      * @param owner the property owner, null if property is not defined
      * @return a SwitchPoint or null
      */
-    public final SwitchPoint getProtoSwitchPoint(final String name, final ScriptObject owner) {
+    public final SwitchPoint[] getProtoSwitchPoints(final String name, final ScriptObject owner) {
         if (owner == this || getProto() == null) {
             return null;
         }
 
+        final List<SwitchPoint> switchPoints = new ArrayList<>();
         for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
             final ScriptObject parent = obj.getProto();
             parent.getMap().addListener(name, obj.getMap());
+            final SwitchPoint sp = parent.getMap().getSharedProtoSwitchPoint();
+            if (sp != null && !sp.hasBeenInvalidated()) {
+                switchPoints.add(sp);
+            }
         }
 
-        return getMap().getSwitchPoint(name);
+        switchPoints.add(getMap().getSwitchPoint(name));
+        return switchPoints.toArray(new SwitchPoint[switchPoints.size()]);
+    }
+
+    private void checkSharedProtoMap() {
+        // Check if our map has an expected shared prototype property map. If it has, make sure that
+        // the prototype map has not been invalidated, and that it does match the actual map of the prototype.
+        if (getMap().isInvalidSharedMapFor(getProto())) {
+            // Change our own map to one that does not assume a shared prototype map.
+            setMap(getMap().makeUnsharedCopy());
+        }
     }
 
     /**
@@ -2194,7 +2218,7 @@
         return new GuardedInvocation(
                 Lookup.EMPTY_SETTER,
                 NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck),
-                getProtoSwitchPoint(name, null),
+                getProtoSwitchPoints(name, null),
                 explicitInstanceOfCheck ? null : ClassCastException.class);
     }
 
@@ -2291,7 +2315,7 @@
                 MH.dropArguments(
                         MH.constant(
                                 ScriptFunction.class,
-                                func.makeBoundFunction(thiz, new Object[] { name })),
+                                func.createBound(thiz, new Object[] { name })),
                         0,
                         Object.class),
                 NashornGuards.combineGuards(
@@ -2340,7 +2364,7 @@
                                 find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
                                 find.getProtoChainLength(),
                                 func),
-                        getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
+                        getProtoSwitchPoints(NO_SUCH_PROPERTY_NAME, find.getOwner()),
                         //TODO this doesn't need a ClassCastException as guard always checks script object
                         null);
             }
@@ -2356,20 +2380,21 @@
     /**
      * Invoke fall back if a property is not found.
      * @param name Name of property.
+     * @param isScope is this a scope access?
      * @param programPoint program point
      * @return Result from call.
      */
-    protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+    protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) {
         final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
+        final Object func = (find != null)? find.getObjectValue() : null;
 
         Object ret = UNDEFINED;
-
-        if (find != null) {
-            final Object func = find.getObjectValue();
-
-            if (func instanceof ScriptFunction) {
-                ret = ScriptRuntime.apply((ScriptFunction)func, this, name);
-            }
+        if (func instanceof ScriptFunction) {
+            final ScriptFunction sfunc = (ScriptFunction)func;
+            final Object self = isScope && sfunc.isStrict()? UNDEFINED : this;
+            ret = ScriptRuntime.apply(sfunc, self, name);
+        } else if (isScope) {
+            throw referenceError("not.defined", name);
         }
 
         if (isValid(programPoint)) {
@@ -2383,21 +2408,27 @@
     /**
      * Get __noSuchMethod__ as a function bound to this object and {@code name} if it is defined.
      * @param name the method name
+     * @param isScope is this a scope access?
      * @return the bound function, or undefined
      */
-    private Object getNoSuchMethod(final String name, final int programPoint) {
+    private Object getNoSuchMethod(final String name, final boolean isScope, final int programPoint) {
         final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true);
 
         if (find == null) {
-            return invokeNoSuchProperty(name, programPoint);
+            return invokeNoSuchProperty(name, isScope, programPoint);
         }
 
         final Object value = find.getObjectValue();
         if (!(value instanceof ScriptFunction)) {
+            if (isScope) {
+                throw referenceError("not.defined", name);
+            }
             return UNDEFINED;
         }
 
-        return ((ScriptFunction)value).makeBoundFunction(this, new Object[] {name});
+        final ScriptFunction func = (ScriptFunction)value;
+        final Object self = isScope && func.isStrict()? UNDEFINED : this;
+        return func.createBound(self, new Object[] {name});
     }
 
     private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String name) {
@@ -2406,7 +2437,7 @@
         }
 
         return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
-                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoint(name, null),
+                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoints(name, null),
                 explicitInstanceOfCheck ? null : ClassCastException.class);
     }
 
@@ -2646,11 +2677,7 @@
         }
 
         if (newLength > arrayLength) {
-            data = data.ensure(newLength - 1);
-            if (data.canDelete(arrayLength, newLength - 1, false)) {
-               data = data.delete(arrayLength, newLength - 1);
-            }
-            setArray(data);
+            setArray(data.ensure(newLength - 1).safeDelete(arrayLength, newLength - 1, false));
             return;
         }
 
@@ -2712,7 +2739,7 @@
             }
         }
 
-        return JSType.toInt32(invokeNoSuchProperty(key, programPoint));
+        return JSType.toInt32(invokeNoSuchProperty(key, false, programPoint));
     }
 
     @Override
@@ -2794,7 +2821,7 @@
             }
         }
 
-        return JSType.toLong(invokeNoSuchProperty(key, programPoint));
+        return JSType.toLong(invokeNoSuchProperty(key, false, programPoint));
     }
 
     @Override
@@ -2876,7 +2903,7 @@
             }
         }
 
-        return JSType.toNumber(invokeNoSuchProperty(key, INVALID_PROGRAM_POINT));
+        return JSType.toNumber(invokeNoSuchProperty(key, false, INVALID_PROGRAM_POINT));
     }
 
     @Override
@@ -2957,7 +2984,7 @@
             }
         }
 
-        return invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
+        return invokeNoSuchProperty(key, false, INVALID_PROGRAM_POINT);
     }
 
     @Override
@@ -3071,23 +3098,12 @@
         return false;
     }
 
-    private void doesNotHaveEnsureDelete(final long longIndex, final long oldLength, final boolean strict) {
-        if (longIndex > oldLength) {
-            ArrayData array = getArray();
-            if (array.canDelete(oldLength, longIndex - 1, strict)) {
-                array = array.delete(oldLength, longIndex - 1);
-            }
-            setArray(array);
-        }
-    }
-
     private void doesNotHave(final int index, final int value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
             final boolean strict = isStrictFlag(callSiteFlags);
-            setArray(getArray().set(index, value, strict));
-            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
         }
     }
 
@@ -3096,8 +3112,7 @@
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
             final boolean strict = isStrictFlag(callSiteFlags);
-            setArray(getArray().set(index, value, strict));
-            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
         }
     }
 
@@ -3106,8 +3121,7 @@
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
             final boolean strict = isStrictFlag(callSiteFlags);
-            setArray(getArray().set(index, value, strict));
-            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
         }
     }
 
@@ -3116,8 +3130,7 @@
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
             final boolean strict = isStrictFlag(callSiteFlags);
-            setArray(getArray().set(index, value, strict));
-            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
         }
     }
 
@@ -3786,15 +3799,20 @@
     }
 
     /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created */
-    private static int count;
-
+    private static LongAdder count;
+
+    static {
+        if (Context.DEBUG) {
+            count = new LongAdder();
+        }
+    }
     /**
      * Get number of {@code ScriptObject} instances created. If not running in debug
      * mode this is always 0
      *
      * @return number of ScriptObjects created
      */
-    public static int getCount() {
-        return count;
+    public static long getCount() {
+        return count.longValue();
     }
 }
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Thu Oct 29 17:22:12 2015 -0700
@@ -685,6 +685,33 @@
     }
 
     /**
+     * ECMA 11.4.1 - delete operator, implementation for slow scopes
+     *
+     * This implementation of 'delete' walks the scope chain to find the scope that contains the
+     * property to be deleted, then invokes delete on it.
+     *
+     * @param obj       top scope object
+     * @param property  property to delete
+     * @param strict    are we in strict mode
+     *
+     * @return true if property was successfully found and deleted
+     */
+    public static boolean SLOW_DELETE(final Object obj, final Object property, final Object strict) {
+        if (obj instanceof ScriptObject) {
+            ScriptObject sobj = (ScriptObject) obj;
+            final String key = property.toString();
+            while (sobj != null && sobj.isScope()) {
+                final FindProperty find = sobj.findProperty(key, false);
+                if (find != null) {
+                    return sobj.delete(key, Boolean.TRUE.equals(strict));
+                }
+                sobj = sobj.getProto();
+            }
+        }
+        return DELETE(obj, property, strict);
+    }
+
+    /**
      * ECMA 11.4.1 - delete operator, special case
      *
      * This is 'delete' that always fails. We have to check strict mode and throw error.
--- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Thu Oct 29 17:22:12 2015 -0700
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
@@ -70,6 +71,9 @@
     /** EXIT name - special property used by $EXEC API. */
     public static final String EXIT_NAME = "$EXIT";
 
+    /** THROW_ON_ERROR name - special property of the $EXEC function used by $EXEC API. */
+    public static final String THROW_ON_ERROR_NAME = "throwOnError";
+
     /** Names of special properties used by $ENV API. */
     public  static final String ENV_NAME  = "$ENV";
 
@@ -244,6 +248,19 @@
             }
         }
 
+        // if we got a non-zero exit code ("failure"), then we have to decide to throw error or not
+        if (exit != 0) {
+            // get the $EXEC function object from the global object
+            final Object exec = global.get(EXEC_NAME);
+            assert exec instanceof ScriptObject : EXEC_NAME + " is not a script object!";
+
+            // Check if the user has set $EXEC.throwOnError property to true. If so, throw RangeError
+            // If that property is not set or set to false, then silently proceed with the rest.
+            if (JSType.toBoolean(((ScriptObject)exec).get(THROW_ON_ERROR_NAME))) {
+                throw rangeError("exec.returned.non.zero", ScriptRuntime.safeToString(exit));
+            }
+        }
+
         // Return the result from stdout.
         return out;
     }
--- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -186,10 +186,7 @@
 
     private SetMethod createNewPropertySetter(final SwitchPoint builtinSwitchPoint) {
         final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter(builtinSwitchPoint) : createNewSpillPropertySetter(builtinSwitchPoint);
-        final PropertyListeners listeners = map.getListeners();
-        if (listeners != null) {
-            listeners.propertyAdded(sm.property);
-        }
+        map.propertyAdded(sm.property, true);
         return sm;
     }
 
@@ -204,7 +201,7 @@
         //fast type specific setter
         final MethodHandle fastSetter = property.getSetter(type, newMap); //0 sobj, 1 value, slot folded for spill property already
 
-        //slow setter, that calls ScriptObject.set with appropraite type and key name
+        //slow setter, that calls ScriptObject.set with appropriate type and key name
         MethodHandle slowSetter = ScriptObject.SET_SLOW[getAccessorTypeIndex(type)];
         slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.getFlags(desc));
         slowSetter = MH.insertArguments(slowSetter, 1, name);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/runtime/SharedPropertyMap.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, 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 java.lang.invoke.SwitchPoint;
+
+/**
+ * This class represents a property map that can be shared among multiple prototype objects, allowing all inheriting
+ * top-level objects to also share one property map. This is class is only used for prototype objects, the
+ * top-level objects use ordinary {@link PropertyMap}s with the {@link PropertyMap#sharedProtoMap} field
+ * set to the expected shared prototype map.
+ *
+ * <p>When an instance of this class is evolved because a property is added, removed, or modified in an object
+ * using it, the {@link #invalidateSwitchPoint()} method is invoked to signal to all callsites and inheriting
+ * objects that the assumption of a single shared prototype map is no longer valid. The property map resulting
+ * from the modification will no longer be an instance of this class.</p>
+ */
+public final class SharedPropertyMap extends PropertyMap {
+
+    private SwitchPoint switchPoint;
+
+    private static final long serialVersionUID = 2166297719721778876L;
+
+    /**
+     * Create a new shared property map from the given {@code map}.
+     * @param map property map to copy
+     */
+    public SharedPropertyMap(final PropertyMap map) {
+        super(map);
+        this.switchPoint = new SwitchPoint();
+    }
+
+    @Override
+    public void propertyAdded(final Property property, final boolean isSelf) {
+        if (isSelf) {
+            invalidateSwitchPoint();
+        }
+        super.propertyAdded(property, isSelf);
+    }
+
+    @Override
+    public void propertyDeleted(final Property property, final boolean isSelf) {
+        if (isSelf) {
+            invalidateSwitchPoint();
+        }
+        super.propertyDeleted(property, isSelf);
+    }
+
+    @Override
+    public void propertyModified(final Property oldProperty, final Property newProperty, final boolean isSelf) {
+        if (isSelf) {
+            invalidateSwitchPoint();
+        }
+        super.propertyModified(oldProperty, newProperty, isSelf);
+    }
+
+    @Override
+    synchronized boolean isValidSharedProtoMap() {
+        return switchPoint != null;
+    }
+
+    @Override
+    synchronized SwitchPoint getSharedProtoSwitchPoint() {
+        return switchPoint;
+    }
+
+    /**
+     * Invalidate the shared prototype switch point if this is a shared prototype map.
+     */
+    synchronized void invalidateSwitchPoint() {
+        if (switchPoint != null) {
+            assert !switchPoint.hasBeenInvalidated();
+            SwitchPoint.invalidateAll(new SwitchPoint[]{ switchPoint });
+            switchPoint = null;
+        }
+    }
+}
--- a/src/jdk/nashorn/internal/runtime/Source.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/Source.java	Thu Oct 29 17:22:12 2015 -0700
@@ -971,7 +971,7 @@
         return initLogger(Context.getContextTrusted());
     }
 
-    private File dumpFile(final String dir) {
+    private File dumpFile(final File dirFile) {
         final URL u = getURL();
         final StringBuilder buf = new StringBuilder();
         // make it unique by prefixing current date & time
@@ -986,11 +986,17 @@
             buf.append(getName());
         }
 
-        return new File(dir, buf.toString());
+        return new File(dirFile, buf.toString());
     }
 
     void dump(final String dir) {
-        final File file = dumpFile(dir);
+        final File dirFile = new File(dir);
+        final File file = dumpFile(dirFile);
+        if (!dirFile.exists() && !dirFile.mkdirs()) {
+            debug("Skipping source dump for " + name);
+            return;
+        }
+
         try (final FileOutputStream fos = new FileOutputStream(file)) {
             final PrintWriter pw = new PrintWriter(fos);
             pw.print(data.toString());
--- a/src/jdk/nashorn/internal/runtime/StoredScript.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/StoredScript.java	Thu Oct 29 17:22:12 2015 -0700
@@ -77,7 +77,7 @@
         return compilationId;
     }
 
-    private Map<String, Class<?>> installClasses(final Source source, final CodeInstaller<ScriptEnvironment> installer) {
+    private Map<String, Class<?>> installClasses(final Source source, final CodeInstaller installer) {
         final Map<String, Class<?>> installedClasses = new HashMap<>();
         final byte[]   mainClassBytes = classBytes.get(mainClassName);
         final Class<?> mainClass      = installer.install(mainClassName, mainClassBytes);
@@ -96,7 +96,7 @@
         return installedClasses;
     }
 
-    FunctionInitializer installFunction(final RecompilableScriptFunctionData data, final CodeInstaller<ScriptEnvironment> installer) {
+    FunctionInitializer installFunction(final RecompilableScriptFunctionData data, final CodeInstaller installer) {
         final Map<String, Class<?>> installedClasses = installClasses(data.getSource(), installer);
 
         assert initializers != null;
@@ -124,7 +124,7 @@
      * @param installer the installer
      * @return main script class
      */
-    Class<?> installScript(final Source source, final CodeInstaller<ScriptEnvironment> installer) {
+    Class<?> installScript(final Source source, final CodeInstaller installer) {
 
         final Map<String, Class<?>> installedClasses = installClasses(source, installer);
 
--- a/src/jdk/nashorn/internal/runtime/Timing.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/Timing.java	Thu Oct 29 17:22:12 2015 -0700
@@ -28,12 +28,14 @@
 import java.io.IOException;
 import java.io.StringReader;
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.LongAdder;
+import java.util.function.Function;
 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;
@@ -156,11 +158,15 @@
     }
 
     final class TimeSupplier implements Supplier<String> {
-        private final Map<String, Long> timings;
-
-        TimeSupplier() {
-            timings   = new LinkedHashMap<>();
-        }
+        private final Map<String, LongAdder> timings = new ConcurrentHashMap<>();
+        private final LinkedBlockingQueue<String> orderedTimingNames = new LinkedBlockingQueue<>();
+        private final Function<String, LongAdder> newTimingCreator = new Function<String, LongAdder>() {
+            @Override
+            public LongAdder apply(final String s) {
+                orderedTimingNames.add(s);
+                return new LongAdder();
+            }
+        };
 
         String[] getStrings() {
             final List<String> strs = new ArrayList<>();
@@ -184,26 +190,26 @@
             int  maxKeyLength = 0;
             int  maxValueLength = 0;
 
-            for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+            for (final Map.Entry<String, LongAdder> entry : timings.entrySet()) {
                 maxKeyLength   = Math.max(maxKeyLength, entry.getKey().length());
-                maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue()).length());
+                maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue().longValue()).length());
             }
             maxKeyLength++;
 
             final StringBuilder sb = new StringBuilder();
             sb.append("Accumulated compilation phase timings:\n\n");
-            for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+            for (final String timingName: orderedTimingNames) {
                 int len;
 
                 len = sb.length();
-                sb.append(entry.getKey());
+                sb.append(timingName);
                 len = sb.length() - len;
 
                 while (len++ < maxKeyLength) {
                     sb.append(' ');
                 }
 
-                final Long duration = entry.getValue();
+                final long duration = timings.get(timingName).longValue();
                 final String strDuration = toMillisPrint(duration);
                 len = strDuration.length();
                 for (int i = 0; i < maxValueLength - len; i++) {
@@ -233,11 +239,7 @@
         }
 
         private void accumulateTime(final String module, final long duration) {
-            Long accumulatedTime = timings.get(module);
-            if (accumulatedTime == null) {
-                accumulatedTime = 0L;
-            }
-            timings.put(module, accumulatedTime + duration);
+            timings.computeIfAbsent(module, newTimingCreator).add(duration);
         }
     }
 }
--- a/src/jdk/nashorn/internal/runtime/Undefined.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/Undefined.java	Thu Oct 29 17:22:12 2015 -0700
@@ -96,8 +96,12 @@
 
         switch (operator) {
         case "new":
-        case "call":
-            throw lookupTypeError("cant.call.undefined", desc);
+        case "call": {
+            final String name = NashornCallSiteDescriptor.getFunctionDescription(desc);
+            final String msg = name != null? "not.a.function" : "cant.call.undefined";
+            throw typeError(msg, name);
+        }
+
         case "callMethod":
             throw lookupTypeError("cant.read.property.of.undefined", desc);
         // NOTE: we support getElem and setItem as JavaScript doesn't distinguish items from properties. Nashorn itself
@@ -125,7 +129,8 @@
     }
 
     private static ECMAException lookupTypeError(final String msg, final CallSiteDescriptor desc) {
-        return typeError(msg, desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null);
+        final String name = desc.getNameToken(2);
+        return typeError(msg, name != null && !name.isEmpty()? name : null);
     }
 
     private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class);
--- a/src/jdk/nashorn/internal/runtime/WithObject.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/WithObject.java	Thu Oct 29 17:22:12 2015 -0700
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -45,7 +46,7 @@
  *
  */
 public final class WithObject extends Scope {
-    private static final MethodHandle WITHEXPRESSIONGUARD    = findOwnMH("withExpressionGuard",  boolean.class, Object.class, PropertyMap.class, SwitchPoint.class);
+    private static final MethodHandle WITHEXPRESSIONGUARD    = findOwnMH("withExpressionGuard",  boolean.class, Object.class, PropertyMap.class, SwitchPoint[].class);
     private static final MethodHandle WITHEXPRESSIONFILTER   = findOwnMH("withFilterExpression", Object.class, Object.class);
     private static final MethodHandle WITHSCOPEFILTER        = findOwnMH("withFilterScope",      Object.class, Object.class);
     private static final MethodHandle BIND_TO_EXPRESSION_OBJ = findOwnMH("bindToExpression",     Object.class, Object.class, Object.class);
@@ -209,16 +210,18 @@
     }
 
     @Override
-    protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+    protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) {
         FindProperty find = expression.findProperty(NO_SUCH_PROPERTY_NAME, true);
         if (find != null) {
             final Object func = find.getObjectValue();
             if (func instanceof ScriptFunction) {
-                return ScriptRuntime.apply((ScriptFunction)func, expression, name);
+                final ScriptFunction sfunc = (ScriptFunction)func;
+                final Object self = isScope && sfunc.isStrict()? UNDEFINED : expression;
+                return ScriptRuntime.apply(sfunc, self, name);
             }
         }
 
-        return getProto().invokeNoSuchProperty(name, programPoint);
+        return getProto().invokeNoSuchProperty(name, isScope, programPoint);
     }
 
     @Override
@@ -352,18 +355,29 @@
     }
 
     private static Object bindToExpression(final ScriptFunction fn, final Object receiver) {
-        return fn.makeBoundFunction(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY);
+        return fn.createBound(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY);
     }
 
     private MethodHandle expressionGuard(final String name, final ScriptObject owner) {
         final PropertyMap map = expression.getMap();
-        final SwitchPoint sp = expression.getProtoSwitchPoint(name, owner);
+        final SwitchPoint[] sp = expression.getProtoSwitchPoints(name, owner);
         return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp);
     }
 
     @SuppressWarnings("unused")
-    private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint sp) {
-        return ((WithObject)receiver).expression.getMap() == map && (sp == null || !sp.hasBeenInvalidated());
+    private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint[] sp) {
+        return ((WithObject)receiver).expression.getMap() == map && !hasBeenInvalidated(sp);
+    }
+
+    private static boolean hasBeenInvalidated(final SwitchPoint[] switchPoints) {
+        if (switchPoints != null) {
+            for (final SwitchPoint switchPoint : switchPoints) {
+                if (switchPoint.hasBeenInvalidated()) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     /**
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Thu Oct 29 17:22:12 2015 -0700
@@ -258,7 +258,7 @@
      * Factory method for unspecified array - start as int
      * @return ArrayData
      */
-    public final static ArrayData initialArray() {
+    public static ArrayData initialArray() {
         return new IntArrayData();
     }
 
@@ -278,7 +278,7 @@
      * @param size size required
      * @return size given, always &gt;= size
      */
-    protected final static int alignUp(final int size) {
+    protected static int alignUp(final int size) {
         return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1);
     }
 
@@ -288,7 +288,7 @@
      * @param length the initial length
      * @return ArrayData
      */
-    public static final ArrayData allocate(final int length) {
+    public static ArrayData allocate(final int length) {
         if (length == 0) {
             return new IntArrayData();
         } else if (length >= SparseArrayData.MAX_DENSE_LENGTH) {
@@ -304,7 +304,7 @@
      * @param  array the array
      * @return ArrayData wrapping this array
      */
-    public static final ArrayData allocate(final Object array) {
+    public static ArrayData allocate(final Object array) {
         final Class<?> clazz = array.getClass();
 
         if (clazz == int[].class) {
@@ -324,7 +324,7 @@
      * @param array the array to use for initial elements
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final int[] array) {
+    public static ArrayData allocate(final int[] array) {
          return new IntArrayData(array, array.length);
     }
 
@@ -334,7 +334,7 @@
      * @param array the array to use for initial elements
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final long[] array) {
+    public static ArrayData allocate(final long[] array) {
         return new LongArrayData(array, array.length);
     }
 
@@ -344,7 +344,7 @@
      * @param array the array to use for initial elements
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final double[] array) {
+    public static ArrayData allocate(final double[] array) {
         return new NumberArrayData(array, array.length);
     }
 
@@ -354,7 +354,7 @@
      * @param array the array to use for initial elements
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final Object[] array) {
+    public static ArrayData allocate(final Object[] array) {
         return new ObjectArrayData(array, array.length);
     }
 
@@ -364,7 +364,7 @@
      * @param buf the nio ByteBuffer to wrap
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final ByteBuffer buf) {
+    public static ArrayData allocate(final ByteBuffer buf) {
         return new ByteBufferArrayData(buf);
     }
 
@@ -374,7 +374,7 @@
      * @param underlying  the underlying ArrayData to wrap in the freeze filter
      * @return the frozen ArrayData
      */
-    public static final ArrayData freeze(final ArrayData underlying) {
+    public static ArrayData freeze(final ArrayData underlying) {
         return new FrozenArrayFilter(underlying);
     }
 
@@ -384,7 +384,7 @@
      * @param underlying  the underlying ArrayData to wrap in the seal filter
      * @return the sealed ArrayData
      */
-    public static final ArrayData seal(final ArrayData underlying) {
+    public static ArrayData seal(final ArrayData underlying) {
         return new SealedArrayFilter(underlying);
     }
 
@@ -394,7 +394,7 @@
      * @param  underlying the underlying ArrayData to wrap in the non extensible filter
      * @return new array data, filtered
      */
-    public static final ArrayData preventExtension(final ArrayData underlying) {
+    public static ArrayData preventExtension(final ArrayData underlying) {
         return new NonExtensibleArrayFilter(underlying);
     }
 
@@ -404,7 +404,7 @@
      * @param underlying the underlying ArrayDAta to wrap in the non extensible filter
      * @return new array data, filtered
      */
-    public static final ArrayData setIsLengthNotWritable(final ArrayData underlying) {
+    public static ArrayData setIsLengthNotWritable(final ArrayData underlying) {
         return new LengthNotWritableFilter(underlying);
     }
 
@@ -676,19 +676,34 @@
     }
 
     /**
-     * Returns if element at specific index range can be deleted or not.
+     * Returns if element at specific index can be deleted or not.
      *
-     * @param fromIndex  the start index
-     * @param toIndex    the end index
+     * @param longIndex  the index
      * @param strict     are we in strict mode
      *
      * @return true if range can be deleted
      */
-    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+    public boolean canDelete(final long longIndex, final boolean strict) {
         return true;
     }
 
     /**
+     * Delete a range from the array if {@code fromIndex} is less than or equal to {@code toIndex}
+     * and the array supports deletion.
+     *
+     * @param fromIndex  the start index (inclusive)
+     * @param toIndex    the end index (inclusive)
+     * @param strict     are we in strict mode
+     * @return an array with the range deleted, or this array if no deletion took place
+     */
+    public final ArrayData safeDelete(final long fromIndex, final long toIndex, final boolean strict) {
+        if (fromIndex <= toIndex && canDelete(fromIndex, strict)) {
+            return delete(fromIndex, toIndex);
+        }
+        return this;
+    }
+
+    /**
      * Returns property descriptor for element at a given index
      *
      * @param global the global object
--- a/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java	Thu Oct 29 17:22:12 2015 -0700
@@ -164,7 +164,7 @@
     }
 
     @Override
-    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+    public boolean canDelete(final long longIndex, final boolean strict) {
         return false;
     }
 
--- a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Thu Oct 29 17:22:12 2015 -0700
@@ -191,7 +191,7 @@
 
     /**
      * Return element setter for a {@link ContinuousArrayData}
-     * @param clazz        clazz for exact type guard
+     * @param clazz        class for exact type guard
      * @param setHas       set has guard
      * @param elementType  element type
      * @return method handle for element setter
--- a/src/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java	Fri Oct 16 12:19:59 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime.arrays;
-
-/**
- * Mechanism for communicating that something isn't a plain
- * numeric integer array index. This enables things like
- * array getters for the fast case in a try, basically
- * just consisting of an "array[index]" access without
- * any checks of boundary conditions that rarely happen
- */
-@SuppressWarnings("serial")
-class InvalidArrayIndexException extends Exception {
-
-    private final Object index;
-
-    InvalidArrayIndexException(final Object index) {
-        super(index == null ? "null" : index.toString());
-        this.index = index;
-    }
-
-    InvalidArrayIndexException(final int index) {
-        this(Integer.valueOf(index));
-    }
-
-    InvalidArrayIndexException(final long index) {
-        this(Long.valueOf(index));
-    }
-
-    InvalidArrayIndexException(final double index) {
-        this(Double.valueOf(index));
-    }
-
-    @Override
-    public String toString() {
-        return index.toString();
-    }
-
-    Object getIndex() {
-        return index;
-    }
-
-}
--- a/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java	Thu Oct 29 17:22:12 2015 -0700
@@ -50,15 +50,15 @@
 
     @Override
     public boolean canDelete(final int index, final boolean strict) {
-        if (strict) {
-            throw typeError("cant.delete.property", Integer.toString(index), "sealed array");
-        }
-        return false;
+        return canDelete(ArrayIndex.toLongIndex(index), strict);
     }
 
     @Override
-    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
-        return canDelete((int) fromIndex, strict);
+    public boolean canDelete(final long longIndex, final boolean strict) {
+        if (strict) {
+            throw typeError("cant.delete.property", Long.toString(longIndex), "sealed array");
+        }
+        return false;
     }
 
     @Override
--- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Thu Oct 29 17:22:12 2015 -0700
@@ -36,7 +36,7 @@
  * Handle arrays where the index is very large.
  */
 class SparseArrayData extends ArrayData {
-    static final int MAX_DENSE_LENGTH = 8 * 1024 * 1024;
+    static final int MAX_DENSE_LENGTH = 1024 * 1024;
 
     /** Underlying array. */
     private ArrayData underlying;
@@ -166,8 +166,9 @@
     @Override
     public ArrayData set(final int index, final Object value, final boolean strict) {
         if (index >= 0 && index < maxDenseLength) {
+            final long oldLength = underlying.length();
             ensure(index);
-            underlying = underlying.set(index, value, strict);
+            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
             final Long longIndex = indexToKey(index);
@@ -181,8 +182,9 @@
     @Override
     public ArrayData set(final int index, final int value, final boolean strict) {
         if (index >= 0 && index < maxDenseLength) {
+            final long oldLength = underlying.length();
             ensure(index);
-            underlying = underlying.set(index, value, strict);
+            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
             final Long longIndex = indexToKey(index);
@@ -195,8 +197,9 @@
     @Override
     public ArrayData set(final int index, final long value, final boolean strict) {
         if (index >= 0 && index < maxDenseLength) {
+            final long oldLength = underlying.length();
             ensure(index);
-            underlying = underlying.set(index, value, strict);
+            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
             final Long longIndex = indexToKey(index);
@@ -209,8 +212,9 @@
     @Override
     public ArrayData set(final int index, final double value, final boolean strict) {
         if (index >= 0 && index < maxDenseLength) {
+            final long oldLength = underlying.length();
             ensure(index);
-            underlying = underlying.set(index, value, strict);
+            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
             final Long longIndex = indexToKey(index);
--- a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Thu Oct 29 17:22:12 2015 -0700
@@ -83,7 +83,7 @@
     }
 
     @Override
-    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+    public boolean canDelete(final long longIndex, final boolean strict) {
         return false;
     }
 
--- a/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java	Thu Oct 29 17:22:12 2015 -0700
@@ -34,7 +34,7 @@
  * This filter handles the presence of undefined array elements.
  */
 final class UndefinedArrayFilter extends ArrayFilter {
-    /** Bit vector tracking undefines. */
+    /** Bit vector tracking undefined slots. */
     private final BitVector undefined;
 
     UndefinedArrayFilter(final ArrayData underlying) {
--- a/src/jdk/nashorn/internal/runtime/linker/AdaptationException.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/AdaptationException.java	Thu Oct 29 17:22:12 2015 -0700
@@ -30,6 +30,7 @@
     private final AdaptationResult adaptationResult;
 
     AdaptationException(final AdaptationResult.Outcome outcome, final String classList) {
+        super(null, null, false, false);
         this.adaptationResult = new AdaptationResult(outcome, classList);
     }
 
--- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Thu Oct 29 17:22:12 2015 -0700
@@ -50,7 +50,6 @@
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
-import jdk.nashorn.internal.objects.ScriptFunctionImpl;
 import jdk.nashorn.internal.runtime.ECMAException;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
@@ -70,7 +69,7 @@
     private static final MethodHandle VOID_TO_OBJECT = MH.constant(Object.class, ScriptRuntime.UNDEFINED);
 
     /**
-     * The default dynalink relink threshold for megamorphisism is 8. In the case
+     * The default dynalink relink threshold for megamorphism is 8. In the case
      * of object fields only, it is fine. However, with dual fields, in order to get
      * performance on benchmarks with a lot of object instantiation and then field
      * reassignment, it can take slightly more relinks to become stable with type
@@ -190,7 +189,7 @@
      * @return true if the obj is an instance of @FunctionalInterface interface
      */
     public static boolean isFunctionalInterfaceObject(final Object obj) {
-        return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethod(obj.getClass()) != null);
+        return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethodName(obj.getClass()) != null);
     }
 
     /**
@@ -214,7 +213,7 @@
      * @param type           method type
      * @param programPoint   program point to bind to callsite
      *
-     * @return callsite for a math instrinic node
+     * @return callsite for a math intrinsic node
      */
     public static CallSite mathBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int programPoint) {
         final MethodHandle mh;
@@ -397,8 +396,8 @@
      * @throws ECMAException with {@code TypeError} if the object is not a callable.
      */
     public static Object bindCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
-        if (callable instanceof ScriptFunctionImpl) {
-            return ((ScriptFunctionImpl)callable).makeBoundFunction(boundThis, boundArgs);
+        if (callable instanceof ScriptFunction) {
+            return ((ScriptFunction)callable).createBound(boundThis, boundArgs);
         } else if (callable instanceof BoundCallable) {
             return ((BoundCallable)callable).bind(boundArgs);
         } else if (isCallable(callable)) {
--- a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Thu Oct 29 17:22:12 2015 -0700
@@ -99,9 +99,10 @@
             return null;
         }
 
-        final GuardedInvocation inv;
+        GuardedInvocation inv;
         if (jsObjectClass.isInstance(self)) {
             inv = lookup(desc, request, linkerServices);
+            inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard());
         } else {
             throw new AssertionError(); // Should never reach here.
         }
--- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Thu Oct 29 17:22:12 2015 -0700
@@ -77,9 +77,10 @@
             return null;
         }
 
-        final GuardedInvocation inv;
+        GuardedInvocation inv;
         if (self instanceof JSObject) {
             inv = lookup(desc, request, linkerServices);
+            inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard());
         } else if (self instanceof Map || self instanceof Bindings) {
             // guard to make sure the Map or Bindings does not turn into JSObject later!
             final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices);
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Thu Oct 29 17:22:12 2015 -0700
@@ -203,6 +203,8 @@
 
     // This is the superclass for our generated adapter.
     private final Class<?> superClass;
+    // Interfaces implemented by our generated adapter.
+    private final List<Class<?>> interfaces;
     // Class loader used as the parent for the class loader we'll create to load the generated class. It will be a class
     // loader that has the visibility of all original types (class to extend and interfaces to implement) and of the
     // Nashorn classes.
@@ -254,6 +256,7 @@
         assert interfaces != null;
 
         this.superClass = superClass;
+        this.interfaces = interfaces;
         this.classOverride = classOverride;
         this.commonLoader = commonLoader;
         cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
@@ -571,7 +574,7 @@
             mv.visitVarInsn(ALOAD, 0);
             if (fromFunction && !mi.getName().equals(samName)) {
                 // Constructors initializing from a ScriptFunction only initialize methods with the SAM name.
-                // NOTE: if there's a concrete overloaded method sharing the SAM name, it'll be overriden too. This
+                // NOTE: if there's a concrete overloaded method sharing the SAM name, it'll be overridden too. This
                 // is a deliberate design choice. All other method handles are initialized to null.
                 mv.visitInsn(ACONST_NULL);
             } else {
@@ -1031,6 +1034,24 @@
         endMethod(mv);
     }
 
+    // find the appropriate super type to use for invokespecial on the given interface
+    private Class<?> findInvokespecialOwnerFor(final Class<?> cl) {
+        assert Modifier.isInterface(cl.getModifiers()) : cl + " is not an interface";
+
+        if (cl.isAssignableFrom(superClass)) {
+            return superClass;
+        }
+
+        for (final Class<?> iface : interfaces) {
+             if (cl.isAssignableFrom(iface)) {
+                 return iface;
+             }
+        }
+
+        // we better that interface that extends the given interface!
+        throw new AssertionError("can't find the class/interface that extends " + cl);
+    }
+
     private void emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name, final String methodDesc) {
         mv.visitVarInsn(ALOAD, 0);
         int nextParam = 1;
@@ -1042,7 +1063,9 @@
 
         // default method - non-abstract, interface method
         if (Modifier.isInterface(owner.getModifiers())) {
-            mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false);
+            // we should call default method on the immediate "super" type - not on (possibly)
+            // the indirectly inherited interface class!
+            mv.invokespecial(Type.getInternalName(findInvokespecialOwnerFor(owner)), name, methodDesc, false);
         } else {
             mv.invokespecial(superClassName, name, methodDesc, false);
         }
--- a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java	Thu Oct 29 17:22:12 2015 -0700
@@ -43,6 +43,7 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.LongAdder;
 import jdk.internal.dynalink.ChainedCallSite;
 import jdk.internal.dynalink.DynamicLinker;
 import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -70,7 +71,7 @@
     LinkerCallSite(final NashornCallSiteDescriptor descriptor) {
         super(descriptor);
         if (Context.DEBUG) {
-            LinkerCallSite.count++;
+            LinkerCallSite.count.increment();
         }
     }
 
@@ -173,7 +174,7 @@
      * @return self reference
      */
     public static Object increaseMissCount(final String desc, final Object self) {
-        ++missCount;
+        missCount.increment();
         if (r.nextInt(100) < missSamplingPercentage) {
             final AtomicInteger i = missCounts.get(desc);
             if (i == null) {
@@ -500,7 +501,7 @@
          * @param desc callsite descriptor string
          * @param args arguments to function
          *
-         * @throws Throwable if invocation failes or throws exception/error
+         * @throws Throwable if invocation fails or throws exception/error
          */
         @SuppressWarnings("unused")
         public void traceMiss(final String desc, final Object... args) throws Throwable {
@@ -509,12 +510,19 @@
     }
 
     // counters updated in debug mode
-    private static int count;
+    private static LongAdder count;
     private static final HashMap<String, AtomicInteger> missCounts = new HashMap<>();
-    private static int missCount;
+    private static LongAdder missCount;
     private static final Random r = new Random();
     private static final int missSamplingPercentage = Options.getIntProperty("nashorn.tcs.miss.samplePercent", 1);
 
+    static {
+        if (Context.DEBUG) {
+            count = new LongAdder();
+            missCount = new LongAdder();
+        }
+    }
+
     @Override
     protected int getMaxChainLength() {
         return 8;
@@ -524,16 +532,16 @@
      * Get the callsite count
      * @return the count
      */
-    public static int getCount() {
-        return count;
+    public static long getCount() {
+        return count.longValue();
     }
 
     /**
      * Get the callsite miss count
      * @return the missCount
      */
-    public static int getMissCount() {
-        return missCount;
+    public static long getMissCount() {
+        return missCount.longValue();
     }
 
     /**
--- a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Thu Oct 29 17:22:12 2015 -0700
@@ -26,7 +26,6 @@
 package jdk.nashorn.internal.runtime.linker;
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -42,13 +41,11 @@
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.internal.dynalink.linker.MethodHandleTransformer;
 import jdk.internal.dynalink.support.DefaultInternalObjectFilter;
-import jdk.internal.dynalink.support.Guards;
 import jdk.internal.dynalink.support.Lookup;
 import jdk.nashorn.api.scripting.ScriptUtils;
 import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
@@ -79,10 +76,10 @@
     }
 
     // cache of @FunctionalInterface method of implementor classes
-    private static final ClassValue<Method> FUNCTIONAL_IFACE_METHOD = new ClassValue<Method>() {
+    private static final ClassValue<String> FUNCTIONAL_IFACE_METHOD_NAME = new ClassValue<String>() {
         @Override
-        protected Method computeValue(final Class<?> type) {
-            return findFunctionalInterfaceMethod(type);
+        protected String computeValue(final Class<?> type) {
+            return findFunctionalInterfaceMethodName(type);
         }
     };
 
@@ -107,19 +104,21 @@
             // annotated interface. This way Java method, constructor references or
             // implementations of java.util.function.* interfaces can be called as though
             // those are script functions.
-            final Method m = getFunctionalInterfaceMethod(self.getClass());
-            if (m != null) {
+            final String name = getFunctionalInterfaceMethodName(self.getClass());
+            if (name != null) {
                 final MethodType callType = desc.getMethodType();
-                // 'callee' and 'thiz' passed from script + actual arguments
-                if (callType.parameterCount() != m.getParameterCount() + 2) {
-                    throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
-                }
-                return new GuardedInvocation(
-                        // drop 'thiz' passed from the script.
-                        MH.dropArguments(linkerServices.filterInternalObjects(desc.getLookup().unreflect(m)), 1,
-                                callType.parameterType(1)), Guards.getInstanceOfGuard(
-                                        m.getDeclaringClass())).asTypeSafeReturn(
-                                                new NashornBeansLinkerServices(linkerServices), callType);
+                // drop callee (Undefined ScriptFunction) and change the request to be dyn:callMethod:<name>
+                final NashornCallSiteDescriptor newDesc = NashornCallSiteDescriptor.get(desc.getLookup(),
+                        "dyn:callMethod:" + name, desc.getMethodType().dropParameterTypes(1, 2),
+                        NashornCallSiteDescriptor.getFlags(desc));
+                final GuardedInvocation gi = getGuardedInvocation(beansLinker,
+                        linkRequest.replaceArguments(newDesc, linkRequest.getArguments()),
+                        new NashornBeansLinkerServices(linkerServices));
+
+                // drop 'thiz' passed from the script.
+                return gi.replaceMethods(
+                    MH.dropArguments(linkerServices.filterInternalObjects(gi.getInvocation()), 1, callType.parameterType(1)),
+                    gi.getGuard());
             }
         }
         return getGuardedInvocation(beansLinker, linkRequest, linkerServices);
@@ -163,13 +162,13 @@
         return arg instanceof ConsString ? arg.toString() : arg;
     }
 
-    private static Method findFunctionalInterfaceMethod(final Class<?> clazz) {
+    private static String findFunctionalInterfaceMethodName(final Class<?> clazz) {
         if (clazz == null) {
             return null;
         }
 
         for (final Class<?> iface : clazz.getInterfaces()) {
-            // check accessiblity up-front
+            // check accessibility up-front
             if (! Context.isAccessibleClass(iface)) {
                 continue;
             }
@@ -179,20 +178,20 @@
                 // return the first abstract method
                 for (final Method m : iface.getMethods()) {
                     if (Modifier.isAbstract(m.getModifiers())) {
-                        return m;
+                        return m.getName();
                     }
                 }
             }
         }
 
         // did not find here, try super class
-        return findFunctionalInterfaceMethod(clazz.getSuperclass());
+        return findFunctionalInterfaceMethodName(clazz.getSuperclass());
     }
 
     // Returns @FunctionalInterface annotated interface's single abstract
-    // method. If not found, returns null.
-    static Method getFunctionalInterfaceMethod(final Class<?> clazz) {
-        return FUNCTIONAL_IFACE_METHOD.get(clazz);
+    // method name. If not found, returns null.
+    static String getFunctionalInterfaceMethodName(final Class<?> clazz) {
+        return FUNCTIONAL_IFACE_METHOD_NAME.get(clazz);
     }
 
     static MethodHandleTransformer createHiddenObjectFilter() {
--- a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Thu Oct 29 17:22:12 2015 -0700
@@ -27,6 +27,8 @@
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.JSType.GET_UNDEFINED;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_OBJECT_INDEX;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
@@ -92,7 +94,7 @@
             if(BeansLinker.isDynamicMethod(self)) {
                 throw typeError("method.not.constructor", ScriptRuntime.safeToString(self));
             }
-            throw typeError("not.a.function", ScriptRuntime.safeToString(self));
+            throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
         case "call":
             if(BeansLinker.isDynamicConstructor(self)) {
                 throw typeError("constructor.requires.new", ScriptRuntime.safeToString(self));
@@ -100,10 +102,12 @@
             if(BeansLinker.isDynamicMethod(self)) {
                 throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
             }
-            throw typeError("not.a.function", ScriptRuntime.safeToString(self));
+            throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
         case "callMethod":
+            throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self));
         case "getMethod":
-            throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self));
+            // evaluate to undefined, later on Undefined will take care of throwing TypeError
+            return getInvocation(MH.dropArguments(GET_UNDEFINED.get(TYPE_OBJECT_INDEX), 0, Object.class), self, linkerServices, desc);
         case "getProp":
         case "getElem":
             if(NashornCallSiteDescriptor.isOptimistic(desc)) {
--- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Thu Oct 29 17:22:12 2015 -0700
@@ -34,6 +34,7 @@
 import jdk.internal.dynalink.support.AbstractCallSiteDescriptor;
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
 import jdk.nashorn.internal.ir.debug.NashornTextifier;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
 
 /**
  * Nashorn-specific implementation of Dynalink's {@link CallSiteDescriptor}. The reason we have our own subclass is that
@@ -150,7 +151,7 @@
     public static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final String name,
             final MethodType methodType, final int flags) {
         final String[] tokenizedName = CallSiteDescriptorFactory.tokenizeName(name);
-        assert tokenizedName.length == 2 || tokenizedName.length == 3;
+        assert tokenizedName.length >= 2;
         assert "dyn".equals(tokenizedName[0]);
         assert tokenizedName[1] != null;
         // TODO: see if we can move mangling/unmangling into Dynalink
@@ -248,6 +249,54 @@
     }
 
     /**
+     * If this is a dyn:call or dyn:new, this returns function description from callsite.
+     * Caller has to make sure this is a dyn:call or dyn:new call site.
+     *
+     * @return function description if available (or null)
+     */
+    public String getFunctionDescription() {
+        assert getFirstOperator().equals("call") || getFirstOperator().equals("new");
+        return getNameTokenCount() > 2? getNameToken(2) : null;
+    }
+
+    /**
+     * If this is a dyn:call or dyn:new, this returns function description from callsite.
+     * Caller has to make sure this is a dyn:call or dyn:new call site.
+     *
+     * @param desc call site descriptor
+     * @return function description if available (or null)
+     */
+    public static String getFunctionDescription(final CallSiteDescriptor desc) {
+        return desc instanceof NashornCallSiteDescriptor ?
+                ((NashornCallSiteDescriptor)desc).getFunctionDescription() : null;
+    }
+
+
+    /**
+     * Returns the error message to be used when dyn:call or dyn:new is used on a non-function.
+     *
+     * @param obj object on which dyn:call or dyn:new is used
+     * @return error message
+     */
+    public String getFunctionErrorMessage(final Object obj) {
+        final String funcDesc = getFunctionDescription();
+        return funcDesc != null? funcDesc : ScriptRuntime.safeToString(obj);
+    }
+
+    /**
+     * Returns the error message to be used when dyn:call or dyn:new is used on a non-function.
+     *
+     * @param desc call site descriptor
+     * @param obj object on which dyn:call or dyn:new is used
+     * @return error message
+     */
+    public static String getFunctionErrorMessage(final CallSiteDescriptor desc, final Object obj) {
+        return desc instanceof NashornCallSiteDescriptor ?
+                ((NashornCallSiteDescriptor)desc).getFunctionErrorMessage(obj) :
+                ScriptRuntime.safeToString(obj);
+    }
+
+    /**
      * Returns the Nashorn-specific flags for this call site descriptor.
      * @param desc the descriptor. It can be any kind of a call site descriptor, not necessarily a
      * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
@@ -274,7 +323,7 @@
      * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
      * generated outside of Nashorn.
      * @param flag the tested flag
-     * @return true if the flag is set, false otherwise (it will be false if the decriptor is not a Nashorn call site
+     * @return true if the flag is set, false otherwise (it will be false if the descriptor is not a Nashorn call site
      * descriptor).
      */
     private static boolean isFlag(final CallSiteDescriptor desc, final int flag) {
--- a/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java	Thu Oct 29 17:22:12 2015 -0700
@@ -99,10 +99,10 @@
                         final StringBuilder sb = new StringBuilder();
 
                         sb.append('[')
-                           .append(record.getLoggerName())
-                           .append("] ")
-                           .append(record.getMessage())
-                           .append('\n');
+                        .append(record.getLoggerName())
+                        .append("] ")
+                        .append(record.getMessage())
+                        .append('\n');
 
                         return sb.toString();
                     }
@@ -194,7 +194,7 @@
      */
     public void indent(final int pos) {
         if (isEnabled) {
-           indent += pos * INDENT_SPACE;
+            indent += pos * INDENT_SPACE;
         }
     }
 
@@ -227,57 +227,14 @@
     }
 
     /**
-     * Check if the logger is above the level of detail given
+     * Check if the event of given level will be logged.
      * @see java.util.logging.Level
      *
-     * The higher the level, the more severe the warning
-     *
-     * @param level logging level
-     * @return true if level is above the given one
-     */
-    public boolean levelCoarserThan(final Level level) {
-        return getLevel().intValue() > level.intValue();
-    }
-
-    /**
-     * Check if the logger is above or equal to the level
-     * of detail given
-     * @see java.util.logging.Level
-     *
-     * The higher the level, the more severe the warning
-     *
      * @param level logging level
-     * @return true if level is above the given one
-     */
-    public boolean levelCoarserThanOrEqual(final Level level) {
-        return getLevel().intValue() >= level.intValue();
-    }
-
-    /**
-     * Check if the logger is below the level of detail given
-     * @see java.util.logging.Level
-     *
-     * The higher the level, the more severe the warning
-     *
-     * @param level logging level
-     * @return true if level is above the given one
+     * @return true if event of given level will be logged.
      */
-    public boolean levelFinerThan(final Level level) {
-        return getLevel().intValue() < level.intValue();
-    }
-
-    /**
-     * Check if the logger is below or equal to the level
-     * of detail given
-     * @see java.util.logging.Level
-     *
-     * The higher the level, the more severe the warning
-     *
-     * @param level logging level
-     * @return true if level is above the given one
-     */
-    public boolean levelFinerThanOrEqual(final Level level) {
-        return getLevel().intValue() <= level.intValue();
+    public boolean isLoggable(final Level level) {
+        return logger.isLoggable(level);
     }
 
     /**
@@ -566,7 +523,7 @@
      * @param str   string to log
      */
     public void log(final Level level, final String str) {
-        if (isEnabled && !isQuiet) {
+        if (isEnabled && !isQuiet && logger.isLoggable(level)) {
             final StringBuilder sb = new StringBuilder();
             for (int i = 0 ; i < indent ; i++) {
                 sb.append(' ');
@@ -584,7 +541,7 @@
      * @param objs  objects for which to invoke toString and concatenate to log
      */
     public void log(final Level level, final Object... objs) {
-        if (isEnabled && !isQuiet) {
+        if (isEnabled && !isQuiet && logger.isLoggable(level)) {
             final StringBuilder sb = new StringBuilder();
             for (final Object obj : objs) {
                 sb.append(obj);
--- a/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java	Thu Oct 29 17:22:12 2015 -0700
@@ -163,7 +163,7 @@
 
     /**
      * Does this option automatically enable another option, i.e. a dependency.
-     * @return the dependecy or null if non exists
+     * @return the dependency or null if none exists
      */
     public String getDependency() {
         return this.dependency;
@@ -304,8 +304,8 @@
         }
     }
 
-    boolean matches(final String key0) {
-        return key0.equals(this.shortName) || key0.equals(this.name);
+    boolean nameMatches(final String aName) {
+        return aName.equals(this.shortName) || aName.equals(this.name);
     }
 
     private static final int LINE_BREAK = 64;
--- a/src/jdk/nashorn/internal/runtime/options/Options.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/options/Options.java	Thu Oct 29 17:22:12 2015 -0700
@@ -519,9 +519,25 @@
         }
     }
 
-    private static OptionTemplate getOptionTemplate(final String key) {
+    /**
+     * Retrieves an option template identified by key.
+     * @param shortKey the short (that is without the e.g. "nashorn.option." part) key
+     * @return the option template identified by the key
+     * @throws IllegalArgumentException if the key doesn't specify an existing template
+     */
+    public OptionTemplate getOptionTemplateByKey(final String shortKey) {
+        final String fullKey = key(shortKey);
+        for(final OptionTemplate t: validOptions) {
+            if(t.getKey().equals(fullKey)) {
+                return t;
+            }
+        }
+        throw new IllegalArgumentException(shortKey);
+    }
+
+    private static OptionTemplate getOptionTemplateByName(final String name) {
         for (final OptionTemplate t : Options.validOptions) {
-            if (t.matches(key)) {
+            if (t.nameMatches(name)) {
                 return t;
             }
         }
@@ -681,7 +697,7 @@
             }
 
             final String token = st.nextToken();
-            this.template = Options.getOptionTemplate(token);
+            this.template = getOptionTemplateByName(token);
             if (this.template == null) {
                 throw new IllegalArgumentException(argument);
             }
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java	Thu Oct 29 17:22:12 2015 -0700
@@ -65,7 +65,7 @@
 
     final boolean DONT_OPTIMIZE                     = false;
 
-    final boolean USE_STRING_TEMPLATES              = true; // use embeded string templates in Regex object as byte arrays instead of compiling them into int bytecode array
+    final boolean USE_STRING_TEMPLATES              = true; // use embedded string templates in Regex object as byte arrays instead of compiling them into int bytecode array
 
     final boolean NON_UNICODE_SDW                   = true;
 
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java	Thu Oct 29 17:22:12 2015 -0700
@@ -24,6 +24,6 @@
     private static final long serialVersionUID = -6027192180014164667L;
 
     public JOniException(final String message) {
-        super(message);
+        super(message, null, false, false);
     }
 }
--- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Thu Oct 29 17:22:12 2015 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2015, 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
@@ -31,6 +31,7 @@
 lexer.error.json.invalid.number=Invalid JSON number format
 lexer.error.invalid.escape.char=Invalid escape character
 lexer.error.illegal.identifier.character=Illegal character in identifier
+lexer.error.here.non.matching.delimiter=Quoted here string end marker must have matching delimiters
 
 parser.error.illegal.continue.stmt=Illegal continue statement
 parser.error.illegal.break.stmt=Illegal break statement
@@ -78,6 +79,7 @@
 type.error.not.a.regexp={0} is not a RegExp
 type.error.not.a.string={0} is not a String
 type.error.not.a.function={0} is not a function
+type.error.not.a.function.value={0}, which has value {1}, is not a function
 type.error.not.a.constructor={0} is not a constructor function
 type.error.not.a.file={0} is not a File
 type.error.not.a.numeric.array={0} is not a numeric array
@@ -148,6 +150,7 @@
 type.error.method.not.constructor=Java method {0} cannot be used as a constructor.
 type.error.env.not.object=$ENV must be an Object.
 type.error.unsupported.java.to.type=Unsupported Java.to target type {0}.
+type.error.java.array.conversion.failed=Java.to conversion to array type {0} failed
 type.error.constructor.requires.new=Constructor {0} requires "new".
 type.error.new.on.nonpublic.javatype=new cannot be used with non-public java type {0}.
 
@@ -161,6 +164,7 @@
 range.error.invalid.date=Invalid Date
 range.error.too.many.errors=Script contains too many errors: {0} errors
 range.error.concat.string.too.big=Concatenated String is too big
+range.error.exec.returned.non.zero=$EXEC returned non-zero exit code: {0}
 
 reference.error.not.defined="{0}" is not defined
 reference.error.cant.be.used.as.lhs="{0}" can not be used as the left-hand side of assignment
@@ -171,7 +175,9 @@
 syntax.error.unprotected.switch.declaration=Unsupported {0} declaration in unprotected switch statement
 
 io.error.cant.write=cannot write "{0}"
+
 config.error.no.dest=no destination directory supplied
+config.error.eagerCompilationConflictsWithOptimisticTypes={0}=false (eager compilation) is not compatible with {1}=true.
 
 uri.error.bad.uri=Bad URI "{0}" near offset {1}
 list.adapter.null.global=Attempted to create the adapter from outside a JavaScript execution context.
--- a/src/jdk/nashorn/internal/runtime/resources/parser.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/internal/runtime/resources/parser.js	Thu Oct 29 17:22:12 2015 -0700
@@ -55,7 +55,7 @@
                 // do not start with '/'. If regexp, then eval it to make RegExp object
                 return value.startsWith('/')? eval(value) : value.substring(1);
             } else {
-                // anythin else is returned "as is""
+                // anything else is returned "as is"
                 return value;
             }
         });
--- a/src/jdk/nashorn/tools/Shell.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/src/jdk/nashorn/tools/Shell.java	Thu Oct 29 17:22:12 2015 -0700
@@ -54,7 +54,6 @@
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
@@ -255,12 +254,9 @@
                     return COMPILATION_ERROR;
                 }
 
-                new Compiler(
+                Compiler.forNoInstallerCompilation(
                        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);
 
--- a/test/script/basic/JDK-8026016.js.EXPECTED	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8026016.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -1,182 +1,182 @@
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such method _,0
-no such method _,1
-no such method _,2
-no such method _,3
-no such method _,4
-no such method _,5
-no such method _,6
-no such method _,7
-no such method _,8
-no such method _,9
-no such method _,10
-no such method _,11
-no such method _,12
-no such method _,13
-no such method _,14
-no such method _,15
-no such method _,16
-no such method _,17
-no such method _,18
-no such method _,19
-no such method _,20
-no such method _,21
-no such method _,22
-no such method _,23
-no such method _,24
-no such method _,25
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+TypeError: o._ is not a function
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such method _,0
+no such method _,1
+no such method _,2
+no such method _,3
+no such method _,4
+no such method _,5
+no such method _,6
+no such method _,7
+no such method _,8
+no such method _,9
+no such method _,10
+no such method _,11
+no such method _,12
+no such method _,13
+no such method _,14
+no such method _,15
+no such method _,16
+no such method _,17
+no such method _,18
+no such method _,19
+no such method _,20
+no such method _,21
+no such method _,22
+no such method _,23
+no such method _,24
+no such method _,25
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+TypeError: o._ is not a function
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
--- a/test/script/basic/JDK-8043232.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8043232.js	Thu Oct 29 17:22:12 2015 -0700
@@ -29,14 +29,14 @@
  */
 
 // call explicit constructor
-print(new (java.awt["Color(int,int,int)"])(255,0,255));
+print(new (java.lang["String(char[],int,int)"])(['a','b', 'c', 'd'], 1, 3));
 // print the constructor itself
-print(java.awt["Color(int,int,int)"]);
+print(java.lang["String(char[],int,int)"]);
 
 // store constructor to call later
-var Color = java.awt["Color(int,int,int)"];
+var Color = java.lang["String(char[],int,int)"];
 // call stored constructor
-print(new Color(33, 233, 2))
+print(new Color(['r','r', 'e', 'd'], 1, 3))
 
 // check if default constructor works
 var obj = new (java.lang["Object()"])();
--- a/test/script/basic/JDK-8043232.js.EXPECTED	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8043232.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -1,14 +1,28 @@
-java.awt.Color[r=255,g=0,b=255]
-[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)]
-java.awt.Color[r=33,g=233,b=2]
+bcd
+[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)]
+red
 TypeError: No such Java class: java.lang.NonExistent
 TypeError: No such Java constructor: Object(String)
 TypeError: Java constructor signature invalid: Object()xxxxx
 TypeError: Java constructor signature invalid: Object(
 TypeError: Java constructor signature invalid: Object)
-TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.lang.System.getProperty] cannot be used as a constructor.
-TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cannot be used as a constructor.
-TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires "new".
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod
+ String java.lang.System.getProperty(String,String)
+ String java.lang.System.getProperty(String)
+] cannot be used as a constructor.
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod
+ void java.io.PrintStream.println()
+ void java.io.PrintStream.println(boolean)
+ void java.io.PrintStream.println(char)
+ void java.io.PrintStream.println(char[])
+ void java.io.PrintStream.println(double)
+ void java.io.PrintStream.println(float)
+ void java.io.PrintStream.println(int)
+ void java.io.PrintStream.println(long)
+ void java.io.PrintStream.println(Object)
+ void java.io.PrintStream.println(String)
+] cannot be used as a constructor.
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new".
 TypeError: No such Java constructor: Runnable()
 TypeError: No such Java constructor: Runnable(int)
 java.lang.InstantiationException: java.io.InputStream
--- a/test/script/basic/JDK-8044750.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8044750.js	Thu Oct 29 17:22:12 2015 -0700
@@ -25,6 +25,8 @@
  * JDK-8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook
  *
  * @test
+ * @fork
+ * @option -Dnashorn.unstable.relink.threshold=16
  * @run
  */
 
@@ -40,7 +42,9 @@
     }
 }
 
-for (var i = 0; i < 20; i++) {
+var LIMIT = 20; // should be more than megamorphic threshold set via @option
+
+for (var i = 0; i < LIMIT; i++) {
     var obj = {};
     obj.foo = i;
     obj[i] = i;
@@ -51,3 +55,30 @@
 // callsite inside func should see __noSuchProperty__
 // hook on global scope object.
 func({});
+
+function checkFoo() {
+    with({}) {
+        try {
+            foo;
+            return true;
+        } catch (e) {
+            return false;
+        }
+    }
+}
+
+var oldNoSuchProperty = this.__noSuchProperty__;
+delete this.__noSuchProperty__;
+
+// keep deleting/restorting __noSuchProperty__ alternatively
+// to make "foo" access in checkFoo function megamorphic!
+
+for (var i = 0; i < LIMIT; i++) {
+    // no __noSuchProperty__ and 'with' scope object has no 'foo'
+    delete __noSuchProperty__;
+    Assert.assertFalse(checkFoo(), "Expected false in iteration " + i);
+
+    // __noSuchProperty__ is exists but 'with' scope object has no 'foo'
+    this.__noSuchProperty__ = oldNoSuchProperty;
+    Assert.assertTrue(checkFoo(), "Expected true in iteration " + i);
+}
--- a/test/script/basic/JDK-8049086.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8049086.js	Thu Oct 29 17:22:12 2015 -0700
@@ -58,7 +58,7 @@
 // (a) Java methods (b) Java classes (as these respond to new)
 // (c) FunctionalInterface objects (d) JSObjects that are 'functions'
 
-print("java.awt.Color is java function? " + Java.isJavaFunction(java.awt.Color));
+print("java.lang.String is java function? " + Java.isJavaFunction(java.lang.String));
 print("java.lang.Runnable instance is java function? "
     + Java.isJavaFunction(new java.lang.Runnable(function() {})));
 print("eval is java function? " + Java.isJavaFunction(eval));
--- a/test/script/basic/JDK-8049086.js.EXPECTED	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8049086.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -13,7 +13,7 @@
 Object is script object? true
 {} is script object? true
 /foo/ is script object? true
-java.awt.Color is java function? true
+java.lang.String is java function? true
 java.lang.Runnable instance is java function? true
 eval is java function? false
 println is java function? true
--- a/test/script/basic/JDK-8049242.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8049242.js	Thu Oct 29 17:22:12 2015 -0700
@@ -29,14 +29,14 @@
  */
 
 // call explicit constructor
-print(new (Java.type("java.awt.Color")["(int,int,int)"])(255,0,255));
+print(new (Java.type("java.lang.String")["(char[],int,int)"])(['a', 'b', 'c'],0, 3));
 // print the constructor itself
-print(Java.type("java.awt.Color")["(int,int,int)"]);
+print(Java.type("java.lang.String")["(char[],int,int)"]);
 
 // store constructor to call later
-var Color = Java.type("java.awt.Color")["(int,int,int)"];
+var Color = Java.type("java.lang.String")["(char[],int,int)"];
 // call stored constructor
-print(new Color(33, 233, 2))
+print(new Color(['j', 'a', 'v', 'a'], 1, 3))
 
 // check if default constructor works
 var obj = new (Java.type("java.lang.Object")["()"])();
--- a/test/script/basic/JDK-8049242.js.EXPECTED	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8049242.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -1,10 +1,10 @@
-java.awt.Color[r=255,g=0,b=255]
-[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)]
-java.awt.Color[r=33,g=233,b=2]
+abc
+[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)]
+ava
 TypeError: null is not a function
 TypeError: null is not a function
 TypeError: null is not a function
-TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires "new".
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new".
 TypeError: null is not a function
 TypeError: null is not a function
 java.lang.InstantiationException: java.io.InputStream
--- a/test/script/basic/JDK-8053905.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8053905.js	Thu Oct 29 17:22:12 2015 -0700
@@ -28,6 +28,7 @@
  * @runif external.octane
  * @fork
  * @option -Dnashorn.compiler.splitter.threshold=1000
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
  * @option -scripting
  * @option --lazy-compilation=false
  */
--- a/test/script/basic/JDK-8058561.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8058561.js	Thu Oct 29 17:22:12 2015 -0700
@@ -26,7 +26,9 @@
  *
  * @test
  * @run
+ * @fork
  * @option --lazy-compilation=false
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
  */
 
 // Just attempting to compile this caused the NPE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8068901.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 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-8068901: Surprising behavior with more than one functional interface on a class
+ *
+ * @test
+ * @run
+ */
+
+var Consumer = java.util.function.Consumer;
+var JFunction = java.util.function.Function;
+
+var fc = new (Java.extend(JFunction, Consumer))({
+    apply: function(x) { print("fc invoked as a function") },
+    accept: function(x) { print("fc invoked as a consumer") }
+});
+
+var c = new Consumer(function(x) { print("c invoked as a consumer") });
+
+var cf = new (Java.extend(Consumer, JFunction))({
+    apply: function(x) { print("cf invoked as a function") },
+    accept: function(x) { print("cf invoked as a consumer") }
+});
+
+var f = new JFunction(function(x) { print("f invoked as a function") });
+
+for each(x in [fc, c, fc, cf, f, cf, c, fc, f, cf]) { x(null); }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8068901.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,10 @@
+fc invoked as a function
+c invoked as a consumer
+fc invoked as a function
+cf invoked as a consumer
+f invoked as a function
+cf invoked as a consumer
+c invoked as a consumer
+fc invoked as a function
+f invoked as a function
+cf invoked as a consumer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8068903.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 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-8068903: Can't invoke vararg @FunctionalInterface methods
+ *
+ * @test
+ * @run
+ */
+
+var vc = new (Java.type("jdk.nashorn.test.models.VarArgConsumer"))(
+    function(x) {
+        Assert.assertTrue(x.length == 3);
+        Assert.assertTrue(x[0] == 1);
+        Assert.assertTrue(x[1] == 2);
+        Assert.assertTrue(x[2] == 3);
+    }
+);
+
+vc(1, 2, 3);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8073733.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 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-8073733: TypeError messages with "call" and "new" could be improved
+ *
+ * @test
+ * @run
+ */
+
+var func = undefined;
+try {
+    func();
+} catch (e) {
+    print(e);
+}
+
+var obj = {};
+try {
+    obj.foo();
+} catch (e) {
+    print(e);
+}
+
+try {
+    new func();
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8073733.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,3 @@
+TypeError: func is not a function
+TypeError: obj.foo is not a function
+TypeError: func is not a function
--- a/test/script/basic/JDK-8078612_eager_1a.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8078612_eager_1a.js	Thu Oct 29 17:22:12 2015 -0700
@@ -29,6 +29,7 @@
  * @option -pcc
  * @option --lazy-compilation=false
  * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
  * @fork
  */
 
--- a/test/script/basic/JDK-8078612_eager_1b.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8078612_eager_1b.js	Thu Oct 29 17:22:12 2015 -0700
@@ -29,6 +29,7 @@
  * @option -pcc
  * @option --lazy-compilation=false
  * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
  * @fork
  */
 
--- a/test/script/basic/JDK-8078612_eager_2a.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8078612_eager_2a.js	Thu Oct 29 17:22:12 2015 -0700
@@ -29,6 +29,7 @@
  * @option -pcc
  * @option --lazy-compilation=false
  * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
  * @fork
  */
 
--- a/test/script/basic/JDK-8078612_eager_2b.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8078612_eager_2b.js	Thu Oct 29 17:22:12 2015 -0700
@@ -29,6 +29,7 @@
  * @option -pcc
  * @option --lazy-compilation=false
  * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
  * @fork
  */
 
--- a/test/script/basic/JDK-8079470.js.EXPECTED	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/JDK-8079470.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -1,2 +1,2 @@
-TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod File java.io.File.java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures.
-TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures.
+TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures.
+TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8087312.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 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-8087312: PropertyMapWrapper.equals should compare className
+ *
+ * @test
+ * @run
+ * @fork
+ * @option -Dnashorn.debug=true
+ */
+
+function createObject(type) {
+    // we want to make sure two different object literals with the same keys and types share the same property map.
+    if (type) {
+        return {
+            a: "a",
+            b: 1,
+            c: 0.1
+        }
+    } else {
+        return {
+            a: "x",
+            b: 10,
+            c: 3.4
+        }
+    }
+}
+
+var o1 = createObject(false);
+var o2 = createObject(true);
+Assert.assertTrue(Debug.map(o1) === Debug.map(o2));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8114838.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, 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-8114838: Anonymous functions escape to surrounding scope when defined under "with" statement
+ *
+ * @test
+ * @run
+ */
+
+// do *not* introduce new lines! The next line should be 32
+with({}) { function () {} }
+if (typeof this["L:32"] != 'undefined') {
+    throw new Error("anonymous name spills into global scope");
+}
+
+var func = eval("function() {}");
+if (typeof func != 'function') {
+    throw new Error("eval of anonymous function does not work!");
+}
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+var engine = new ScriptEngineManager().getEngineByName("nashorn");
+var func2 = engine.eval("function() {}");
+if (typeof func2 != 'function') {
+    throw new Error("eval of anonymous function does not work from script engine!");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8130853.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, 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-8130853: Non-extensible global is not handled property
+ *
+ * @test
+ * @run
+ */
+
+// don't allow extensions to global
+Object.preventExtensions(this);
+try {
+    eval("var x = 34;");
+    throw new Error("should have thrown TypeError");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        throw e;
+    }
+}
+
+try {
+    eval("function func() {}");
+    throw new Error("should have thrown TypeError");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        throw e;
+    }
+}
+
+function checkLoad(code) {
+    try {
+        load({ name: "test", script: code });
+        throw new Error("should have thrown TypeError for load: " + code);
+    } catch (e) {
+        if (! (e instanceof TypeError)) {
+            throw e;
+        }
+    }
+}
+
+checkLoad("var y = 55");
+checkLoad("function f() {}");
+
+// check script engine eval
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+var e = new ScriptEngineManager().getEngineByName("nashorn");
+var global = e.eval("this");
+e.eval("Object.preventExtensions(this);");
+try {
+    e.eval("var myVar = 33;");
+    throw new Error("should have thrown TypeError");
+} catch (e) {
+    if (! (e.cause.ecmaError instanceof global.TypeError)) {
+        throw e;
+    }
+}
+
+// Object.bindProperties on arbitrary non-extensible object
+var obj = {};
+Object.preventExtensions(obj);
+try {
+    Object.bindProperties(obj, { foo: 434 });
+    throw new Error("should have thrown TypeError");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        throw e;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8131039.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 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-8131039: after adding a function property to Object.prototype, JSON.parse with reviver function goes into infinite loop
+ *
+ * @test
+ * @run
+ */
+
+Object.prototype.func = function() {}
+
+function identity(k, v) { return v };
+var obj = JSON.parse('{\"name\" : \"nashorn\"}', identity);
+Assert.assertTrue(obj.name, "nashorn");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8131340.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, 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-8131340:  Varargs function is recompiled each time it is linked
+ *
+ * @test
+ * @run
+ */
+
+// This is an indirect test. If repeated calls were to cause recompilation
+// this would trigger an assertion in RecompilableScriptFunctionData.
+
+function varargs() {
+    return arguments;
+}
+
+varargs(1);
+varargs(2);
+varargs(3);
+varargs(4);
+varargs(5);
+varargs(6);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8131683.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, 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-8131683: Delete fails over multiple scopes
+ *
+ * @test
+ * @run
+ */
+
+a = 1;
+b = 2;
+c = 3;
+
+var A = 1;
+var B = 2;
+var C = 3;
+function D() {}
+
+print((function() {
+    var x; // force creation of scope
+    (function() { x; })();
+    return delete a;
+})());
+
+print((function() {
+    eval("");
+    return delete b;
+})());
+
+print((function() {
+    return eval("delete c");
+})());
+
+print((function() {
+    eval("d = 4");
+    return eval("delete d");
+})());
+
+print(typeof a);
+print(typeof b);
+print(typeof c);
+print(typeof d);
+
+print((function() {
+    var x; // force creation of scope
+    (function() { x; })();
+    return delete A;
+})());
+
+print((function() {
+    eval("");
+    return delete B;
+})());
+
+print((function() {
+    return eval("delete C");
+})());
+
+print((function() {
+    eval("");
+    return delete D;
+})());
+
+print(typeof A);
+print(typeof B);
+print(typeof C);
+print(typeof D);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8131683.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,16 @@
+true
+true
+true
+true
+undefined
+undefined
+undefined
+undefined
+false
+false
+false
+false
+number
+number
+number
+function
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8133119.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 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-8133119: Error message associated with TypeError for call and new should include stringified Node
+ *
+ * @test
+ * @run
+ */
+
+var obj = {}
+try {
+    obj.func();
+} catch (e) {
+    print(e);
+}
+
+var arr = [33];
+try {
+    arr[0].func();
+} catch (e) {
+    print(e);
+}
+
+try {
+    new obj.func();
+} catch (e) {
+    print(e);
+}
+
+try {
+    new arr[0].func();
+} catch (e) {
+    print(e);
+}
+
+obj.foo = {}
+try {
+    new obj.foo();
+} catch (e) {
+    print(e);
+}
+
+try {
+    obj.foo();
+} catch (e) {
+    print(e);
+}
+
+var v = new java.util.Vector();
+try {
+    v();
+} catch (e) {
+    print(e);
+}
+
+try {
+    new v();
+} catch (e) {
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8133119.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,8 @@
+TypeError: obj.func is not a function
+TypeError: arr[0].func is not a function
+TypeError: obj.func is not a function
+TypeError: arr[0].func is not a function
+TypeError: obj.foo is not a function
+TypeError: obj.foo is not a function
+TypeError: v is not a function
+TypeError: v is not a function
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8134488.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 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-8134488: var statement in if(false) block incorrectly evacuated into enclosing function
+ *
+ * @test
+ * @run
+ */
+
+var x = "string"; 
+print(x); 
+
+(function f1() { 
+    (function f2() { 
+        // If it finds both 'print' and 'x', it'll print 'string'.
+        print(x); 
+    })(); 
+
+    if (false) { 
+        (function f3() { 
+            var x; 
+        })(); 
+    } 
+
+})(); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8134488.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,2 @@
+string
+string
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8134490.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 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-8134490: Dead var statement evacuation incorrectly descends into nested functions
+ *
+ * @test
+ * @run
+ */
+
+var v1; 
+
+function f1() 
+{ 
+v1 = 1; 
+return true; 
+(function () { var v1; })(); 
+} 
+
+f1(); 
+// If it executes without throwing an exception in code generator, it's working.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8134569.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2015, 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-8134569: Add tests for prototype callsites
+ *
+ * @test
+ * @run
+ */
+
+function create() {
+    function C() {
+        this.i1 = 1;
+        this.i2 = 2;
+        this.i3 = 3;
+        return this;
+    }
+    return new C();
+}
+
+function createEmpty() {
+    function C() {
+        return this;
+    }
+    return new C();
+}
+
+function createDeep() {
+    function C() {
+        this.i1 = 1;
+        this.i2 = 2;
+        this.i3 = 3;
+        return this;
+    }
+    function D() {
+        this.p1 = 1;
+        this.p2 = 2;
+        this.p3 = 3;
+        return this;
+    }
+    C.prototype = new D();
+    return new C();
+}
+
+function createDeeper() {
+    function C() {
+        this.i1 = 1;
+        this.i2 = 2;
+        this.i3 = 3;
+        return this;
+    }
+    function D() {
+        this.p1 = 1;
+        this.p2 = 2;
+        this.p3 = 3;
+        return this;
+    }
+    function E() {
+        this.e1 = 1;
+        this.e2 = 2;
+        this.e3 = 3;
+        return this;
+    }
+    D.prototype = new E();
+    C.prototype = new D();
+    return new C();
+}
+
+function createEval() {
+    return eval("Object.create({})");
+}
+
+function p(o) { print(o.x) }
+
+function e(o) { print(o.e1) }
+
+var a, b, c;
+
+create();
+a = create();
+b = create();
+c = create();
+a.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = create();
+b = create();
+c = create();
+b.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createEmpty();
+b = createEmpty();
+c = createEmpty();
+a.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createEmpty();
+b = createEmpty();
+c = createEmpty();
+b.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeep();
+b = createDeep();
+c = createDeep();
+a.__proto__.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeep();
+b = createDeep();
+c = createDeep();
+b.__proto__.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeeper();
+b = createDeeper();
+c = createDeeper();
+a.__proto__.__proto__.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeeper();
+b = createDeeper();
+c = createDeeper();
+b.__proto__.__proto__.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeeper();
+b = createDeeper();
+c = createDeeper();
+a.__proto__.__proto__ = null;
+
+e(a);
+e(b);
+e(c);
+
+a = createDeeper();
+b = createDeeper();
+c = createDeeper();
+b.__proto__.__proto__ = null;
+
+e(a);
+e(b);
+e(c);
+
+
+a = createEval();
+b = createEval();
+c = createEval();
+a.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createEval();
+b = createEval();
+c = createEval();
+b.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8134569.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,36 @@
+123
+undefined
+undefined
+undefined
+123
+undefined
+123
+undefined
+undefined
+undefined
+123
+undefined
+123
+undefined
+undefined
+undefined
+123
+undefined
+123
+undefined
+undefined
+undefined
+123
+undefined
+undefined
+1
+1
+1
+undefined
+1
+123
+undefined
+undefined
+undefined
+123
+undefined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8134609.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, 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-8134609: Allow constructors with same prototoype map to share the allocator map
+ *
+ * @test
+ * @run
+ * @fork
+ * @option -Dnashorn.debug
+ */
+
+function createProto(members) {
+    function P() {
+        for (var id in members) {
+            if (members.hasOwnProperty(id)) {
+                this[id] = members[id];
+            }
+        }
+        return this;
+    }
+    return new P();
+}
+
+function createSubclass(prototype, members) {
+    function C() {
+        for (var id in members) {
+            if (members.hasOwnProperty(id)) {
+                this[id] = members[id];
+            }
+        }
+        return this;
+    }
+
+    C.prototype = prototype;
+
+    return new C();
+}
+
+function assertP1(object, value) {
+    Assert.assertTrue(object.p1 === value);
+}
+
+// First prototype will have non-shared proto-map. Second and third will be shared.
+var proto0 = createProto({p1: 0, p2: 1});
+var proto1 = createProto({p1: 1, p2: 2});
+var proto2 = createProto({p1: 2, p2: 3});
+
+Assert.assertTrue(Debug.map(proto1) === Debug.map(proto2));
+
+assertP1(proto1, 1);
+assertP1(proto2, 2);
+
+// First instantiation will have a non-shared prototype map, from the second one
+// maps will be shared until a different proto map comes along.
+var child0 = createSubclass(proto1, {c1: 1, c2: 2});
+var child1 = createSubclass(proto2, {c1: 2, c2: 3});
+var child2 = createSubclass(proto1, {c1: 3, c2: 4});
+var child3 = createSubclass(proto2, {c1: 1, c2: 2});
+var child4 = createSubclass(proto0, {c1: 3, c2: 2});
+
+Assert.assertTrue(Debug.map(child1) === Debug.map(child2));
+Assert.assertTrue(Debug.map(child1) === Debug.map(child3));
+Assert.assertTrue(Debug.map(child3) !== Debug.map(child4));
+
+assertP1(child1, 2);
+assertP1(child2, 1);
+assertP1(child3, 2);
+assertP1(child4, 0);
+
+Assert.assertTrue(delete proto2.p1);
+
+assertP1(child3, undefined);
+assertP1(child2, 1);
+Assert.assertTrue(Debug.map(child1) !== Debug.map(child3));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8134731.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, 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-8134731: `Function.prototype.apply` interacts incorrectly with `arguments` 
+ *
+ * @test
+ * @run
+ */
+
+function func() {
+    return (function(f){
+        return function(a1, a2, a3, a4){
+            return (f.apply(this, arguments));
+        }
+    })(function(){
+        return arguments.length;
+    })
+}
+
+Assert.assertTrue(func()() == 0);
+Assert.assertTrue(func()(33) == 1);
+Assert.assertTrue(func()(33, true) == 2);
+Assert.assertTrue(func()(33, true, "hello") == 3);
+Assert.assertTrue(func()(33, true, "hello", "world") == 4);
+Assert.assertTrue(func()(33, true, "hello", "world", 42) == 5);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8134939.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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-8134939: Improve toString method of Dynalink OverloadedDynamicMethod
+ *
+ * @test
+ * @run
+ */
+
+var overloadedSetter = new (Java.type("jdk.nashorn.test.models.OverloadedSetter"));
+
+Assert.assertEquals(String(overloadedSetter.foo),
+  "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" +
+  " String jdk.nashorn.test.models.OverloadedSetter.foo(String)\n" +
+  " void jdk.nashorn.test.models.OverloadedSetter.foo(int)\n" +
+  "]");
+
+Assert.assertEquals(String(overloadedSetter.setColor),
+  "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" +
+  " void jdk.nashorn.test.models.OverloadedSetter.setColor(int)\n" +
+  " void jdk.nashorn.test.models.OverloadedSetter.setColor(String)\n" +
+  "]");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8135000.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, 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-8135000: Number.prototype.toFixed returns wrong string for 0.5 and -0.5
+ *
+ * @test
+ * @run
+ */
+
+print(-2.6.toFixed());
+print(-2.5.toFixed());
+print(-2.4.toFixed());
+print(-1.6.toFixed());
+print(-1.5.toFixed());
+print(-1.4.toFixed());
+print(-0.6.toFixed());
+print(-0.5.toFixed());
+print(-0.4.toFixed());
+print(0.4.toFixed());
+print(0.5.toFixed());
+print(0.6.toFixed());
+print(1.4.toFixed());
+print(1.5.toFixed());
+print(1.6.toFixed());
+print(2.4.toFixed());
+print(2.5.toFixed());
+print(2.6.toFixed());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8135000.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,18 @@
+-3
+-3
+-2
+-2
+-2
+-1
+-1
+-1
+0
+0
+1
+1
+1
+2
+2
+2
+3
+3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8135190.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, 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-8135190: Method code too large in Babel browser.js script
+ *
+ * @test
+ * @run
+ */
+
+// Make sure huge object literals are parsed correctly and don't throw
+// (using buildObject -> JSON.stringify -> eval -> testObject)
+
+function buildObject(n, d) {
+    if (n < 2) {
+        return {name: "property", type: "identifier"};
+    }
+    var obj = {};
+    for (var i = 0; i < n; i++) {
+        obj["expr" + i] = buildObject(Math.floor(n / d), d);
+    }
+    return obj;
+}
+
+function testObject(obj, n, d) {
+    var keys = Object.keys(obj);
+    if (n < 2) {
+        Assert.assertTrue(keys.length === 2);
+        Assert.assertTrue(keys[0] === "name");
+        Assert.assertTrue(keys[1] === "type");
+    } else {
+        Assert.assertTrue(keys.length === n);
+        for (var i = 0; i < n; i++) {
+            Assert.assertTrue(keys[i] === "expr" + i);
+        }
+    }
+    if (n >= 2) {
+        for (var k in keys) {
+            testObject(obj[keys[k]], Math.floor(n / d), d)
+        }
+    }
+}
+
+var fieldObject = (eval("(" + JSON.stringify(buildObject(25, 2)) + ")"));
+testObject(fieldObject, 25, 2);
+var spillObject = (eval("(" + JSON.stringify(buildObject(1000, 100)) + ")"));
+testObject(spillObject, 1000, 100);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8136544.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, 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-8136544: Call site switching to megamorphic causes incorrect property read
+ *
+ * @test
+ * @fork
+ * @option -Dnashorn.unstable.relink.threshold=8
+ * @run
+ */
+
+var ScriptContext = Java.type("javax.script.ScriptContext");
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+var m = new ScriptEngineManager();
+var e = m.getEngineByName("nashorn");
+
+var scope = e.getBindings(ScriptContext.ENGINE_SCOPE);
+var MYVAR = "myvar";
+
+function loopupVar() {
+    try {
+        e.eval(MYVAR);
+        return true;
+    } catch (e) {
+        return false;
+    }
+}
+
+// make sure we exercise callsite beyond megamorphic threshold we set
+// in this test via nashorn.unstable.relink.threshold property
+// In each iteration, callsite is exercised twice (two evals)
+// So, LIMIT should be more than 4 to exercise megamorphic callsites.
+
+var LIMIT = 5; // This LIMIT should be more than 4
+
+for (var i = 0; i < LIMIT; i++) {
+    // remove the variable and lookup
+    delete scope[MYVAR];
+    Assert.assertFalse(loopupVar(), "Expected true in iteration " + i);
+
+    // set that variable and check again
+    scope[MYVAR] = "foo";
+    Assert.assertTrue(loopupVar(), "Expected false in iteration " + i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8136694.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, 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-8136694: Megemorphic scope access does not throw ReferenceError when property is missing
+ *
+ * @test
+ * @fork
+ * @option -Dnashorn.unstable.relink.threshold=16
+ * @run
+ */
+
+function checkFoo() {
+    try {
+        // The 'foo' access becomes megamorphic
+        foo;
+        return true;
+    } catch (e) {
+        return false;
+    }
+}
+
+
+// Similar check for 'with' blocks as well.
+function checkFooInWith() {
+    with({}) {
+        try {
+            // The 'foo' access becomes megamorphic
+            foo;
+            return true;
+        } catch (e) {
+            return false;
+        }
+    }
+}
+
+function loop(checker) {
+    // LIMIT has to be more than the megamorphic threashold
+    // set via @option in this test header!
+    var LIMIT = 20;
+    for (var i = 0; i < LIMIT; i++) {
+        // make sure global has no "foo"
+        delete foo;
+        Assert.assertFalse(checker(), "Expected false in interation " + i);
+
+        // now add 'foo' in global
+        foo = 44;
+        Assert.assertTrue(checker(), "Expected true in interation " + i);
+    }
+}
+
+
+loop(checkFoo);
+loop(checkFooInWith);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8137134.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, 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-8137134: invokespecial on indirect super interface is generated by Java adapter generator
+ *
+ * @test
+ * @run
+ */
+
+var B = Java.type("jdk.nashorn.test.models.B");
+var b1 = new B() {}
+print(b1.a());
+print(b1.b());
+
+var b2 = new B() {
+    b: function() {
+        return "from B.b in script";
+    }
+};
+
+print(b2.a());
+print(b2.b());
+
+var b3 = new B() {
+    a: function() {
+        return "from A.a in script";
+    },
+    b: function() {
+        return "from B.b in script";
+    }
+};
+
+print(b3.a());
+print(b3.b());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8137134.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,6 @@
+from A.a
+from B.b
+from A.a
+from B.b in script
+from A.a in script
+from B.b in script
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8137281.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 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-8137281: OutOfMemoryError with large numeric keys in JSON.parse
+ *
+ * @test
+ * @run
+ */
+
+function createObject(startKey, level1, level2) {
+    var root = {};
+    var key = startKey;
+    for (var i = 0; i < level1; i++) {
+        var child = {};
+        for (var j = 0; j < level2; j++) {
+            child[key++] = {};
+        }
+        root[key++] = child;
+    }
+    return root;
+}
+
+JSON.parse(JSON.stringify(createObject(500000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(1000000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(2000000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(4000000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(8000000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(16000000, 20, 20)));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8138632.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 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-8138632: Sparse array does not handle growth of underlying dense array
+ *
+ * @test
+ * @run
+ */
+
+var x = [];
+x[10000000] = 1;
+x[10] = 1;
+x[20] = 1;
+print(Object.keys(x));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8138632.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,1 @@
+10,20,10000000
--- a/test/script/basic/NASHORN-75.js.EXPECTED	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/NASHORN-75.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -1,3 +1,3 @@
-TypeError: [RegExp /a|b/g] is not a function
-TypeError: [String hello] is not a function
-TypeError: [object Object] is not a function
+TypeError: RegExp("a|b", "g") is not a function
+TypeError: new String("hello") is not a function
+TypeError: new Object() is not a function
--- a/test/script/basic/errors.js.EXPECTED	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/errors.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -1,31 +1,31 @@
-Error is a function
-EvalError is a function
-RangeError is a function
-ReferenceError is a function
-SyntaxError is a function
-TypeError is a function
-URIError is a function
-Error.arity 1
-EvalError.arity 1
-RangeError.arity 1
-ReferenceError.arity 1
-SyntaxError.arity 1
-TypeError.arity 1
-URIError.arity 1
-true
-my error
-Error
-thrown @ 49
-true
-ReferenceError
-"foo" is not defined
-true
-TypeError
-Cannot call undefined
-Error
-EvalError
-RangeError
-ReferenceError
-SyntaxError
-TypeError
-URIError
+Error is a function
+EvalError is a function
+RangeError is a function
+ReferenceError is a function
+SyntaxError is a function
+TypeError is a function
+URIError is a function
+Error.arity 1
+EvalError.arity 1
+RangeError.arity 1
+ReferenceError.arity 1
+SyntaxError.arity 1
+TypeError.arity 1
+URIError.arity 1
+true
+my error
+Error
+thrown @ 49
+true
+ReferenceError
+"foo" is not defined
+true
+TypeError
+Object.foo_method is not a function
+Error
+EvalError
+RangeError
+ReferenceError
+SyntaxError
+TypeError
+URIError
--- a/test/script/basic/javaarrayconversion.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/basic/javaarrayconversion.js	Thu Oct 29 17:22:12 2015 -0700
@@ -128,24 +128,32 @@
 // Converting to string, toString takes precedence over valueOf
 test({ valueOf: function() { return "42"; },  toString: function() { return "43"; } }, "java.lang.String", "43")
 
+function assertCanConvert(sourceType, targetType) {
+  Java.to([new (Java.type(sourceType))()], targetType + "[]")
+  ++testCount;
+}
+
 function assertCantConvert(sourceType, targetType) {
   try {
-    Java.to([new Java.type(sourceType)()], targetType + "[]")
+    Java.to([new (Java.type(sourceType))()], targetType + "[]")
     throw "no TypeError encountered"
   } catch(e) {
-      if(!(e instanceof TypeError)) {
+      if(!(e instanceof TypeError) ||
+          !e.message.startsWith("Java.to conversion to array type")) {
         throw e;
       }
       ++testCount;
   }
 }
 
+// Arbitrary POJOs to JS Primitive type should work
+assertCanConvert("java.util.BitSet", "int")
+assertCanConvert("java.util.BitSet", "double")
+assertCanConvert("java.util.BitSet", "long")
+assertCanConvert("java.util.BitSet", "boolean")
+assertCanConvert("java.util.BitSet", "java.lang.String")
+
 // Arbitrary POJOs can't be converted to Java values
-assertCantConvert("java.util.BitSet", "int")
-assertCantConvert("java.util.BitSet", "double")
-assertCantConvert("java.util.BitSet", "long")
-assertCantConvert("java.util.BitSet", "boolean")
-assertCantConvert("java.util.BitSet", "java.lang.String")
 assertCantConvert("java.util.BitSet", "java.lang.Double")
 assertCantConvert("java.util.BitSet", "java.lang.Long")
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/nosecurity/JDK-8073613.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 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-8073613: Here documents: how to avoid string interpolation?
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+var a = 2,
+    b = 3
+
+print(<<EOD)
+${a}${b}
+EOD
+
+print(<<"EOD")
+${a}${b}
+EOD
+
+print(<<'EOM')
+${a}${b}
+EOM
+
+print(<<"EOM")
+$\{a}
+EOM
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/nosecurity/JDK-8073613.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,4 @@
+23
+${a}${b}
+${a}${b}
+$\{a}
--- a/test/script/trusted/JDK-8006529.js	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/trusted/JDK-8006529.js	Thu Oct 29 17:22:12 2015 -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, ErrorManager.class, boolean.class);
+var CompilerConstructor = Compiler.class.getMethod("forNoInstallerCompilation", Context.class, Source.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, null, false);
+    var compiler = CompilerConstructor.invoke(null, ctxt, source, false);
 
     return compileMethod.invoke(compiler, func, phases);
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/trusted/JDK-8087292.js	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, 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-8087292: nashorn should have a "fail-fast" option for scripting, analog to bash "set -e"
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+function tryExec() {
+    try {
+        `java`
+    } catch (e) {
+        print(e);
+    }
+
+    // make sure we got non-zero ("failure") exit code!
+    if ($EXIT == 0) {
+        print("Error: expected $EXIT code to be non-zero");
+    }
+}
+
+// no exception now!
+tryExec();
+
+// turn on error with non-zero exit code
+$EXEC.throwOnError = true;
+tryExec();
+
+// no exception after this
+$EXEC.throwOnError = false;
+tryExec();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/trusted/JDK-8087292.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,1 @@
+RangeError: $EXEC returned non-zero exit code: 1
--- a/test/script/trusted/classfilter.js.EXPECTED	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/script/trusted/classfilter.js.EXPECTED	Thu Oct 29 17:22:12 2015 -0700
@@ -4,7 +4,18 @@
 typeof java.util.Map evalutes to function
 typeof java.util.HashMap evalutes to function
 var m = new java.util.HashMap(); m.put('foo', 42); m evalutes to {foo=42}
-java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println]
+java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod
+ void java.io.PrintStream.println()
+ void java.io.PrintStream.println(boolean)
+ void java.io.PrintStream.println(char)
+ void java.io.PrintStream.println(char[])
+ void java.io.PrintStream.println(double)
+ void java.io.PrintStream.println(float)
+ void java.io.PrintStream.println(int)
+ void java.io.PrintStream.println(long)
+ void java.io.PrintStream.println(Object)
+ void java.io.PrintStream.println(String)
+]
 java.lang.System.exit evalutes to [jdk.internal.dynalink.beans.SimpleDynamicMethod void java.lang.System.exit(int)]
 new javax.script.SimpleBindings throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.SimpleBindings
 Java.type('javax.script.ScriptContext') throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.ScriptContext
--- a/test/src/jdk/nashorn/api/scripting/JSONCompatibleTest.java	Fri Oct 16 12:19:59 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2015, 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.api.scripting;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-public class JSONCompatibleTest {
-
-    /**
-     * Wrap a top-level array as a list.
-     */
-    @Test
-    public void testWrapArray() throws ScriptException {
-        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
-        final Object val = engine.eval("Java.asJSONCompatible([1, 2, 3])");
-        assertEquals(asList(val), Arrays.asList(1, 2, 3));
-    }
-
-    /**
-     * Wrap an embedded array as a list.
-     */
-    @Test
-    public void testWrapObjectWithArray() throws ScriptException {
-        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
-        final Object val = engine.eval("Java.asJSONCompatible({x: [1, 2, 3]})");
-        assertEquals(asList(asMap(val).get("x")), Arrays.asList(1, 2, 3));
-    }
-
-    /**
-     * Check it all works transitively several more levels down.
-     */
-    @Test
-    public void testDeepWrapping() throws ScriptException {
-        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
-        final Object val = engine.eval("Java.asJSONCompatible({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
-        final Map<String, Object> root = asMap(val);
-        final List<Object> x = asList(root.get("x"));
-        assertEquals(x.get(0), 1);
-        final Map<String, Object> x1 = asMap(x.get(1));
-        final List<Object> y = asList(x1.get("y"));
-        assertEquals(y.get(0), 2);
-        final Map<String, Object> y1 = asMap(y.get(1));
-        assertEquals(asList(y1.get("z")), Arrays.asList(3));
-        assertEquals(asList(x.get(2)), Arrays.asList(4, 5));
-    }
-
-    /**
-     * Ensure that the old behaviour (every object is a Map) is unchanged.
-     */
-    @Test
-    public void testNonWrapping() throws ScriptException {
-        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
-        final Object val = engine.eval("({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
-        final Map<String, Object> root = asMap(val);
-        final Map<String, Object> x = asMap(root.get("x"));
-        assertEquals(x.get("0"), 1);
-        final Map<String, Object> x1 = asMap(x.get("1"));
-        final Map<String, Object> y = asMap(x1.get("y"));
-        assertEquals(y.get("0"), 2);
-        final Map<String, Object> y1 = asMap(y.get("1"));
-        final Map<String, Object> z = asMap(y1.get("z"));
-        assertEquals(z.get("0"), 3);
-        final Map<String, Object> x2 = asMap(x.get("2"));
-        assertEquals(x2.get("0"), 4);
-        assertEquals(x2.get("1"), 5);
-    }
-
-    @SuppressWarnings("unchecked")
-    private static List<Object> asList(final Object obj) {
-        assertJSObject(obj);
-        Assert.assertTrue(obj instanceof List);
-        return (List)obj;
-    }
-
-    @SuppressWarnings("unchecked")
-    private static Map<String, Object> asMap(final Object obj) {
-        assertJSObject(obj);
-        Assert.assertTrue(obj instanceof Map);
-        return (Map)obj;
-    }
-
-    private static void assertJSObject(final Object obj) {
-        assertTrue(obj instanceof JSObject);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/jdk/nashorn/api/scripting/test/JSONCompatibleTest.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015, 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.api.scripting.test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.NashornScriptEngine;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class JSONCompatibleTest {
+
+    /**
+     * Wrap a top-level array as a list.
+     */
+    @Test
+    public void testWrapArray() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("Java.asJSONCompatible([1, 2, 3])");
+        assertEquals(asList(val), Arrays.asList(1, 2, 3));
+    }
+
+    /**
+     * Wrap an embedded array as a list.
+     */
+    @Test
+    public void testWrapObjectWithArray() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("Java.asJSONCompatible({x: [1, 2, 3]})");
+        assertEquals(asList(asMap(val).get("x")), Arrays.asList(1, 2, 3));
+    }
+
+    /**
+     * Check it all works transitively several more levels down.
+     */
+    @Test
+    public void testDeepWrapping() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("Java.asJSONCompatible({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
+        final Map<String, Object> root = asMap(val);
+        final List<Object> x = asList(root.get("x"));
+        assertEquals(x.get(0), 1);
+        final Map<String, Object> x1 = asMap(x.get(1));
+        final List<Object> y = asList(x1.get("y"));
+        assertEquals(y.get(0), 2);
+        final Map<String, Object> y1 = asMap(y.get(1));
+        assertEquals(asList(y1.get("z")), Arrays.asList(3));
+        assertEquals(asList(x.get(2)), Arrays.asList(4, 5));
+    }
+
+    /**
+     * Ensure that the old behaviour (every object is a Map) is unchanged.
+     */
+    @Test
+    public void testNonWrapping() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
+        final Map<String, Object> root = asMap(val);
+        final Map<String, Object> x = asMap(root.get("x"));
+        assertEquals(x.get("0"), 1);
+        final Map<String, Object> x1 = asMap(x.get("1"));
+        final Map<String, Object> y = asMap(x1.get("y"));
+        assertEquals(y.get("0"), 2);
+        final Map<String, Object> y1 = asMap(y.get("1"));
+        final Map<String, Object> z = asMap(y1.get("z"));
+        assertEquals(z.get("0"), 3);
+        final Map<String, Object> x2 = asMap(x.get("2"));
+        assertEquals(x2.get("0"), 4);
+        assertEquals(x2.get("1"), 5);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static List<Object> asList(final Object obj) {
+        assertJSObject(obj);
+        Assert.assertTrue(obj instanceof List);
+        return (List)obj;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static Map<String, Object> asMap(final Object obj) {
+        assertJSObject(obj);
+        Assert.assertTrue(obj instanceof Map);
+        return (Map)obj;
+    }
+
+    private static void assertJSObject(final Object obj) {
+        assertTrue(obj instanceof JSObject);
+    }
+}
--- a/test/src/jdk/nashorn/api/scripting/test/PluggableJSObjectTest.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/src/jdk/nashorn/api/scripting/test/PluggableJSObjectTest.java	Thu Oct 29 17:22:12 2015 -0700
@@ -27,6 +27,7 @@
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
 import java.nio.IntBuffer;
@@ -34,9 +35,11 @@
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Set;
+import javax.script.Invocable;
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineManager;
 import jdk.nashorn.api.scripting.AbstractJSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import org.testng.annotations.Test;
 
 /**
@@ -286,4 +289,23 @@
             fail(exp.getMessage());
         }
     }
+
+    // @bug 8137258: JSObjectLinker and BrowserJSObjectLinker should not expose internal JS objects
+    @Test
+    public void hidingInternalObjectsForJSObjectTest() throws Exception {
+        final ScriptEngineManager engineManager = new ScriptEngineManager();
+        final ScriptEngine e = engineManager.getEngineByName("nashorn");
+
+        final String code = "function func(obj) { obj.foo = [5, 5]; obj.bar = {} }";
+        e.eval(code);
+
+        // call the exposed function but pass user defined JSObject impl as argument
+        ((Invocable)e).invokeFunction("func", new AbstractJSObject() {
+            @Override
+            public void setMember(final String name, final Object value) {
+                // make sure that wrapped objects are passed (and not internal impl. objects)
+                assertTrue(value.getClass() == ScriptObjectMirror.class);
+            }
+        });
+    }
 }
--- a/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java	Fri Oct 16 12:19:59 2015 -0700
+++ b/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java	Thu Oct 29 17:22:12 2015 -0700
@@ -26,9 +26,11 @@
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 import javax.script.Bindings;
+import javax.script.Invocable;
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
@@ -820,4 +822,93 @@
     public void recursiveEvalCallScriptContextTest() throws ScriptException {
         new RecursiveEval().program();
     }
+
+    private static final String VAR_NAME = "myvar";
+
+    private static boolean lookupVar(final ScriptEngine engine, final String varName) {
+        try {
+            engine.eval(varName);
+            return true;
+        } catch (final ScriptException se) {
+            return false;
+        }
+    }
+
+    // @bug 8136544: Call site switching to megamorphic causes incorrect property read
+    @Test
+    public void megamorphicPropertyReadTest() throws ScriptException {
+        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        final ScriptEngine engine = factory.getScriptEngine();
+        final Bindings scope = engine.getBindings(ScriptContext.ENGINE_SCOPE);
+        boolean ret;
+
+        // Why 16 is the upper limit of this loop? The default nashorn dynalink megamorphic threshold is 16.
+        // See jdk.nashorn.internal.runtime.linker.Bootstrap.NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD
+        // We do, 'eval' of the same in this loop twice. So, 16*2 = 32 times that callsite in the script
+        // is exercised - much beyond the default megamorphic threshold.
+
+        for (int i = 0; i < 16; i++) {
+            scope.remove(VAR_NAME);
+            ret = lookupVar(engine, VAR_NAME);
+            assertFalse(ret, "Expected false in iteration " + i);
+            scope.put(VAR_NAME, "foo");
+            ret = lookupVar(engine, VAR_NAME);
+            assertTrue(ret, "Expected true in iteration " + i);
+        }
+    }
+
+    // @bug 8138616: invokeFunction fails if function calls a function defined in GLOBAL_SCOPE
+    @Test
+    public void invokeFunctionInGlobalScopeTest() throws Exception {
+         final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
+         final ScriptContext ctxt = engine.getContext();
+
+         // define a function called "func"
+         engine.eval("func = function() { return 42 }");
+
+         // move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
+         ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
+
+         // create a new Bindings and set as ENGINE_SCOPE
+         ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+
+         // define new function that calls "func" now in GLOBAL_SCOPE
+         engine.eval("newfunc = function() { return func() }");
+
+         // call "newfunc" and check the return value
+         Object value = ((Invocable)engine).invokeFunction("newfunc");
+         assertTrue(((Number)value).intValue() == 42);
+    }
+
+
+    // @bug 8138616: invokeFunction fails if function calls a function defined in GLOBAL_SCOPE
+    // variant of above that replaces default ScriptContext of the engine with a fresh instance!
+    @Test
+    public void invokeFunctionInGlobalScopeTest2() throws Exception {
+         final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
+
+         // create a new ScriptContext instance
+         final ScriptContext ctxt = new SimpleScriptContext();
+         // set it as 'default' ScriptContext
+         engine.setContext(ctxt);
+
+         // create a new Bindings and set as ENGINE_SCOPE
+         ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+
+         // define a function called "func"
+         engine.eval("func = function() { return 42 }");
+
+         // move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
+         ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
+
+         // create a new Bindings and set as ENGINE_SCOPE
+         ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+
+         // define new function that calls "func" now in GLOBAL_SCOPE
+         engine.eval("newfunc = function() { return func() }");
+
+         // call "newfunc" and check the return value
+         Object value = ((Invocable)engine).invokeFunction("newfunc");
+         assertTrue(((Number)value).intValue() == 42);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/jdk/nashorn/test/models/A.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, 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.test.models;
+
+public interface A {
+    default String a() {
+        return "from A.a";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/jdk/nashorn/test/models/B.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, 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.test.models;
+
+public interface B extends A {
+    default String b() {
+        return "from B.b";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/jdk/nashorn/test/models/VarArgConsumer.java	Thu Oct 29 17:22:12 2015 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, 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.test.models;
+
+/**
+ * Simple function interface with a varargs SAM method.
+ */
+@FunctionalInterface
+public interface VarArgConsumer {
+    public void apply(Object... o);
+}
+