changeset 26893:b5f80ea5eb07

Merge
author lana
date Fri, 03 Oct 2014 12:10:58 -0700
parents 6d8e0b7c707c 97093836f3b7
children 429663d3d9ff
files
diffstat 45 files changed, 494 insertions(+), 316 deletions(-) [+]
line wrap: on
line diff
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java	Fri Oct 03 12:10:58 2014 -0700
@@ -85,6 +85,7 @@
 import jdk.internal.org.objectweb.asm.Handle;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Type;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
 
 /**
  * Base class for all method generating classes.
@@ -97,7 +98,7 @@
     private final Type returnType;
     private final Type[] argumentTypes;
 
-    static final Type EMPTY_LINK_LOGIC_TYPE = Type.getType("Ljdk/nashorn/internal/objects/annotations/SpecializedFunction$LinkLogic$Empty;");
+    static final Type EMPTY_LINK_LOGIC_TYPE = Type.getType(LinkLogic.getEmptyLinkLogicClass());
 
     MethodGenerator(final MethodVisitor mv, final int access, final String name, final String descriptor) {
         super(Main.ASM_VERSION, mv);
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java	Fri Oct 03 12:10:58 2014 -0700
@@ -38,6 +38,7 @@
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Setter;
 import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
 import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind;
 
@@ -55,8 +56,8 @@
     static final String SETTER_ANNO_DESC        = Type.getDescriptor(Setter.class);
     static final String PROPERTY_ANNO_DESC      = Type.getDescriptor(Property.class);
     static final String WHERE_ENUM_DESC         = Type.getDescriptor(Where.class);
+    static final String LINK_LOGIC_DESC         = Type.getDescriptor(LinkLogic.class);
     static final String SPECIALIZED_FUNCTION    = Type.getDescriptor(SpecializedFunction.class);
-    static final String LINK_LOGIC_DESC         = "Ljdk/nashorn/internal/objects/annotations/SpecializedFunction$LinkLogic;";
 
     static final Map<String, Kind> annotations = new HashMap<>();
 
--- a/nashorn/make/BuildNashorn.gmk	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/make/BuildNashorn.gmk	Fri Oct 03 12:10:58 2014 -0700
@@ -29,6 +29,7 @@
 -include $(SPEC)
 include MakeBase.gmk
 include JavaCompilation.gmk
+include SetupJavaCompilers.gmk
 
 JDK_CLASSES := $(subst $(SPACE),$(PATH_SEP),$(strip $(addprefix $(JDK_OUTPUTDIR)/modules/, \
       java.base java.logging java.scripting)))
@@ -63,10 +64,10 @@
 
 # Build nasgen
 $(eval $(call SetupJavaCompilation,BUILD_NASGEN, \
-    SETUP := GENERATE_NEWBYTECODE_DEBUG, \
+    SETUP := GENERATE_OLDBYTECODE, \
     SRC := $(NASGEN_SRC) $(ASM_SRC), \
     BIN := $(NASHORN_OUTPUTDIR)/nasgen_classes, \
-    ADD_JAVAC_FLAGS := -cp $(NASHORN_OUTPUTDIR)/nashorn_classes))
+    ADD_JAVAC_FLAGS := -bootclasspath "$(BOOT_RTJAR)$(PATH_SEP)$(NASHORN_OUTPUTDIR)/nashorn_classes"))
 
 # Nasgen needs nashorn classes
 $(BUILD_NASGEN): $(BUILD_NASHORN)
--- a/nashorn/samples/BufferArray.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/samples/BufferArray.java	Fri Oct 03 12:10:58 2014 -0700
@@ -29,8 +29,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import java.nio.DoubleBuffer;
 import jdk.nashorn.api.scripting.AbstractJSObject;
-import java.nio.DoubleBuffer;
 
 /**
  * Simple class demonstrating pluggable script object
@@ -112,6 +112,8 @@
                       return true;
                   }
               };
+          default:
+              break;
        }
        return null;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java	Fri Oct 03 12:10:58 2014 -0700
@@ -27,7 +27,6 @@
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
 import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX;
-
 import java.lang.invoke.MethodType;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
@@ -35,7 +34,6 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.Expression;
@@ -131,7 +129,7 @@
         @SuppressWarnings("serial")
         final UnsupportedOperationException uoe = new UnsupportedOperationException() {
             @Override
-            public Throwable fillInStackTrace() {
+            public synchronized Throwable fillInStackTrace() {
                 return null;
             }
         };
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Fri Oct 03 12:10:58 2014 -0700
@@ -104,6 +104,7 @@
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.JoinPredecessor;
 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.JumpStatement;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LexicalContextNode;
@@ -1204,17 +1205,21 @@
 
     @Override
     public boolean enterBreakNode(final BreakNode breakNode) {
+        return enterJumpStatement(breakNode);
+    }
+
+    private boolean enterJumpStatement(final JumpStatement jump) {
         if(!method.isReachable()) {
             return false;
         }
-        enterStatement(breakNode);
-
-        method.beforeJoinPoint(breakNode);
-        final BreakableNode breakFrom = lc.getBreakable(breakNode.getLabelName());
-        popScopesUntil(breakFrom);
-        final Label breakLabel = breakFrom.getBreakLabel();
-        breakLabel.markAsBreakTarget();
-        method.splitAwareGoto(lc, breakLabel, breakFrom);
+        enterStatement(jump);
+
+        method.beforeJoinPoint(jump);
+        final BreakableNode target = jump.getTarget(lc);
+        popScopesUntil(target);
+        final Label targetLabel = jump.getTargetLabel(target);
+        targetLabel.markAsBreakTarget();
+        method.splitAwareGoto(lc, targetLabel, target);
 
         return false;
     }
@@ -1517,19 +1522,7 @@
 
     @Override
     public boolean enterContinueNode(final ContinueNode continueNode) {
-        if(!method.isReachable()) {
-            return false;
-        }
-        enterStatement(continueNode);
-        method.beforeJoinPoint(continueNode);
-
-        final LoopNode continueTo = lc.getContinueTo(continueNode.getLabelName());
-        popScopesUntil(continueTo);
-        final Label continueLabel = continueTo.getContinueLabel();
-        continueLabel.markAsBreakTarget();
-        method.splitAwareGoto(lc, continueLabel, continueTo);
-
-        return false;
+        return enterJumpStatement(continueNode);
     }
 
     @Override
@@ -2807,6 +2800,7 @@
         final boolean hasReturn = method.hasReturn();
         final SplitMethodEmitter splitMethod = ((SplitMethodEmitter)method);
         final List<Label> targets = splitMethod.getExternalTargets();
+        final boolean hasControlFlow = hasReturn || !targets.isEmpty();
         final List<BreakableNode> targetNodes  = splitMethod.getExternalTargetNodes();
         final Type returnType = lc.getCurrentFunction().getReturnType();
 
@@ -2814,6 +2808,9 @@
             // Wrap up this method.
 
             if(method.isReachable()) {
+                if (hasControlFlow) {
+                    method.setSplitState(-1);
+                }
                 method.loadCompilerConstant(RETURN, returnType);
                 method._return(returnType);
             }
@@ -2831,17 +2828,16 @@
             throw e;
         }
 
+        //no external jump targets or return in switch node
+        if (!hasControlFlow) {
+            return splitNode;
+        }
+
         // Handle return from split method if there was one.
         final MethodEmitter caller = method;
         final int     targetCount = targets.size();
 
-        //no external jump targets or return in switch node
-        if (!hasReturn && targets.isEmpty()) {
-            return splitNode;
-        }
-
-        caller.loadCompilerConstant(SCOPE);
-        caller.checkcast(Scope.class);
+        caller.loadScope();
         caller.invoke(Scope.GET_SPLIT_STATE);
 
         final Label breakLabel = new Label("no_split_state");
@@ -2873,19 +2869,16 @@
                     caller.loadCompilerConstant(RETURN, returnType);
                     caller._return(returnType);
                 } else {
-                    // Clear split state.
-                    caller.loadCompilerConstant(SCOPE);
-                    caller.checkcast(Scope.class);
-                    caller.load(-1);
-                    caller.invoke(Scope.SET_SPLIT_STATE);
                     final BreakableNode targetNode = targetNodes.get(i - 1);
                     final Label label = targets.get(i - 1);
-                    final JoinPredecessor jumpOrigin = splitNode.getJumpOrigin(label);
-                    if(jumpOrigin != null) {
-                        method.beforeJoinPoint(jumpOrigin);
+                    if (!lc.isExternalTarget(splitNode, targetNode)) {
+                        final JoinPredecessor jumpOrigin = splitNode.getJumpOrigin(label);
+                        if(jumpOrigin != null) {
+                            method.beforeJoinPoint(jumpOrigin);
+                        }
+                        popScopesUntil(targetNode);
                     }
-                    popScopesUntil(targetNode);
-                    caller.splitAwareGoto(lc, targets.get(i - 1), targetNode);
+                    caller.splitAwareGoto(lc, label, targetNode);
                 }
             }
             caller.label(breakLabel);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Fri Oct 03 12:10:58 2014 -0700
@@ -38,7 +38,6 @@
 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.ArrayList;
 import java.util.EnumSet;
@@ -48,7 +47,6 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-
 import jdk.nashorn.internal.AssertsEnabled;
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.ir.FunctionNode;
@@ -627,7 +625,7 @@
 
     /**
      * Start a compilation phase
-     * @param compiler
+     * @param compiler the compiler to use
      * @param functionNode function to compile
      * @return function node
      */
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Fri Oct 03 12:10:58 2014 -0700
@@ -32,7 +32,6 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
 import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
-
 import java.io.File;
 import java.lang.invoke.MethodType;
 import java.util.Arrays;
@@ -154,6 +153,13 @@
     private RecompilableScriptFunctionData compiledFunction;
 
     /**
+     * Most compile unit names are longer than the default StringBuilder buffer,
+     * worth startup performance when massive class generation is going on to increase
+     * this
+     */
+    private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32;
+
+    /**
      * Compilation phases that a compilation goes through
      */
     public static class CompilationPhases implements Iterable<CompilationPhase> {
@@ -631,7 +637,8 @@
     }
 
     String nextCompileUnitName() {
-        final StringBuilder sb = new StringBuilder(firstCompileUnitName);
+        final StringBuilder sb = new StringBuilder(COMPILE_UNIT_NAME_BUFFER_SIZE);
+        sb.append(firstCompileUnitName);
         final int cuid = nextCompileUnitId.getAndIncrement();
         if (cuid > 0) {
             sb.append("$cu").append(cuid);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Label.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Label.java	Fri Oct 03 12:10:58 2014 -0700
@@ -590,8 +590,13 @@
         return label.getOffset() > other.label.getOffset();
     }
 
+    private String str;
+
     @Override
     public String toString() {
-        return name + '_' + id;
+        if (str == null) {
+            str = name + '_' + id;
+        }
+        return str;
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Fri Oct 03 12:10:58 2014 -0700
@@ -464,21 +464,20 @@
 
     @Override
     public boolean enterBreakNode(final BreakNode breakNode) {
-        if(!reachable) {
-            return false;
-        }
-
-        final BreakableNode target = lc.getBreakable(breakNode.getLabelName());
-        return splitAwareJumpToLabel(breakNode, target, target.getBreakLabel());
+        return enterJumpStatement(breakNode);
     }
 
     @Override
     public boolean enterContinueNode(final ContinueNode continueNode) {
+        return enterJumpStatement(continueNode);
+    }
+
+    private boolean enterJumpStatement(final JumpStatement jump) {
         if(!reachable) {
             return false;
         }
-        final LoopNode target = lc.getContinueTo(continueNode.getLabelName());
-        return splitAwareJumpToLabel(continueNode, target, target.getContinueLabel());
+        final BreakableNode target = jump.getTarget(lc);
+        return splitAwareJumpToLabel(jump, target, jump.getTargetLabel(target));
     }
 
     private boolean splitAwareJumpToLabel(final JumpStatement jumpStatement, final BreakableNode target, final Label targetLabel) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Fri Oct 03 12:10:58 2014 -0700
@@ -52,6 +52,7 @@
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.JumpStatement;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
@@ -382,12 +383,16 @@
 
             @Override
             public Node leaveBreakNode(final BreakNode breakNode) {
-                return copy(breakNode, (Node)Lower.this.lc.getBreakable(breakNode.getLabelName()));
+                return leaveJumpStatement(breakNode);
             }
 
             @Override
             public Node leaveContinueNode(final ContinueNode continueNode) {
-                return copy(continueNode, Lower.this.lc.getContinueTo(continueNode.getLabelName()));
+                return leaveJumpStatement(continueNode);
+            }
+
+            private Node leaveJumpStatement(final JumpStatement jump) {
+                return copy(jump, (Node)jump.getTarget(Lower.this.lc));
             }
 
             @Override
@@ -627,7 +632,7 @@
             @Override
             public Node leaveContinueNode(final ContinueNode node) {
                 // all inner loops have been popped.
-                if (lex.contains(lex.getContinueTo(node.getLabelName()))) {
+                if (lex.contains(node.getTarget(lex))) {
                     escapes.add(node);
                 }
                 return node;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java	Fri Oct 03 12:10:58 2014 -0700
@@ -103,6 +103,7 @@
 import jdk.nashorn.internal.runtime.Debug;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.RewriteException;
+import jdk.nashorn.internal.runtime.Scope;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
@@ -1046,6 +1047,14 @@
         return load(getCompilerConstantSymbol(cc), type != null ? type : getCompilerConstantType(cc));
     }
 
+    MethodEmitter loadScope() {
+        return loadCompilerConstant(SCOPE).checkcast(Scope.class);
+    }
+
+    MethodEmitter setSplitState(final int state) {
+        return loadScope().load(state).invoke(Scope.SET_SPLIT_STATE);
+    }
+
     void storeCompilerConstant(final CompilerConstants cc) {
         storeCompilerConstant(cc, null);
     }
@@ -2134,6 +2143,8 @@
             load("Function");
             invoke(ScriptRuntime.INVALIDATE_RESERVED_BUILTIN_NAME);
             break;
+        default:
+            break;
         }
         return this;
     }
@@ -2574,12 +2585,55 @@
      *
      * @param args debug information to print
      */
+    @SuppressWarnings("unused")
     private void debug(final Object... args) {
         if (debug) {
             debug(30, args);
         }
     }
 
+    private void debug(final String arg) {
+        if (debug) {
+            debug(30, arg);
+        }
+    }
+
+    private void debug(final Object arg0, final Object arg1) {
+        if (debug) {
+            debug(30, new Object[] { arg0, arg1 });
+        }
+    }
+
+    private void debug(final Object arg0, final Object arg1, final Object arg2) {
+        if (debug) {
+            debug(30, new Object[] { arg0, arg1, arg2 });
+        }
+    }
+
+    private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3) {
+        if (debug) {
+            debug(30, new Object[] { arg0, arg1, arg2, arg3 });
+        }
+    }
+
+    private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4) {
+        if (debug) {
+            debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4 });
+        }
+    }
+
+    private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5) {
+        if (debug) {
+            debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5 });
+        }
+    }
+
+    private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5, final Object arg6) {
+        if (debug) {
+            debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 });
+        }
+    }
+
     /**
      * Debug function that outputs generated bytecode and stack contents
      * for a label - indentation is currently the only thing that differs
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java	Fri Oct 03 12:10:58 2014 -0700
@@ -443,7 +443,7 @@
                 // does not increase filesDeleted
             }
             files[i] = null; // gc eligible
-        };
+        }
     }
 
     private static Path[] getAllRegularFilesInLastModifiedOrder() throws IOException {
@@ -454,7 +454,7 @@
                 @Override
                 public boolean test(final Path path) {
                     return !Files.isDirectory(path);
-                };
+                }
             })
             .map(new Function<Path, PathAndTime>() {
                 @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitMethodEmitter.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitMethodEmitter.java	Fri Oct 03 12:10:58 2014 -0700
@@ -25,8 +25,6 @@
 
 package jdk.nashorn.internal.codegen;
 
-import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-
 import java.util.ArrayList;
 import java.util.List;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
@@ -34,7 +32,6 @@
 import jdk.nashorn.internal.ir.BreakableNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.SplitNode;
-import jdk.nashorn.internal.runtime.Scope;
 
 /**
  * Emitter used for splitting methods. Needs to keep track of if there are jump targets
@@ -65,15 +62,13 @@
         assert splitNode != null;
         final int index = findExternalTarget(lc, label, targetNode);
         if (index >= 0) {
-            loadCompilerConstant(SCOPE);
-            checkcast(Scope.class);
-            load(index + 1);
-            invoke(Scope.SET_SPLIT_STATE);
-            loadUndefined(Type.OBJECT);
-            _return(functionNode.getReturnType());
-            return;
+            setSplitState(index + 1); // 0 is ordinary return
+            final Type retType = functionNode.getReturnType();
+            loadUndefined(retType);
+            _return(retType);
+        } else {
+            super.splitAwareGoto(lc, label, targetNode);
         }
-        super.splitAwareGoto(lc, label, targetNode);
     }
 
     private int findExternalTarget(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
@@ -94,11 +89,7 @@
     @Override
     MethodEmitter registerReturn() {
         setHasReturn();
-        loadCompilerConstant(SCOPE);
-        checkcast(Scope.class);
-        load(0);
-        invoke(Scope.SET_SPLIT_STATE);
-        return this;
+        return setSplitState(0);
     }
 
     final List<Label> getExternalTargets() {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java	Fri Oct 03 12:10:58 2014 -0700
@@ -47,7 +47,6 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.T_INT;
 import static jdk.internal.org.objectweb.asm.Opcodes.T_LONG;
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
-
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
@@ -55,8 +54,10 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.util.Collections;
 import java.util.Map;
 import java.util.TreeMap;
+import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import jdk.internal.org.objectweb.asm.Handle;
@@ -104,6 +105,16 @@
     /** The class for this type */
     private final Class<?> clazz;
 
+    /**
+     * Cache for internal types - this is a query that requires complex stringbuilding inside
+     * ASM and it saves startup time to cache the type mappings
+     */
+    private static final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> INTERNAL_TYPE_CACHE =
+            Collections.synchronizedMap(new WeakHashMap<Class<?>, jdk.internal.org.objectweb.asm.Type>());
+
+    /** Internal ASM type for this Type - computed once at construction */
+    private final jdk.internal.org.objectweb.asm.Type internalType;
+
     /** Weights are used to decide which types are "wider" than other types */
     protected static final int MIN_WEIGHT = -1;
 
@@ -122,12 +133,13 @@
      * @param slots       how many bytecode slots the type takes up
      */
     Type(final String name, final Class<?> clazz, final int weight, final int slots) {
-        this.name       = name;
-        this.clazz      = clazz;
-        this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz);
-        this.weight     = weight;
+        this.name         = name;
+        this.clazz        = clazz;
+        this.descriptor   = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz);
+        this.weight       = weight;
         assert weight >= MIN_WEIGHT && weight <= MAX_WEIGHT : "illegal type weight: " + weight;
-        this.slots      = slots;
+        this.slots        = slots;
+        this.internalType = getInternalType(clazz);
     }
 
     /**
@@ -299,7 +311,7 @@
      *
      * @param typeMap the type map
      * @param output data output
-     * @throws IOException
+     * @throws IOException if write cannot be completed
      */
     public static void writeTypeMap(final Map<Integer, Type> typeMap, final DataOutput output) throws IOException {
         if (typeMap == null) {
@@ -329,7 +341,7 @@
      *
      * @param input data input
      * @return type map
-     * @throws IOException
+     * @throws IOException if read cannot be completed
      */
     public static Map<Integer, Type> readTypeMap(final DataInput input) throws IOException {
         final int size = input.readInt();
@@ -357,11 +369,22 @@
     }
 
     private jdk.internal.org.objectweb.asm.Type getInternalType() {
-        return jdk.internal.org.objectweb.asm.Type.getType(getTypeClass());
+        return internalType;
+    }
+
+    private static jdk.internal.org.objectweb.asm.Type lookupInternalType(final Class<?> type) {
+        final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> cache = INTERNAL_TYPE_CACHE;
+        jdk.internal.org.objectweb.asm.Type itype = cache.get(type);
+        if (itype != null) {
+            return itype;
+        }
+        itype = jdk.internal.org.objectweb.asm.Type.getType(type);
+        cache.put(type, itype);
+        return itype;
     }
 
     private static jdk.internal.org.objectweb.asm.Type getInternalType(final Class<?> type) {
-        return jdk.internal.org.objectweb.asm.Type.getType(type);
+        return lookupInternalType(type);
     }
 
     static void invokestatic(final MethodVisitor method, final Call call) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BreakNode.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BreakNode.java	Fri Oct 03 12:10:58 2014 -0700
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.ir;
 
+import jdk.nashorn.internal.codegen.Label;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -68,4 +69,14 @@
     String getStatementName() {
         return "break";
     }
+
+    @Override
+    public BreakableNode getTarget(final LexicalContext lc) {
+        return lc.getBreakable(getLabelName());
+    }
+
+    @Override
+    public Label getTargetLabel(final BreakableNode target) {
+        return target.getBreakLabel();
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ContinueNode.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ContinueNode.java	Fri Oct 03 12:10:58 2014 -0700
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.ir;
 
+import jdk.nashorn.internal.codegen.Label;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -67,5 +68,16 @@
     String getStatementName() {
         return "continue";
     }
+
+
+    @Override
+    public BreakableNode getTarget(final LexicalContext lc) {
+        return lc.getContinueTo(getLabelName());
+    }
+
+    @Override
+    public Label getTargetLabel(final BreakableNode target) {
+        return ((LoopNode)target).getContinueLabel();
+    }
 }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JumpStatement.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JumpStatement.java	Fri Oct 03 12:10:58 2014 -0700
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.ir;
 
+import jdk.nashorn.internal.codegen.Label;
+
 /**
  * Common base class for jump statements (e.g. {@code break} and {@code continue}).
  */
@@ -82,6 +84,24 @@
 
     abstract String getStatementName();
 
+    /**
+     * Finds the target for this jump statement in a lexical context.
+     * @param lc the lexical context
+     * @return the target, or null if not found
+     */
+    public abstract BreakableNode getTarget(final LexicalContext lc);
+
+    /**
+     * Returns the label corresponding to this kind of jump statement (either a break or continue label) in the target.
+     * @param target the target. Note that it need not be the target of this jump statement, as the method can retrieve
+     * a label on any passed target as long as the target has a label of the requisite kind. Of course, it is advisable
+     * to invoke the method on a jump statement that targets the breakable.
+     * @return the label of the target corresponding to the kind of jump statement.
+     * @throws ClassCastException if invoked on the kind of breakable node that this jump statement is not prepared to
+     * handle.
+     */
+    public abstract Label getTargetLabel(final BreakableNode target);
+
     @Override
     public JumpStatement setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
         if(this.conversion == conversion) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Fri Oct 03 12:10:58 2014 -0700
@@ -561,6 +561,7 @@
      *
      * @param engine ScriptEngine to initialize
      */
+    @SuppressWarnings("hiding")
     public void initBuiltinObjects(final ScriptEngine engine) {
         if (this.builtinObject != null) {
             // already initialized, just return
@@ -905,10 +906,12 @@
         }
 
         switch (nameStr) {
-            case "context":
-                return sctxt;
-            case "engine":
-                return global.engine;
+        case "context":
+            return sctxt;
+        case "engine":
+            return global.engine;
+        default:
+            break;
         }
 
         if (self == UNDEFINED) {
@@ -1715,6 +1718,7 @@
         return func;
     }
 
+    @SuppressWarnings("hiding")
     private void init(final ScriptEngine engine) {
         assert Context.getGlobal() == this : "this global is not set as current";
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Fri Oct 03 12:10:58 2014 -0700
@@ -1835,7 +1835,7 @@
             return false;
         }
 
-        private ContinuousArrayData getContinuousNonEmptyArrayData(final Object self) {
+        private static ContinuousArrayData getContinuousNonEmptyArrayData(final Object self) {
             final ContinuousArrayData data = getContinuousArrayData(self);
             if (data != null) {
                 return data.length() == 0 ? null : data;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDebug.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDebug.java	Fri Oct 03 12:10:58 2014 -0700
@@ -26,7 +26,6 @@
 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;
@@ -262,8 +261,8 @@
 
     /**
      * Set the event queue capacity
-     * @param self
-     * @param newCapacity
+     * @param self an event queue
+     * @param newCapacity new capacity
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static void setEventQueueCapacity(final Object self, final Object newCapacity) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java	Fri Oct 03 12:10:58 2014 -0700
@@ -77,7 +77,7 @@
             public boolean isEmpty() {
                 return true;
             }
-        };
+        }
 
         /**
          * Get the class representing the empty link logic
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java	Fri Oct 03 12:10:58 2014 -0700
@@ -30,7 +30,6 @@
 import static jdk.nashorn.internal.parser.TokenType.EOF;
 import static jdk.nashorn.internal.parser.TokenType.EOL;
 import static jdk.nashorn.internal.parser.TokenType.IDENT;
-
 import java.util.HashMap;
 import java.util.Map;
 import jdk.nashorn.internal.ir.IdentNode;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java	Fri Oct 03 12:10:58 2014 -0700
@@ -100,4 +100,21 @@
      * @return compiled script data
      */
     public StoredScript loadScript(Source source, String functionKey);
+
+    /**
+     * Returns a new code installer that shares most of the functionality of this code installer, but uses a
+     * new, independent class loader.
+     * @return a new code installer with a new independent class loader.
+     */
+    public CodeInstaller<T> withNewLoader();
+
+    /**
+     * Returns true if this code installer is compatible with the other code installer. Compatibility is expected to be
+     * an equivalence relation, and installers are supposed to be compatible with those they create using
+     * {@link #withNewLoader()}.
+     * @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);
+
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java	Fri Oct 03 12:10:58 2014 -0700
@@ -210,7 +210,7 @@
         /**
          * Constructor
          *
-         * @throws IOException
+         * @throws IOException if there are read/write problems with the cache and cache directory
          */
         public DirectoryCodeStore() throws IOException {
             this(Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"), false, DEFAULT_MIN_SIZE);
@@ -222,7 +222,7 @@
          * @param path    directory to store code in
          * @param readOnly is this a read only code store
          * @param minSize minimum file size for caching scripts
-         * @throws IOException
+         * @throws IOException if there are read/write problems with the cache and cache directory
          */
         public DirectoryCodeStore(final String path, final boolean readOnly, final int minSize) throws IOException {
             this.dir = checkDirectory(path, readOnly);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java	Fri Oct 03 12:10:58 2014 -0700
@@ -110,9 +110,8 @@
              */
             this.invoker = MH.insertArguments(invoker, invoker.type().parameterCount() - 1, UnwarrantedOptimismException.FIRST_PROGRAM_POINT);
             throw new AssertionError("Optimistic (UnwarrantedOptimismException throwing) builtin functions are currently not in use");
-        } else {
-            this.invoker = invoker;
         }
+        this.invoker = invoker;
         this.constructor = constructor;
         this.flags = flags;
         this.callSiteType = callSiteType;
@@ -510,8 +509,8 @@
         return ((ArrayType)paramTypes[paramTypes.length - 1]).getElementType();
     }
 
-    boolean matchesCallSite(final MethodType callSiteType, final boolean pickVarArg) {
-        if (callSiteType.equals(this.callSiteType)) {
+    boolean matchesCallSite(final MethodType other, final boolean pickVarArg) {
+        if (other.equals(this.callSiteType)) {
             return true;
         }
         final MethodType type  = type();
@@ -521,7 +520,7 @@
             return pickVarArg;
         }
 
-        final int csParamCount = getParamCount(callSiteType);
+        final int csParamCount = getParamCount(other);
         final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
         final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type
 
@@ -530,7 +529,7 @@
         // We must match all incoming parameters, except "this". Starting from 1 to skip "this".
         for(int i = 1; i < minParams; ++i) {
             final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
-            final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(callSiteType.parameterType(i + 1));
+            final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
             if(!fnType.isEquivalentTo(csType)) {
                 return false;
             }
@@ -752,9 +751,9 @@
         return sb.toString();
     }
 
-    private void logRecompile(final String reason, final FunctionNode fn, final MethodType callSiteType, final Map<Integer, Type> ipp) {
+    private void logRecompile(final String reason, final FunctionNode fn, final MethodType type, final Map<Integer, Type> ipp) {
         if (log.isEnabled()) {
-            log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", callSiteType, " ", toStringInvalidations(ipp));
+            log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type, " ", toStringInvalidations(ipp));
         }
     }
 
@@ -815,8 +814,6 @@
             compiler.persistClassInfo(cacheKey, normalFn);
         }
 
-        FunctionNode fn2 = effectiveOptInfo.reparse();
-        fn2 = compiler.compile(fn2, CompilationPhases.COMPILE_UPTO_BYTECODE);
         log.info("Done.");
 
         final boolean canBeDeoptimized = normalFn.canBeDeoptimized();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Fri Oct 03 12:10:58 2014 -0700
@@ -64,9 +64,7 @@
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.logging.Level;
-
 import javax.script.ScriptEngine;
-
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
 import jdk.nashorn.api.scripting.ClassFilter;
@@ -161,7 +159,7 @@
         }
 
         /**
-         * Return the context for this installer
+         * Return the script environment for this installer
          * @return ScriptEnvironment
          */
         @Override
@@ -225,6 +223,20 @@
             }
             return null;
         }
+
+        @Override
+        public CodeInstaller<ScriptEnvironment> withNewLoader() {
+            return new ContextCodeInstaller(context, context.createNewLoader(), codeSource);
+        }
+
+        @Override
+        public boolean isCompatibleWith(final CodeInstaller<ScriptEnvironment> other) {
+            if (other instanceof ContextCodeInstaller) {
+                final ContextCodeInstaller cci = (ContextCodeInstaller)other;
+                return cci.context == context && cci.codeSource == codeSource;
+            }
+            return false;
+        }
     }
 
     /** Is Context global debug mode enabled ? */
@@ -1390,7 +1402,7 @@
      * logic to e.g. multiple switchpoint classes.
      */
     public static final class BuiltinSwitchPoint extends SwitchPoint {
-
+        //empty
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Debug.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Debug.java	Fri Oct 03 12:10:58 2014 -0700
@@ -26,7 +26,6 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.parser.TokenType.EOF;
-
 import jdk.nashorn.internal.parser.Lexer;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenStream;
@@ -42,12 +41,12 @@
 
     /**
      * Return the topmost JavaScript frame in a stack trace
-     * @param e
+     * @param t throwable that contains the stack trace
      * @return line describing the topmost JavaScript frame
      */
-    public static String firstJSFrame(final Throwable e) {
-        for (final StackTraceElement ste : e.getStackTrace()) {
-            if(ECMAErrors.isScriptFrame(ste)) {
+    public static String firstJSFrame(final Throwable t) {
+        for (final StackTraceElement ste : t.getStackTrace()) {
+            if (ECMAErrors.isScriptFrame(ste)) {
                 return ste.toString();
             }
         }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -26,6 +26,7 @@
 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;
@@ -268,7 +269,7 @@
         if (this.source == null && this.installer == null) {
             this.source    = src;
             this.installer = inst;
-        } else if (this.source != src || this.installer != inst) {
+        } else if (this.source != src || !this.installer.isCompatibleWith(inst)) {
             // Existing values must be same as those passed as parameters
             throw new IllegalArgumentException();
         }
@@ -407,6 +408,17 @@
         return getCompiler(fn, actualCallSiteType, newLocals(runtimeScope), null, null);
     }
 
+    /**
+     * Returns a code installer for installing new code. If we're using either optimistic typing or loader-per-compile,
+     * then asks for a code installer with a new class loader; otherwise just uses the current installer. We use
+     * 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();
+        return env._optimistic_types || env._loader_per_compile ? installer.withNewLoader() : installer;
+    }
+
     Compiler getCompiler(final FunctionNode functionNode, final MethodType actualCallSiteType,
             final ScriptObject runtimeScope, final Map<Integer, Type> invalidatedProgramPoints,
             final int[] continuationEntryPoints) {
@@ -417,7 +429,7 @@
         return new Compiler(
                 context,
                 context.getEnv(),
-                installer,
+                getInstallerForNewCode(),
                 functionNode.getSource(),  // source
                 context.getErrorManager(),
                 isStrict() | functionNode.isStrict(), // is strict
@@ -463,11 +475,12 @@
             final TypeMap typeMap = typeMap(actualCallSiteType);
             final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
             cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes);
-            final StoredScript script = installer.loadScript(source, cacheKey);
+            final CodeInstaller<ScriptEnvironment> newInstaller = getInstallerForNewCode();
+            final StoredScript script = newInstaller.loadScript(source, cacheKey);
 
             if (script != null) {
                 Compiler.updateCompilationId(script.getCompilationId());
-                return install(script);
+                return installStoredScript(script, newInstaller);
             }
         }
 
@@ -481,15 +494,7 @@
         return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
     }
 
-
-    /**
-     * Install this script using the given {@code installer}.
-     *
-     * @param script the compiled script
-     * @return the function initializer
-     */
-    private FunctionInitializer install(final StoredScript script) {
-
+    private static Map<String, Class<?>> installStoredScriptClasses(final StoredScript script, final CodeInstaller<ScriptEnvironment> installer) {
         final Map<String, Class<?>> installedClasses = new HashMap<>();
         final Map<String, byte[]>   classBytes       = script.getClassBytes();
         final String   mainClassName   = script.getMainClassName();
@@ -501,14 +506,25 @@
 
         for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
             final String className = entry.getKey();
-            final byte[] code = entry.getValue();
+            final byte[] bytecode = entry.getValue();
 
             if (className.equals(mainClassName)) {
                 continue;
             }
 
-            installedClasses.put(className, installer.install(className, code));
+            installedClasses.put(className, installer.install(className, bytecode));
         }
+        return installedClasses;
+    }
+
+    /**
+     * Install this script using the given {@code installer}.
+     *
+     * @param script the compiled script
+     * @return the function initializer
+     */
+    private FunctionInitializer installStoredScript(final StoredScript script, final CodeInstaller<ScriptEnvironment> newInstaller) {
+        final Map<String, Class<?>> installedClasses = installStoredScriptClasses(script, newInstaller);
 
         final Map<Integer, FunctionInitializer> initializers = script.getInitializers();
         assert initializers != null;
@@ -523,7 +539,7 @@
             }
         }
 
-        installer.initialize(installedClasses.values(), source, constants);
+        newInstaller.initialize(installedClasses.values(), source, constants);
         initializer.setCode(installedClasses.get(initializer.getClassName()));
         return initializer;
     }
@@ -588,9 +604,11 @@
         return lookupCodeMethod(fn.getCompileUnit().getCode(), type);
     }
 
-    MethodHandle lookupCodeMethod(final Class<?> code, final MethodType targetType) {
-        log.info("Looking up ", DebugLogger.quote(name), " type=", targetType);
-        return MH.findStatic(LOOKUP, code, functionName, targetType);
+    MethodHandle lookupCodeMethod(final Class<?> codeClass, final MethodType targetType) {
+        if (log.isEnabled()) {
+            log.info("Looking up ", DebugLogger.quote(name), " type=", targetType);
+        }
+        return MH.findStatic(LOOKUP, codeClass, functionName, targetType);
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java	Fri Oct 03 12:10:58 2014 -0700
@@ -501,7 +501,7 @@
      * @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 LinkLogic getLinkLogic(final Object self, final Class<? extends LinkLogic> linkLogicClass) {
+    private static LinkLogic getLinkLogic(final Object self, final Class<? extends LinkLogic> linkLogicClass) {
         if (linkLogicClass == null) {
             return LinkLogic.EMPTY_INSTANCE; //always OK to link this, specialization but without special linking logic
         }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Oct 03 12:10:58 2014 -0700
@@ -935,10 +935,10 @@
      * creating setters that probably aren't used. Inject directly into the spill pool
      * the defaults for "arguments" and "caller"
      *
-     * @param key
-     * @param propertyFlags
-     * @param getter
-     * @param setter
+     * @param key           property key
+     * @param propertyFlags flags
+     * @param getter        getter for {@link UserAccessorProperty}, null if not present or N/A
+     * @param setter        setter for {@link UserAccessorProperty}, null if not present or N/A
      */
     protected final void initUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
         final int slot = spillLength;
@@ -1749,8 +1749,8 @@
      */
     public Object put(final Object key, final Object value, final boolean strict) {
         final Object oldValue = get(key);
-        final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
-        set(key, value, flags);
+        final int scriptObjectFlags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
+        set(key, value, scriptObjectFlags);
         return oldValue;
     }
 
@@ -1763,9 +1763,9 @@
      * @param strict strict mode or not
      */
     public void putAll(final Map<?, ?> otherMap, final boolean strict) {
-        final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
+        final int scriptObjectFlags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
         for (final Map.Entry<?, ?> entry : otherMap.entrySet()) {
-            set(entry.getKey(), entry.getValue(), flags);
+            set(entry.getKey(), entry.getValue(), scriptObjectFlags);
         }
     }
 
@@ -2046,7 +2046,7 @@
     // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST
     @SuppressWarnings("unused")
     private void declareAndSet(final String key, final Object value) {
-        final PropertyMap map = getMap();
+        final PropertyMap oldMap = getMap();
         final FindProperty find = findProperty(key, false);
         assert find != null;
 
@@ -2054,7 +2054,7 @@
         assert property != null;
         assert property.needsDeclaration();
 
-        final PropertyMap newMap = map.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION));
+        final PropertyMap newMap = oldMap.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION));
         setMap(newMap);
         set(key, value, 0);
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -536,7 +536,7 @@
         final Class<?>  widest  = widestType(items);
 
         ArrayData newData = convert(widest);
-        long      pos     = newData.length();
+        long      pos     = newData.length;
         for (final Object item : items) {
             newData = newData.ensure(pos); //avoid sparse array
             newData.set((int)pos++, item, strict);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java	Fri Oct 03 12:10:58 2014 -0700
@@ -39,7 +39,7 @@
     protected ArrayData underlying;
 
     ArrayFilter(final ArrayData underlying) {
-        super(underlying.length());
+        super(underlying.length);
         this.underlying = underlying;
     }
 
@@ -70,13 +70,13 @@
     @Override
     public void shiftLeft(final int by) {
         underlying.shiftLeft(by);
-        setLength(underlying.length());
+        setLength(underlying.length);
     }
 
     @Override
     public ArrayData shiftRight(final int by) {
         underlying = underlying.shiftRight(by);
-        setLength(underlying.length());
+        setLength(underlying.length);
 
         return this;
     }
@@ -84,7 +84,7 @@
     @Override
     public ArrayData ensure(final long safeIndex) {
         underlying = underlying.ensure(safeIndex);
-        setLength(underlying.length());
+        setLength(underlying.length);
 
         return this;
     }
@@ -92,7 +92,7 @@
     @Override
     public ArrayData shrink(final long newLength) {
         underlying = underlying.shrink(newLength);
-        setLength(underlying.length());
+        setLength(underlying.length);
 
         return this;
     }
@@ -100,7 +100,7 @@
     @Override
     public ArrayData set(final int index, final Object value, final boolean strict) {
         underlying = underlying.set(index, value, strict);
-        setLength(underlying.length());
+        setLength(underlying.length);
 
         return this;
     }
@@ -108,7 +108,7 @@
     @Override
     public ArrayData set(final int index, final int value, final boolean strict) {
         underlying = underlying.set(index, value, strict);
-        setLength(underlying.length());
+        setLength(underlying.length);
 
         return this;
     }
@@ -116,7 +116,7 @@
     @Override
     public ArrayData set(final int index, final long value, final boolean strict) {
         underlying = underlying.set(index, value, strict);
-        setLength(underlying.length());
+        setLength(underlying.length);
 
         return this;
     }
@@ -124,7 +124,7 @@
     @Override
     public ArrayData set(final int index, final double value, final boolean strict) {
         underlying = underlying.set(index, value, strict);
-        setLength(underlying.length());
+        setLength(underlying.length);
 
         return this;
     }
@@ -189,28 +189,28 @@
     @Override
     public ArrayData delete(final int index) {
         underlying = underlying.delete(index);
-        setLength(underlying.length());
+        setLength(underlying.length);
         return this;
     }
 
     @Override
     public ArrayData delete(final long from, final long to) {
         underlying = underlying.delete(from, to);
-        setLength(underlying.length());
+        setLength(underlying.length);
         return this;
     }
 
     @Override
     public ArrayData convert(final Class<?> type) {
         underlying = underlying.convert(type);
-        setLength(underlying.length());
+        setLength(underlying.length);
         return this;
     }
 
     @Override
     public Object pop() {
         final Object value = underlying.pop();
-        setLength(underlying.length());
+        setLength(underlying.length);
 
         return value;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -76,11 +76,11 @@
      * array without reallocating, or if we are overwriting an already
      * allocated element
      *
-     * @param index
+     * @param index index to check
      * @return true if we don't need to do any array reallocation to fit an element at index
      */
     public final boolean hasRoomFor(final int index) {
-        return has(index) || (index == length() && ensure(index) == this);
+        return has(index) || (index == length && ensure(index) == this);
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java	Fri Oct 03 12:10:58 2014 -0700
@@ -26,7 +26,6 @@
 package jdk.nashorn.internal.runtime.arrays;
 
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
 import java.lang.reflect.Array;
 import jdk.nashorn.internal.runtime.BitVector;
 
@@ -40,7 +39,7 @@
     DeletedArrayFilter(final ArrayData underlying) {
         super(underlying);
 
-        this.deleted = new BitVector(underlying.length());
+        this.deleted = new BitVector(underlying.length);
     }
 
     @Override
@@ -80,25 +79,25 @@
     @Override
     public void shiftLeft(final int by) {
         super.shiftLeft(by);
-        deleted.shiftLeft(by, length());
+        deleted.shiftLeft(by, length);
     }
 
     @Override
     public ArrayData shiftRight(final int by) {
         super.shiftRight(by);
-        deleted.shiftRight(by, length());
+        deleted.shiftRight(by, length);
 
         return this;
     }
 
     @Override
     public ArrayData ensure(final long safeIndex) {
-        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
+        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) {
             return new SparseArrayData(this, safeIndex + 1);
         }
 
         super.ensure(safeIndex);
-        deleted.resize(length());
+        deleted.resize(length);
 
         return this;
     }
@@ -106,7 +105,7 @@
     @Override
     public ArrayData shrink(final long newLength) {
         super.shrink(newLength);
-        deleted.resize(length());
+        deleted.resize(length);
 
         return this;
     }
@@ -147,7 +146,7 @@
     @Override
     public ArrayData delete(final int index) {
         final long longIndex = ArrayIndex.toLongIndex(index);
-        assert longIndex >= 0 && longIndex < length();
+        assert longIndex >= 0 && longIndex < length;
         deleted.set(longIndex);
         underlying.setEmpty(index);
         return this;
@@ -155,7 +154,7 @@
 
     @Override
     public ArrayData delete(final long fromIndex, final long toIndex) {
-        assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length();
+        assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length;
         deleted.setRange(fromIndex, toIndex + 1);
         underlying.setEmpty(fromIndex, toIndex);
         return this;
@@ -163,7 +162,7 @@
 
     @Override
     public Object pop() {
-        final long index = length() - 1;
+        final long index = length - 1;
 
         if (super.has((int)index)) {
             final boolean isDeleted = deleted.isSet(index);
@@ -180,7 +179,7 @@
         final ArrayData newArray = underlying.slice(from, to);
         final DeletedArrayFilter newFilter = new DeletedArrayFilter(newArray);
         newFilter.getDeleted().copy(deleted);
-        newFilter.getDeleted().shiftLeft(from, newFilter.length());
+        newFilter.getDeleted().shiftLeft(from, newFilter.length);
 
         return newFilter;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java	Fri Oct 03 12:10:58 2014 -0700
@@ -45,7 +45,7 @@
         if(hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) {
             return underlying;
         }
-        return new SparseArrayData(underlying, underlying.length());
+        return new SparseArrayData(underlying, underlying.length);
     }
 
     private boolean isEmpty() {
@@ -93,7 +93,7 @@
 
     @Override
     public ArrayData ensure(final long safeIndex) {
-        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
+        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) {
             return new SparseArrayData(this, safeIndex + 1);
         }
 
@@ -110,8 +110,9 @@
     @Override
     public ArrayData shiftRight(final int by) {
         super.shiftRight(by);
-        lo = Math.min(length(), lo + by);
-        hi = Math.min(length() - 1, hi + by);
+        final long len = length;
+        lo = Math.min(len, lo + by);
+        hi = Math.min(len - 1, hi + by);
 
         return isEmpty() ? getUnderlying() : this;
     }
@@ -237,7 +238,7 @@
 
     @Override
     public Object pop() {
-        final int index = (int)(length() - 1);
+        final int index = (int)length - 1;
         if (super.has(index)) {
             final boolean isDeleted = isDeleted(index);
             final Object value      = super.pop();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -105,13 +105,13 @@
 
     @Override
     public ArrayData copy() {
-        return new IntArrayData(array.clone(), (int) length());
+        return new IntArrayData(array.clone(), (int)length);
     }
 
     @Override
     public Object asArrayOfType(final Class<?> componentType) {
         if (componentType == int.class) {
-            return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length());
+            return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length);
         }
         return super.asArrayOfType(componentType);
     }
@@ -183,7 +183,7 @@
 
     @Override
     public ArrayData shiftRight(final int by) {
-        final ArrayData newData = ensure(by + length() - 1);
+        final ArrayData newData = ensure(by + length - 1);
         if (newData != this) {
             newData.shiftRight(by);
             return newData;
@@ -229,7 +229,7 @@
     @Override
     public ArrayData set(final int index, final int value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
 
         return this;
     }
@@ -238,7 +238,7 @@
     public ArrayData set(final int index, final long value, final boolean strict) {
         if (JSType.isRepresentableAsInt(value)) {
             array[index] = JSType.toInt32(value);
-            setLength(Math.max(index + 1, length()));
+            setLength(Math.max(index + 1, length));
             return this;
         }
 
@@ -249,7 +249,7 @@
     public ArrayData set(final int index, final double value, final boolean strict) {
         if (JSType.isRepresentableAsInt(value)) {
             array[index] = (int)(long)value;
-            setLength(Math.max(index + 1, length()));
+            setLength(Math.max(index + 1, length));
             return this;
         }
 
@@ -298,7 +298,7 @@
 
     @Override
     public boolean has(final int index) {
-        return 0 <= index && index < length();
+        return 0 <= index && index < length;
     }
 
     @Override
@@ -313,11 +313,11 @@
 
     @Override
     public Object pop() {
-        if (length() == 0) {
+        if (length == 0) {
             return ScriptRuntime.UNDEFINED;
         }
 
-        final int newLength = (int) length() - 1;
+        final int newLength = (int)length - 1;
         final int elem = array[newLength];
         array[newLength] = 0;
         setLength(newLength);
@@ -327,7 +327,7 @@
 
     @Override
     public ArrayData slice(final long from, final long to) {
-        final long start     = from < 0 ? from + length() : from;
+        final long start     = from < 0 ? from + length : from;
         final long newLength = to - start;
 
         return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
@@ -335,18 +335,18 @@
 
     @Override
     public final ArrayData push(final boolean strict, final int item) {
-        final long      length = length();
-        final ArrayData newData = ensure(length);
+        final long      len     = length;
+        final ArrayData newData = ensure(len);
         if (newData == this) {
-            array[(int)length] = item;
+            array[(int)len] = item;
             return this;
         }
-        return newData.set((int)length, item, strict);
+        return newData.set((int)len, item, strict);
     }
 
     @Override
     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
-        final long oldLength = length();
+        final long oldLength = length;
         final long newLength = oldLength - removed + added;
         if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
             throw new UnsupportedOperationException();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -62,12 +62,12 @@
 
     @Override
     public ArrayData copy() {
-        return new LongArrayData(array.clone(), (int)length());
+        return new LongArrayData(array.clone(), (int)length);
     }
 
     @Override
     public Object[] asObjectArray() {
-        return toObjectArray(array, (int)length());
+        return toObjectArray(array, (int)length);
     }
 
     private static Object[] toObjectArray(final long[] array, final int length) {
@@ -84,7 +84,7 @@
     @Override
     public Object asArrayOfType(final Class<?> componentType) {
         if (componentType == long.class) {
-            return array.length == length() ? array.clone() : Arrays.copyOf(array, (int)length());
+            return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length);
         }
         return super.asArrayOfType(componentType);
     }
@@ -105,11 +105,11 @@
         if (type == Integer.class || type == Long.class) {
             return this;
         }
-        final int length = (int) length();
+        final int len = (int)length;
         if (type == Double.class) {
-            return new NumberArrayData(LongArrayData.toDoubleArray(array, length), length);
+            return new NumberArrayData(LongArrayData.toDoubleArray(array, len), len);
         }
-        return new ObjectArrayData(LongArrayData.toObjectArray(array, length), length);
+        return new ObjectArrayData(LongArrayData.toObjectArray(array, len), len);
     }
 
     @Override
@@ -119,7 +119,7 @@
 
     @Override
     public ArrayData shiftRight(final int by) {
-        final ArrayData newData = ensure(by + length() - 1);
+        final ArrayData newData = ensure(by + length - 1);
         if (newData != this) {
             newData.shiftRight(by);
             return newData;
@@ -165,14 +165,14 @@
     @Override
     public ArrayData set(final int index, final int value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
         return this;
     }
 
     @Override
     public ArrayData set(final int index, final long value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
         return this;
     }
 
@@ -180,7 +180,7 @@
     public ArrayData set(final int index, final double value, final boolean strict) {
         if (JSType.isRepresentableAsLong(value)) {
             array[index] = (long)value;
-            setLength(Math.max(index + 1, length()));
+            setLength(Math.max(index + 1, length));
             return this;
         }
         return convert(Double.class).set(index, value, strict);
@@ -256,7 +256,7 @@
 
     @Override
     public boolean has(final int index) {
-        return 0 <= index && index < length();
+        return 0 <= index && index < length;
     }
 
     @Override
@@ -271,11 +271,11 @@
 
     @Override
     public Object pop() {
-        if (length() == 0) {
+        if (length == 0) {
             return ScriptRuntime.UNDEFINED;
         }
 
-        final int newLength = (int) (length() - 1);
+        final int newLength = (int)length - 1;
         final long elem = array[newLength];
         array[newLength] = 0;
         setLength(newLength);
@@ -285,25 +285,25 @@
 
     @Override
     public ArrayData slice(final long from, final long to) {
-        final long start     = from < 0 ? from + length() : from;
+        final long start     = from < 0 ? from + length : from;
         final long newLength = to - start;
         return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
     }
 
     @Override
     public final ArrayData push(final boolean strict, final long item) {
-        final long      length = length();
-        final ArrayData newData = ensure(length);
+        final long      len     = length;
+        final ArrayData newData = ensure(len);
         if (newData == this) {
-            array[(int)length] = item;
+            array[(int)len] = item;
             return this;
         }
-        return newData.set((int)length, item, strict);
+        return newData.set((int)len, item, strict);
     }
 
     @Override
     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
-        final long oldLength = length();
+        final long oldLength = length;
         final long newLength = oldLength - removed + added;
         if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
             throw new UnsupportedOperationException();
@@ -353,7 +353,6 @@
         final long elem = array[newLength];
         array[newLength] = 0;
         return elem;
-        //return array[(int)--length];
     }
 
     @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -58,19 +58,19 @@
 
     @Override
     public ArrayData convert(final Class<?> type) {
-        final long length = length();
+        final long len = length;
         final ArrayData arrayData;
         if (type == Long.class) {
-            arrayData = new LongArrayData(new long[ArrayData.nextSize((int)length)], (int)length);
+            arrayData = new LongArrayData(new long[ArrayData.nextSize((int)len)], (int)len);
         } else if (type == Double.class) {
-            arrayData = new NumberArrayData(new double[ArrayData.nextSize((int)length)], (int)length);
+            arrayData = new NumberArrayData(new double[ArrayData.nextSize((int)len)], (int)len);
         } else if (type == Integer.class) {
-            arrayData = new IntArrayData(new int[ArrayData.nextSize((int)length)], (int)length);
+            arrayData = new IntArrayData(new int[ArrayData.nextSize((int)len)], (int)len);
         } else {
             assert !type.isPrimitive();
-            arrayData = new ObjectArrayData(new Object[ArrayData.nextSize((int)length)], (int)length);
+            arrayData = new ObjectArrayData(new Object[ArrayData.nextSize((int)len)], (int)len);
         }
-        return length == 0 ? arrayData : new DeletedRangeArrayFilter(arrayData, 0, length - 1);
+        return length == 0 ? arrayData : new DeletedRangeArrayFilter(arrayData, 0, len - 1);
     }
 
     @Override
@@ -90,11 +90,11 @@
         }
 
         // Don't trample the shared EMPTY_ARRAY.
-        if (length() == 0) {
-            return new NoTypeArrayData(Math.max(safeIndex + 1, length()));
+        if (length == 0) {
+            return new NoTypeArrayData(Math.max(safeIndex + 1, length));
         }
 
-        setLength(Math.max(safeIndex + 1, length()));
+        setLength(Math.max(safeIndex + 1, length));
         return this;
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -61,12 +61,12 @@
 
     @Override
     public ArrayData copy() {
-        return new NumberArrayData(array.clone(), (int) length());
+        return new NumberArrayData(array.clone(), (int)length);
     }
 
     @Override
     public Object[] asObjectArray() {
-        return toObjectArray(array, (int) length());
+        return toObjectArray(array, (int)length);
     }
 
     private static Object[] toObjectArray(final double[] array, final int length) {
@@ -82,7 +82,7 @@
     @Override
     public Object asArrayOfType(final Class<?> componentType) {
         if(componentType == double.class) {
-            return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length());
+            return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length);
         }
         return super.asArrayOfType(componentType);
     }
@@ -90,8 +90,8 @@
     @Override
     public ArrayData convert(final Class<?> type) {
         if (type != Double.class && type != Integer.class && type != Long.class) {
-            final int length = (int) length();
-            return new ObjectArrayData(NumberArrayData.toObjectArray(array, length), length);
+            final int len = (int)length;
+            return new ObjectArrayData(NumberArrayData.toObjectArray(array, len), len);
         }
         return this;
     }
@@ -103,7 +103,7 @@
 
     @Override
     public ArrayData shiftRight(final int by) {
-        final ArrayData newData = ensure(by + length() - 1);
+        final ArrayData newData = ensure(by + length - 1);
         if (newData != this) {
             newData.shiftRight(by);
             return newData;
@@ -148,21 +148,21 @@
     @Override
     public ArrayData set(final int index, final int value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
         return this;
     }
 
     @Override
     public ArrayData set(final int index, final long value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
         return this;
     }
 
     @Override
     public ArrayData set(final int index, final double value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
         return this;
     }
 
@@ -231,7 +231,7 @@
 
     @Override
     public boolean has(final int index) {
-        return 0 <= index && index < length();
+        return 0 <= index && index < length;
     }
 
     @Override
@@ -246,11 +246,11 @@
 
     @Override
     public Object pop() {
-        if (length() == 0) {
+        if (length == 0) {
             return UNDEFINED;
         }
 
-        final int newLength = (int) (length() - 1);
+        final int newLength = (int)length - 1;
         final double elem = array[newLength];
         array[newLength] = 0;
         setLength(newLength);
@@ -259,25 +259,25 @@
 
     @Override
     public ArrayData slice(final long from, final long to) {
-        final long start     = from < 0 ? from + length() : from;
+        final long start     = from < 0 ? from + length : from;
         final long newLength = to - start;
         return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
     }
 
     @Override
     public final ArrayData push(final boolean strict, final double item) {
-        final long      length = length();
-        final ArrayData newData = ensure(length);
+        final long      len     = length;
+        final ArrayData newData = ensure(len);
         if (newData == this) {
-            array[(int)length] = item;
+            array[(int)len] = item;
             return this;
         }
-        return newData.set((int)length, item, strict);
+        return newData.set((int)len, item, strict);
     }
 
     @Override
     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
-        final long oldLength = length();
+        final long oldLength = length;
         final long newLength = oldLength - removed + added;
         if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
             throw new UnsupportedOperationException();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -67,14 +67,14 @@
 
     @Override
     public Object[] asObjectArray() {
-        return array.length == length() ? array.clone() : asObjectArrayCopy();
+        return array.length == length ? array.clone() : asObjectArrayCopy();
     }
 
     private Object[] asObjectArrayCopy() {
-        final long l = length();
-        assert l <= Integer.MAX_VALUE;
-        final Object[] copy = new Object[(int)l];
-        System.arraycopy(array, 0, copy, 0, (int)l);
+        final long len = length;
+        assert len <= Integer.MAX_VALUE;
+        final Object[] copy = new Object[(int)len];
+        System.arraycopy(array, 0, copy, 0, (int)len);
         return copy;
     }
 
@@ -90,7 +90,7 @@
 
     @Override
     public ArrayData shiftRight(final int by) {
-        final ArrayData newData = ensure(by + length() - 1);
+        final ArrayData newData = ensure(by + length - 1);
         if (newData != this) {
             newData.shiftRight(by);
             return newData;
@@ -122,28 +122,28 @@
     @Override
     public ArrayData set(final int index, final Object value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
         return this;
     }
 
     @Override
     public ArrayData set(final int index, final int value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
         return this;
     }
 
     @Override
     public ArrayData set(final int index, final long value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
         return this;
     }
 
     @Override
     public ArrayData set(final int index, final double value, final boolean strict) {
         array[index] = value;
-        setLength(Math.max(index + 1, length()));
+        setLength(Math.max(index + 1, length));
         return this;
     }
 
@@ -220,7 +220,7 @@
 
     @Override
     public boolean has(final int index) {
-        return 0 <= index && index < length();
+        return 0 <= index && index < length;
     }
 
     @Override
@@ -273,11 +273,11 @@
 
     @Override
     public Object pop() {
-        if (length() == 0) {
+        if (length == 0) {
             return ScriptRuntime.UNDEFINED;
         }
 
-        final int newLength = (int) (length() - 1);
+        final int newLength = (int)length - 1;
         final Object elem = array[newLength];
         setEmpty(newLength);
         setLength(newLength);
@@ -286,25 +286,25 @@
 
     @Override
     public ArrayData slice(final long from, final long to) {
-        final long start     = from < 0 ? from + length() : from;
+        final long start     = from < 0 ? from + length : from;
         final long newLength = to - start;
         return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
     }
 
     @Override
     public ArrayData push(final boolean strict, final Object item) {
-        final long      length = length();
-        final ArrayData newData = ensure(length);
+        final long      len     = length;
+        final ArrayData newData = ensure(len);
         if (newData == this) {
-            array[(int)length] = item;
+            array[(int)len] = item;
             return this;
         }
-        return newData.set((int)length, item, strict);
+        return newData.set((int)len, item, strict);
     }
 
     @Override
     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
-        final long oldLength = length();
+        final long oldLength = length;
         final long newLength = oldLength - removed + added;
         if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
             throw new UnsupportedOperationException();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -53,28 +53,28 @@
 
     SparseArrayData(final ArrayData underlying, final long length, final TreeMap<Long, Object> sparseMap) {
         super(length);
-        assert underlying.length() <= length;
+        assert underlying.length <= length;
         this.underlying = underlying;
-        this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length());
+        this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length);
         this.sparseMap = sparseMap;
     }
 
     @Override
     public ArrayData copy() {
-        return new SparseArrayData(underlying.copy(), length(), new TreeMap<>(sparseMap));
+        return new SparseArrayData(underlying.copy(), length, new TreeMap<>(sparseMap));
     }
 
     @Override
     public Object[] asObjectArray() {
-        final int length = (int) Math.min(length(), Integer.MAX_VALUE);
-        final int underlyingLength = (int) Math.min(length, underlying.length());
-        final Object[] objArray = new Object[length];
+        final int len = (int)Math.min(length, Integer.MAX_VALUE);
+        final int underlyingLength = (int)Math.min(len, underlying.length);
+        final Object[] objArray = new Object[len];
 
         for (int i = 0; i < underlyingLength; i++) {
             objArray[i] = underlying.getObject(i);
         }
 
-        Arrays.fill(objArray, underlyingLength, length, ScriptRuntime.UNDEFINED);
+        Arrays.fill(objArray, underlyingLength, len, ScriptRuntime.UNDEFINED);
 
         for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
             final long key = entry.getKey();
@@ -104,14 +104,14 @@
         }
 
         sparseMap = newSparseMap;
-        setLength(Math.max(length() - by, 0));
+        setLength(Math.max(length - by, 0));
     }
 
     @Override
     public ArrayData shiftRight(final int by) {
         final TreeMap<Long, Object> newSparseMap = new TreeMap<>();
-        if (underlying.length() + by > maxDenseLength) {
-            for (long i = maxDenseLength - by; i < underlying.length(); i++) {
+        if (underlying.length + by > maxDenseLength) {
+            for (long i = maxDenseLength - by; i < underlying.length; i++) {
                 if (underlying.has((int) i)) {
                     newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i));
                 }
@@ -127,23 +127,23 @@
         }
 
         sparseMap = newSparseMap;
-        setLength(length() + by);
+        setLength(length + by);
 
         return this;
     }
 
     @Override
     public ArrayData ensure(final long safeIndex) {
-        if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) {
+        if (safeIndex < maxDenseLength && underlying.length <= safeIndex) {
             underlying = underlying.ensure(safeIndex);
         }
-        setLength(Math.max(safeIndex + 1, length()));
+        setLength(Math.max(safeIndex + 1, length));
         return this;
     }
 
     @Override
     public ArrayData shrink(final long newLength) {
-        if (newLength < underlying.length()) {
+        if (newLength < underlying.length) {
             underlying = underlying.shrink(newLength);
             underlying.setLength(newLength);
             sparseMap.clear();
@@ -160,11 +160,11 @@
         if (index >= 0 && index < maxDenseLength) {
             ensure(index);
             underlying = underlying.set(index, value, strict);
-            setLength(Math.max(underlying.length(), length()));
+            setLength(Math.max(underlying.length, length));
         } else {
             final Long longIndex = indexToKey(index);
             sparseMap.put(longIndex, value);
-            setLength(Math.max(longIndex + 1, length()));
+            setLength(Math.max(longIndex + 1, length));
         }
 
         return this;
@@ -175,11 +175,11 @@
         if (index >= 0 && index < maxDenseLength) {
             ensure(index);
             underlying = underlying.set(index, value, strict);
-            setLength(Math.max(underlying.length(), length()));
+            setLength(Math.max(underlying.length, length));
         } else {
             final Long longIndex = indexToKey(index);
             sparseMap.put(longIndex, value);
-            setLength(Math.max(longIndex + 1, length()));
+            setLength(Math.max(longIndex + 1, length));
         }
         return this;
     }
@@ -189,11 +189,11 @@
         if (index >= 0 && index < maxDenseLength) {
             ensure(index);
             underlying = underlying.set(index, value, strict);
-            setLength(Math.max(underlying.length(), length()));
+            setLength(Math.max(underlying.length, length));
         } else {
             final Long longIndex = indexToKey(index);
             sparseMap.put(longIndex, value);
-            setLength(Math.max(longIndex + 1, length()));
+            setLength(Math.max(longIndex + 1, length));
         }
         return this;
     }
@@ -203,11 +203,11 @@
         if (index >= 0 && index < maxDenseLength) {
             ensure(index);
             underlying = underlying.set(index, value, strict);
-            setLength(Math.max(underlying.length(), length()));
+            setLength(Math.max(underlying.length, length));
         } else {
             final Long longIndex = indexToKey(index);
             sparseMap.put(longIndex, value);
-            setLength(Math.max(longIndex + 1, length()));
+            setLength(Math.max(longIndex + 1, length));
         }
         return this;
     }
@@ -294,7 +294,7 @@
     @Override
     public boolean has(final int index) {
         if (index >= 0 && index < maxDenseLength) {
-            return index < underlying.length() && underlying.has(index);
+            return index < underlying.length && underlying.has(index);
         }
 
         return sparseMap.containsKey(indexToKey(index));
@@ -303,7 +303,7 @@
     @Override
     public ArrayData delete(final int index) {
         if (index >= 0 && index < maxDenseLength) {
-            if (index < underlying.length()) {
+            if (index < underlying.length) {
                 underlying = underlying.delete(index);
             }
         } else {
@@ -315,8 +315,8 @@
 
     @Override
     public ArrayData delete(final long fromIndex, final long toIndex) {
-        if (fromIndex < maxDenseLength && fromIndex < underlying.length()) {
-            underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length() - 1));
+        if (fromIndex < maxDenseLength && fromIndex < underlying.length) {
+            underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length - 1));
         }
         if (toIndex >= maxDenseLength) {
             sparseMap.subMap(fromIndex, true, toIndex, true).clear();
@@ -336,30 +336,30 @@
 
     @Override
     public Object pop() {
-        if (length() == 0) {
+        if (length == 0) {
             return ScriptRuntime.UNDEFINED;
         }
-        if (length() == underlying.length()) {
+        if (length == underlying.length) {
             final Object result = underlying.pop();
-            setLength(underlying.length());
+            setLength(underlying.length);
             return result;
         }
-        setLength(length() - 1);
-        final Long key = Long.valueOf(length());
+        setLength(length - 1);
+        final Long key = Long.valueOf(length);
         return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED;
     }
 
     @Override
     public ArrayData slice(final long from, final long to) {
-        assert to <= length();
-        final long start = from < 0 ? (from + length()) : from;
+        assert to <= length;
+        final long start = from < 0 ? (from + length) : from;
         final long newLength = to - start;
 
         if (start >= 0 && to <= maxDenseLength) {
-            if (newLength <= underlying.length()) {
+            if (newLength <= underlying.length) {
                 return underlying.slice(from, to);
             }
-            return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length(), newLength);
+            return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length, newLength);
         }
 
         ArrayData sliced = EMPTY_ARRAY;
@@ -369,13 +369,13 @@
                 sliced = sliced.set((int)(i - start), getObject((int)i), false);
             }
         }
-        assert sliced.length() == newLength;
+        assert sliced.length == newLength;
         return sliced;
     }
 
     @Override
     public long nextIndex(final long index) {
-        if (index < underlying.length() - 1) {
+        if (index < underlying.length - 1) {
             return underlying.nextIndex(index);
         }
 
@@ -383,6 +383,6 @@
         if (nextKey != null) {
             return nextKey;
         }
-        return length();
+        return length;
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Fri Oct 03 12:10:58 2014 -0700
@@ -54,11 +54,11 @@
     }
 
     /**
-     * Length in elements. Accessed from {@code ArrayBufferView}
+     * Length in number of elements. Accessed from {@code ArrayBufferView}
      * @return element length
      */
     public final int getElementLength() {
-        return (int)length();
+        return (int)length;
     }
 
     /**
@@ -119,7 +119,7 @@
 
     @Override
     public final boolean has(final int index) {
-        return 0 <= index && index < length();
+        return 0 <= index && index < length;
     }
 
     @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java	Fri Oct 03 12:10:58 2014 -0700
@@ -26,7 +26,6 @@
 package jdk.nashorn.internal.runtime.arrays;
 
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
 import java.lang.reflect.Array;
 import jdk.nashorn.internal.runtime.BitVector;
 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
@@ -41,7 +40,7 @@
     UndefinedArrayFilter(final ArrayData underlying) {
         super(underlying);
 
-        this.undefined = new BitVector(underlying.length());
+        this.undefined = new BitVector(underlying.length);
     }
 
     @Override
@@ -81,25 +80,25 @@
     @Override
     public void shiftLeft(final int by) {
         super.shiftLeft(by);
-        undefined.shiftLeft(by, length());
+        undefined.shiftLeft(by, length);
     }
 
     @Override
     public ArrayData shiftRight(final int by) {
         super.shiftRight(by);
-        undefined.shiftRight(by, length());
+        undefined.shiftRight(by, length);
 
         return this;
     }
 
     @Override
     public ArrayData ensure(final long safeIndex) {
-        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
+        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) {
             return new SparseArrayData(this, safeIndex + 1);
         }
 
         super.ensure(safeIndex);
-        undefined.resize(length());
+        undefined.resize(length);
 
         return this;
     }
@@ -107,7 +106,7 @@
     @Override
     public ArrayData shrink(final long newLength) {
         super.shrink(newLength);
-        undefined.resize(length());
+        undefined.resize(length);
 
         return this;
     }
@@ -217,7 +216,7 @@
 
     @Override
     public Object pop() {
-        final long index = length() - 1;
+        final long index = length - 1;
 
         if (super.has((int)index)) {
             final boolean isUndefined = undefined.isSet(index);
@@ -234,7 +233,7 @@
         final ArrayData newArray = underlying.slice(from, to);
         final UndefinedArrayFilter newFilter = new UndefinedArrayFilter(newArray);
         newFilter.getUndefined().copy(undefined);
-        newFilter.getUndefined().shiftLeft(from, newFilter.length());
+        newFilter.getUndefined().shiftLeft(from, newFilter.length);
 
         return newFilter;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Fri Oct 03 11:07:16 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Fri Oct 03 12:10:58 2014 -0700
@@ -25,6 +25,9 @@
 
 package jdk.nashorn.internal.runtime.regexp;
 
+import java.util.Collections;
+import java.util.Set;
+import java.util.WeakHashMap;
 import jdk.nashorn.internal.runtime.ParserException;
 import jdk.nashorn.internal.runtime.options.Options;
 
@@ -39,6 +42,15 @@
     private final static String JDK  = "jdk";
     private final static String JONI = "joni";
 
+    /** Weak cache of already validated regexps - when reparsing, we don't, for example
+     *  need to recompile (reverify) all regexps that have previously been parsed by this
+     *  RegExpFactory in a previous compilation. This saves significant time in e.g. avatar
+     *  startup */
+    private static final Set<String> VALID_CACHE_SET =
+            Collections.newSetFromMap(
+                    Collections.synchronizedMap(
+                            new WeakHashMap<String, Boolean>()));
+
     static {
         final String impl = Options.getStringProperty("nashorn.regexp.impl", JONI);
         switch (impl) {
@@ -88,7 +100,9 @@
      */
     // @SuppressWarnings({"unused"})
     public static void validate(final String pattern, final String flags) throws ParserException {
-        instance.compile(pattern, flags);
+        if (VALID_CACHE_SET.add(pattern + flags)) {
+            instance.compile(pattern, flags);
+        }
     }
 
     /**