Merge

Tue, 06 Oct 2015 11:04:55 -0700

author
asaha
date
Tue, 06 Oct 2015 11:04:55 -0700
changeset 1635
f606c983f7fa
parent 1634
718b32884775
parent 1558
f7c3d65076a0
child 1639
75bca5dc1e81

Merge

.hgtags file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/api/scripting/JSONCompatibleTest.java file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Mon Sep 28 15:36:24 2015 -0700
     1.2 +++ b/.hgtags	Tue Oct 06 11:04:55 2015 -0700
     1.3 @@ -473,3 +473,4 @@
     1.4  9a3b86240761e602469c41bd720c7791997253e6 jdk8u66-b15
     1.5  c0ce5c308f5e2c42ac0d2e7367355663312a3128 jdk8u66-b16
     1.6  667e020da337e453eac8ecb9285c9b34a47e25fd jdk8u72-b00
     1.7 +a105e7b0eff93895b82e3d372a63df4311d79821 jdk8u72-b01
     2.1 --- a/make/build.xml	Mon Sep 28 15:36:24 2015 -0700
     2.2 +++ b/make/build.xml	Tue Oct 06 11:04:55 2015 -0700
     2.3 @@ -280,8 +280,8 @@
     2.4      <javac srcdir="${test.src.dir}"
     2.5             destdir="${build.test.classes.dir}"
     2.6             classpath="${javac.test.classpath}"
     2.7 -           source="${javac.source}"
     2.8 -           target="${javac.target}"
     2.9 +           source="${test.javac.source}"
    2.10 +           target="${test.javac.target}"
    2.11             debug="${javac.debug}"
    2.12             encoding="${javac.encoding}"
    2.13             includeantruntime="false" fork="true">
     3.1 --- a/make/project.properties	Mon Sep 28 15:36:24 2015 -0700
     3.2 +++ b/make/project.properties	Tue Oct 06 11:04:55 2015 -0700
     3.3 @@ -30,6 +30,8 @@
     3.4  build.compiler=modern
     3.5  javac.source=1.7
     3.6  javac.target=1.7
     3.7 +test.javac.source=1.8
     3.8 +test.javac.target=1.8
     3.9  
    3.10  # nashorn version information
    3.11  nashorn.version=0.1
     4.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Mon Sep 28 15:36:24 2015 -0700
     4.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Tue Oct 06 11:04:55 2015 -0700
     4.3 @@ -140,7 +140,7 @@
     4.4          this._global_per_engine = nashornContext.getEnv()._global_per_engine;
     4.5  
     4.6          // create new global object
     4.7 -        this.global = createNashornGlobal(context);
     4.8 +        this.global = createNashornGlobal();
     4.9          // set the default ENGINE_SCOPE object for the default context
    4.10          context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
    4.11      }
    4.12 @@ -167,7 +167,7 @@
    4.13              // We use same 'global' for all Bindings.
    4.14              return new SimpleBindings();
    4.15          }
    4.16 -        return createGlobalMirror(null);
    4.17 +        return createGlobalMirror();
    4.18      }
    4.19  
    4.20      // Compilable methods
    4.21 @@ -317,7 +317,7 @@
    4.22  
    4.23          // We didn't find associated nashorn global mirror in the Bindings given!
    4.24          // Create new global instance mirror and associate with the Bindings.
    4.25 -        final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
    4.26 +        final ScriptObjectMirror mirror = createGlobalMirror();
    4.27          bindings.put(NASHORN_GLOBAL, mirror);
    4.28          return mirror.getHomeGlobal();
    4.29      }
    4.30 @@ -333,13 +333,13 @@
    4.31      }
    4.32  
    4.33      // Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
    4.34 -    private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
    4.35 -        final Global newGlobal = createNashornGlobal(ctxt);
    4.36 +    private ScriptObjectMirror createGlobalMirror() {
    4.37 +        final Global newGlobal = createNashornGlobal();
    4.38          return new ScriptObjectMirror(newGlobal, newGlobal);
    4.39      }
    4.40  
    4.41      // Create a new Nashorn Global object
    4.42 -    private Global createNashornGlobal(final ScriptContext ctxt) {
    4.43 +    private Global createNashornGlobal() {
    4.44          final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
    4.45              @Override
    4.46              public Global run() {
    4.47 @@ -354,7 +354,7 @@
    4.48              }
    4.49          }, CREATE_GLOBAL_ACC_CTXT);
    4.50  
    4.51 -        nashornContext.initGlobal(newGlobal, this, ctxt);
    4.52 +        nashornContext.initGlobal(newGlobal, this);
    4.53  
    4.54          return newGlobal;
    4.55      }
     5.1 --- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Mon Sep 28 15:36:24 2015 -0700
     5.2 +++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Tue Oct 06 11:04:55 2015 -0700
     5.3 @@ -41,9 +41,8 @@
     5.4  import jdk.nashorn.internal.ir.Expression;
     5.5  import jdk.nashorn.internal.ir.FunctionNode;
     5.6  import jdk.nashorn.internal.ir.IdentNode;
     5.7 -import jdk.nashorn.internal.ir.LexicalContext;
     5.8  import jdk.nashorn.internal.ir.Node;
     5.9 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    5.10 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
    5.11  import jdk.nashorn.internal.objects.Global;
    5.12  import jdk.nashorn.internal.runtime.Context;
    5.13  import jdk.nashorn.internal.runtime.logging.DebugLogger;
    5.14 @@ -81,7 +80,7 @@
    5.15   */
    5.16  
    5.17  @Logger(name="apply2call")
    5.18 -public final class ApplySpecialization extends NodeVisitor<LexicalContext> implements Loggable {
    5.19 +public final class ApplySpecialization extends SimpleNodeVisitor implements Loggable {
    5.20  
    5.21      private static final boolean USE_APPLY2CALL = Options.getBooleanProperty("nashorn.apply2call", true);
    5.22  
    5.23 @@ -105,7 +104,6 @@
    5.24       * @param compiler compiler
    5.25       */
    5.26      public ApplySpecialization(final Compiler compiler) {
    5.27 -        super(new LexicalContext());
    5.28          this.compiler = compiler;
    5.29          this.log = initLogger(compiler.getContext());
    5.30      }
    5.31 @@ -138,7 +136,7 @@
    5.32  
    5.33      private boolean hasApplies(final FunctionNode functionNode) {
    5.34          try {
    5.35 -            functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
    5.36 +            functionNode.accept(new SimpleNodeVisitor() {
    5.37                  @Override
    5.38                  public boolean enterFunctionNode(final FunctionNode fn) {
    5.39                      return fn == functionNode;
    5.40 @@ -172,7 +170,7 @@
    5.41          final Deque<Set<Expression>> stack = new ArrayDeque<>();
    5.42  
    5.43          //ensure that arguments is only passed as arg to apply
    5.44 -        functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
    5.45 +        functionNode.accept(new SimpleNodeVisitor() {
    5.46  
    5.47              private boolean isCurrentArg(final Expression expr) {
    5.48                  return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call
     6.1 --- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Mon Sep 28 15:36:24 2015 -0700
     6.2 +++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Tue Oct 06 11:04:55 2015 -0700
     6.3 @@ -67,14 +67,12 @@
     6.4  import jdk.nashorn.internal.ir.FunctionNode;
     6.5  import jdk.nashorn.internal.ir.IdentNode;
     6.6  import jdk.nashorn.internal.ir.IndexNode;
     6.7 -import jdk.nashorn.internal.ir.LexicalContext;
     6.8  import jdk.nashorn.internal.ir.LexicalContextNode;
     6.9  import jdk.nashorn.internal.ir.LiteralNode;
    6.10 -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
    6.11 -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
    6.12  import jdk.nashorn.internal.ir.Node;
    6.13  import jdk.nashorn.internal.ir.RuntimeNode;
    6.14  import jdk.nashorn.internal.ir.RuntimeNode.Request;
    6.15 +import jdk.nashorn.internal.ir.Splittable;
    6.16  import jdk.nashorn.internal.ir.Statement;
    6.17  import jdk.nashorn.internal.ir.SwitchNode;
    6.18  import jdk.nashorn.internal.ir.Symbol;
    6.19 @@ -82,7 +80,7 @@
    6.20  import jdk.nashorn.internal.ir.UnaryNode;
    6.21  import jdk.nashorn.internal.ir.VarNode;
    6.22  import jdk.nashorn.internal.ir.WithNode;
    6.23 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    6.24 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
    6.25  import jdk.nashorn.internal.parser.TokenType;
    6.26  import jdk.nashorn.internal.runtime.Context;
    6.27  import jdk.nashorn.internal.runtime.ECMAErrors;
    6.28 @@ -103,7 +101,7 @@
    6.29   * visitor.
    6.30   */
    6.31  @Logger(name="symbols")
    6.32 -final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggable {
    6.33 +final class AssignSymbols extends SimpleNodeVisitor implements Loggable {
    6.34      private final DebugLogger log;
    6.35      private final boolean     debug;
    6.36  
    6.37 @@ -151,7 +149,6 @@
    6.38      private final boolean isOnDemand;
    6.39  
    6.40      public AssignSymbols(final Compiler compiler) {
    6.41 -        super(new LexicalContext());
    6.42          this.compiler = compiler;
    6.43          this.log   = initLogger(compiler.getContext());
    6.44          this.debug = log.isEnabled();
    6.45 @@ -188,7 +185,7 @@
    6.46       */
    6.47      private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
    6.48          // This visitor will assign symbol to all declared variables.
    6.49 -        body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
    6.50 +        body.accept(new SimpleNodeVisitor() {
    6.51              @Override
    6.52              protected boolean enterDefault(final Node node) {
    6.53                  // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
    6.54 @@ -984,7 +981,7 @@
    6.55          boolean previousWasBlock = false;
    6.56          for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
    6.57              final LexicalContextNode node = it.next();
    6.58 -            if (node instanceof FunctionNode || isSplitArray(node)) {
    6.59 +            if (node instanceof FunctionNode || isSplitLiteral(node)) {
    6.60                  // We reached the function boundary or a splitting boundary without seeing a definition for the symbol.
    6.61                  // It needs to be in scope.
    6.62                  return true;
    6.63 @@ -1010,12 +1007,8 @@
    6.64          throw new AssertionError();
    6.65      }
    6.66  
    6.67 -    private static boolean isSplitArray(final LexicalContextNode expr) {
    6.68 -        if(!(expr instanceof ArrayLiteralNode)) {
    6.69 -            return false;
    6.70 -        }
    6.71 -        final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits();
    6.72 -        return !(units == null || units.isEmpty());
    6.73 +    private static boolean isSplitLiteral(final LexicalContextNode expr) {
    6.74 +        return expr instanceof Splittable && ((Splittable) expr).getSplitRanges() != null;
    6.75      }
    6.76  
    6.77      private void throwUnprotectedSwitchError(final VarNode varNode) {
     7.1 --- a/src/jdk/nashorn/internal/codegen/CacheAst.java	Mon Sep 28 15:36:24 2015 -0700
     7.2 +++ b/src/jdk/nashorn/internal/codegen/CacheAst.java	Tue Oct 06 11:04:55 2015 -0700
     7.3 @@ -29,19 +29,17 @@
     7.4  import java.util.Collections;
     7.5  import java.util.Deque;
     7.6  import jdk.nashorn.internal.ir.FunctionNode;
     7.7 -import jdk.nashorn.internal.ir.LexicalContext;
     7.8  import jdk.nashorn.internal.ir.Node;
     7.9  import jdk.nashorn.internal.ir.Statement;
    7.10 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    7.11 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
    7.12  import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
    7.13  
    7.14 -class CacheAst extends NodeVisitor<LexicalContext> {
    7.15 +class CacheAst extends SimpleNodeVisitor {
    7.16      private final Deque<RecompilableScriptFunctionData> dataStack = new ArrayDeque<>();
    7.17  
    7.18      private final Compiler compiler;
    7.19  
    7.20      CacheAst(final Compiler compiler) {
    7.21 -        super(new LexicalContext());
    7.22          this.compiler = compiler;
    7.23          assert !compiler.isOnDemandCompilation();
    7.24      }
     8.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Mon Sep 28 15:36:24 2015 -0700
     8.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Tue Oct 06 11:04:55 2015 -0700
     8.3 @@ -105,7 +105,6 @@
     8.4  import jdk.nashorn.internal.ir.LexicalContextNode;
     8.5  import jdk.nashorn.internal.ir.LiteralNode;
     8.6  import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
     8.7 -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
     8.8  import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
     8.9  import jdk.nashorn.internal.ir.LocalVariableConversion;
    8.10  import jdk.nashorn.internal.ir.LoopNode;
    8.11 @@ -118,6 +117,7 @@
    8.12  import jdk.nashorn.internal.ir.RuntimeNode.Request;
    8.13  import jdk.nashorn.internal.ir.SetSplitState;
    8.14  import jdk.nashorn.internal.ir.SplitReturn;
    8.15 +import jdk.nashorn.internal.ir.Splittable;
    8.16  import jdk.nashorn.internal.ir.Statement;
    8.17  import jdk.nashorn.internal.ir.SwitchNode;
    8.18  import jdk.nashorn.internal.ir.Symbol;
    8.19 @@ -129,7 +129,7 @@
    8.20  import jdk.nashorn.internal.ir.WhileNode;
    8.21  import jdk.nashorn.internal.ir.WithNode;
    8.22  import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
    8.23 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    8.24 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
    8.25  import jdk.nashorn.internal.objects.Global;
    8.26  import jdk.nashorn.internal.parser.Lexer.RegexToken;
    8.27  import jdk.nashorn.internal.parser.TokenType;
    8.28 @@ -242,7 +242,7 @@
    8.29      private final DebugLogger log;
    8.30  
    8.31      /** From what size should we use spill instead of fields for JavaScript objects? */
    8.32 -    private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
    8.33 +    static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
    8.34  
    8.35      private final Set<String> emittedMethods = new HashSet<>();
    8.36  
    8.37 @@ -1433,8 +1433,7 @@
    8.38          final Block currentBlock = lc.getCurrentBlock();
    8.39          final CodeGeneratorLexicalContext codegenLexicalContext = lc;
    8.40  
    8.41 -        function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
    8.42 -
    8.43 +        function.accept(new SimpleNodeVisitor() {
    8.44              private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
    8.45                  final Symbol symbol = identNode.getSymbol();
    8.46                  final boolean isFastScope = isFastScope(symbol);
    8.47 @@ -1634,7 +1633,7 @@
    8.48  
    8.49                      @Override
    8.50                      void consumeStack() {
    8.51 -                        dynamicCall(2 + argsCount, getCallSiteFlags(), origCallee.getName());
    8.52 +                        dynamicCall(2 + argsCount, getCallSiteFlags(), null);
    8.53                      }
    8.54                  }.emit();
    8.55                  return false;
    8.56 @@ -2234,73 +2233,33 @@
    8.57       *
    8.58       * @param arrayLiteralNode the array of contents
    8.59       * @param arrayType        the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT
    8.60 -     *
    8.61 -     * @return the method generator that was used
    8.62       */
    8.63 -    private MethodEmitter loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
    8.64 +    private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
    8.65          assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
    8.66  
    8.67 -        final Expression[]    nodes    = arrayLiteralNode.getValue();
    8.68 -        final Object          presets  = arrayLiteralNode.getPresets();
    8.69 -        final int[]           postsets = arrayLiteralNode.getPostsets();
    8.70 -        final Class<?>        type     = arrayType.getTypeClass();
    8.71 -        final List<ArrayUnit> units    = arrayLiteralNode.getUnits();
    8.72 +        final Expression[]     nodes    = arrayLiteralNode.getValue();
    8.73 +        final Object           presets  = arrayLiteralNode.getPresets();
    8.74 +        final int[]            postsets = arrayLiteralNode.getPostsets();
    8.75 +        final List<Splittable.SplitRange> ranges   = arrayLiteralNode.getSplitRanges();
    8.76  
    8.77          loadConstant(presets);
    8.78  
    8.79          final Type elementType = arrayType.getElementType();
    8.80  
    8.81 -        if (units != null) {
    8.82 -            final MethodEmitter savedMethod     = method;
    8.83 -            final FunctionNode  currentFunction = lc.getCurrentFunction();
    8.84 -
    8.85 -            for (final ArrayUnit arrayUnit : units) {
    8.86 -                unit = lc.pushCompileUnit(arrayUnit.getCompileUnit());
    8.87 -
    8.88 -                final String className = unit.getUnitClassName();
    8.89 -                assert unit != null;
    8.90 -                final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
    8.91 -                final String signature = methodDescriptor(type, ScriptFunction.class, Object.class, ScriptObject.class, type);
    8.92 -
    8.93 -                pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
    8.94 -
    8.95 -                method.setFunctionNode(currentFunction);
    8.96 -                method.begin();
    8.97 -
    8.98 -                defineCommonSplitMethodParameters();
    8.99 -                defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), arrayType);
   8.100 -
   8.101 -                // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
   8.102 -                // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
   8.103 -                final int arraySlot = fixScopeSlot(currentFunction, 3);
   8.104 -
   8.105 -                lc.enterSplitNode();
   8.106 -
   8.107 -                for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) {
   8.108 -                    method.load(arrayType, arraySlot);
   8.109 -                    storeElement(nodes, elementType, postsets[i]);
   8.110 +        if (ranges != null) {
   8.111 +
   8.112 +            loadSplitLiteral(new SplitLiteralCreator() {
   8.113 +                @Override
   8.114 +                public void populateRange(final MethodEmitter method, final Type type, final int slot, final int start, final int end) {
   8.115 +                    for (int i = start; i < end; i++) {
   8.116 +                        method.load(type, slot);
   8.117 +                        storeElement(nodes, elementType, postsets[i]);
   8.118 +                    }
   8.119 +                    method.load(type, slot);
   8.120                  }
   8.121 -
   8.122 -                method.load(arrayType, arraySlot);
   8.123 -                method._return();
   8.124 -                lc.exitSplitNode();
   8.125 -                method.end();
   8.126 -                lc.releaseSlots();
   8.127 -                popMethodEmitter();
   8.128 -
   8.129 -                assert method == savedMethod;
   8.130 -                method.loadCompilerConstant(CALLEE);
   8.131 -                method.swap();
   8.132 -                method.loadCompilerConstant(THIS);
   8.133 -                method.swap();
   8.134 -                method.loadCompilerConstant(SCOPE);
   8.135 -                method.swap();
   8.136 -                method.invokestatic(className, name, signature);
   8.137 -
   8.138 -                unit = lc.popCompileUnit(unit);
   8.139 -            }
   8.140 -
   8.141 -            return method;
   8.142 +            }, ranges, arrayType);
   8.143 +
   8.144 +            return;
   8.145          }
   8.146  
   8.147          if(postsets.length > 0) {
   8.148 @@ -2312,7 +2271,6 @@
   8.149              }
   8.150              method.load(arrayType, arraySlot);
   8.151          }
   8.152 -        return method;
   8.153      }
   8.154  
   8.155      private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
   8.156 @@ -2502,7 +2460,7 @@
   8.157  
   8.158              @Override
   8.159              public Boolean get() {
   8.160 -                value.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   8.161 +                value.accept(new SimpleNodeVisitor() {
   8.162                      @Override
   8.163                      public boolean enterFunctionNode(final FunctionNode functionNode) {
   8.164                          return false;
   8.165 @@ -2537,6 +2495,7 @@
   8.166          final List<MapTuple<Expression>> tuples = new ArrayList<>();
   8.167          final List<PropertyNode> gettersSetters = new ArrayList<>();
   8.168          final int ccp = getCurrentContinuationEntryPoint();
   8.169 +        final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();
   8.170  
   8.171          Expression protoNode = null;
   8.172          boolean restOfProperty = false;
   8.173 @@ -2583,7 +2542,13 @@
   8.174                      loadExpressionAsType(node, type);
   8.175                  }};
   8.176          }
   8.177 -        oc.makeObject(method);
   8.178 +
   8.179 +        if (ranges != null) {
   8.180 +            oc.createObject(method);
   8.181 +            loadSplitLiteral(oc, ranges, Type.typeFor(oc.getAllocatorClass()));
   8.182 +        } else {
   8.183 +            oc.makeObject(method);
   8.184 +        }
   8.185  
   8.186          //if this is a rest of method and our continuation point was found as one of the values
   8.187          //in the properties above, we need to reset the map to oc.getMap() in the continuation
   8.188 @@ -2833,7 +2798,7 @@
   8.189              boolean contains;
   8.190              @Override
   8.191              public Boolean get() {
   8.192 -                rootExpr.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   8.193 +                rootExpr.accept(new SimpleNodeVisitor() {
   8.194                      @Override
   8.195                      public boolean enterFunctionNode(final FunctionNode functionNode) {
   8.196                          return false;
   8.197 @@ -2899,6 +2864,54 @@
   8.198          method.onLocalStore(type, slot);
   8.199      }
   8.200  
   8.201 +    private void loadSplitLiteral(final SplitLiteralCreator creator, final List<Splittable.SplitRange> ranges, final Type literalType) {
   8.202 +        assert ranges != null;
   8.203 +
   8.204 +        // final Type literalType = Type.typeFor(literalClass);
   8.205 +        final MethodEmitter savedMethod     = method;
   8.206 +        final FunctionNode  currentFunction = lc.getCurrentFunction();
   8.207 +
   8.208 +        for (final Splittable.SplitRange splitRange : ranges) {
   8.209 +            unit = lc.pushCompileUnit(splitRange.getCompileUnit());
   8.210 +
   8.211 +            assert unit != null;
   8.212 +            final String className = unit.getUnitClassName();
   8.213 +            final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
   8.214 +            final Class<?> clazz   = literalType.getTypeClass();
   8.215 +            final String signature = methodDescriptor(clazz, ScriptFunction.class, Object.class, ScriptObject.class, clazz);
   8.216 +
   8.217 +            pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
   8.218 +
   8.219 +            method.setFunctionNode(currentFunction);
   8.220 +            method.begin();
   8.221 +
   8.222 +            defineCommonSplitMethodParameters();
   8.223 +            defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), literalType);
   8.224 +
   8.225 +            // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
   8.226 +            // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
   8.227 +            final int literalSlot = fixScopeSlot(currentFunction, 3);
   8.228 +
   8.229 +            lc.enterSplitNode();
   8.230 +
   8.231 +            creator.populateRange(method, literalType, literalSlot, splitRange.getLow(), splitRange.getHigh());
   8.232 +
   8.233 +            method._return();
   8.234 +            lc.exitSplitNode();
   8.235 +            method.end();
   8.236 +            lc.releaseSlots();
   8.237 +            popMethodEmitter();
   8.238 +
   8.239 +            assert method == savedMethod;
   8.240 +            method.loadCompilerConstant(CALLEE).swap();
   8.241 +            method.loadCompilerConstant(THIS).swap();
   8.242 +            method.loadCompilerConstant(SCOPE).swap();
   8.243 +            method.invokestatic(className, name, signature);
   8.244 +
   8.245 +            unit = lc.popCompileUnit(unit);
   8.246 +        }
   8.247 +    }
   8.248 +
   8.249      private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) {
   8.250          // TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method)
   8.251          final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
   8.252 @@ -4333,7 +4346,7 @@
   8.253               * on the stack throughout the store and used at the end to execute it
   8.254               */
   8.255  
   8.256 -            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   8.257 +            target.accept(new SimpleNodeVisitor() {
   8.258                  @Override
   8.259                  public boolean enterIdentNode(final IdentNode node) {
   8.260                      if (node.getSymbol().isScope()) {
   8.261 @@ -4432,7 +4445,7 @@
   8.262               * need to do a conversion on non-equivalent types exists, but is
   8.263               * very rare. See for example test/script/basic/access-specializer.js
   8.264               */
   8.265 -            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   8.266 +            target.accept(new SimpleNodeVisitor() {
   8.267                  @Override
   8.268                  protected boolean enterDefault(final Node node) {
   8.269                      throw new AssertionError("Unexpected node " + node + " in store epilogue");
   8.270 @@ -5461,4 +5474,21 @@
   8.271              method.uncheckedGoto(targetCatchLabel);
   8.272          }
   8.273      }
   8.274 +
   8.275 +    /**
   8.276 +     * Interface implemented by object creators that support splitting over multiple methods.
   8.277 +     */
   8.278 +    interface SplitLiteralCreator {
   8.279 +        /**
   8.280 +         * Generate code to populate a range of the literal object. A reference to the object
   8.281 +         * should be left on the stack when the method terminates.
   8.282 +         *
   8.283 +         * @param method the method emitter
   8.284 +         * @param type the type of the literal object
   8.285 +         * @param slot the local slot containing the literal object
   8.286 +         * @param start the start index (inclusive)
   8.287 +         * @param end the end index (exclusive)
   8.288 +         */
   8.289 +        void populateRange(MethodEmitter method, Type type, int slot, int start, int end);
   8.290 +    }
   8.291  }
     9.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Mon Sep 28 15:36:24 2015 -0700
     9.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Tue Oct 06 11:04:55 2015 -0700
     9.3 @@ -36,13 +36,13 @@
     9.4  import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
     9.5  import jdk.nashorn.internal.ir.Block;
     9.6  import jdk.nashorn.internal.ir.FunctionNode;
     9.7 -import jdk.nashorn.internal.ir.LexicalContext;
     9.8  import jdk.nashorn.internal.ir.LiteralNode;
     9.9  import jdk.nashorn.internal.ir.Node;
    9.10  import jdk.nashorn.internal.ir.Symbol;
    9.11  import jdk.nashorn.internal.ir.debug.ASTWriter;
    9.12  import jdk.nashorn.internal.ir.debug.PrintVisitor;
    9.13  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    9.14 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
    9.15  import jdk.nashorn.internal.runtime.CodeInstaller;
    9.16  import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
    9.17  import jdk.nashorn.internal.runtime.ScriptEnvironment;
    9.18 @@ -118,7 +118,7 @@
    9.19              FunctionNode newFunctionNode;
    9.20  
    9.21              //ensure elementTypes, postsets and presets exist for splitter and arraynodes
    9.22 -            newFunctionNode = transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
    9.23 +            newFunctionNode = transformFunction(fn, new SimpleNodeVisitor() {
    9.24                  @Override
    9.25                  public LiteralNode<?> leaveLiteralNode(final LiteralNode<?> literalNode) {
    9.26                      return literalNode.initialize(lc);
    9.27 @@ -217,7 +217,7 @@
    9.28              // correctness, it's just an optimization -- runtime type calculation is not used when the compilation
    9.29              // is not an on-demand optimistic compilation, so we can skip locals marking then.
    9.30              if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) {
    9.31 -                fn.getBody().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
    9.32 +                fn.getBody().accept(new SimpleNodeVisitor() {
    9.33                      @Override
    9.34                      public boolean enterFunctionNode(final FunctionNode functionNode) {
    9.35                          // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand
    9.36 @@ -483,8 +483,8 @@
    9.37              Class<?> rootClass = null;
    9.38              long length = 0L;
    9.39  
    9.40 -            final CodeInstaller<ScriptEnvironment> codeInstaller = compiler.getCodeInstaller();
    9.41 -            final Map<String, byte[]>              bytecode      = compiler.getBytecode();
    9.42 +            final CodeInstaller       codeInstaller = compiler.getCodeInstaller();
    9.43 +            final Map<String, byte[]> bytecode      = compiler.getBytecode();
    9.44  
    9.45              for (final Entry<String, byte[]> entry : bytecode.entrySet()) {
    9.46                  final String className = entry.getKey();
    10.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java	Mon Sep 28 15:36:24 2015 -0700
    10.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Tue Oct 06 11:04:55 2015 -0700
    10.3 @@ -101,7 +101,7 @@
    10.4  
    10.5      private final ConstantData constantData;
    10.6  
    10.7 -    private final CodeInstaller<ScriptEnvironment> installer;
    10.8 +    private final CodeInstaller installer;
    10.9  
   10.10      /** logger for compiler, trampolines and related code generation events
   10.11       *  that affect classes */
   10.12 @@ -351,47 +351,83 @@
   10.13      private static final AtomicInteger COMPILATION_ID = new AtomicInteger(0);
   10.14  
   10.15      /**
   10.16 -     * Constructor
   10.17 +     * Creates a new compiler instance for initial compilation of a script.
   10.18       *
   10.19 -     * @param context   context
   10.20 -     * @param env       script environment
   10.21       * @param installer code installer
   10.22       * @param source    source to compile
   10.23       * @param errors    error manager
   10.24       * @param isStrict  is this a strict compilation
   10.25 +     * @return a new compiler
   10.26       */
   10.27 -    public Compiler(
   10.28 -            final Context context,
   10.29 -            final ScriptEnvironment env,
   10.30 -            final CodeInstaller<ScriptEnvironment> installer,
   10.31 +    public static Compiler forInitialCompilation(
   10.32 +            final CodeInstaller installer,
   10.33              final Source source,
   10.34              final ErrorManager errors,
   10.35              final boolean isStrict) {
   10.36 -        this(context, env, installer, source, errors, isStrict, false, null, null, null, null, null, null);
   10.37 +        return new Compiler(installer.getContext(), installer, source, errors, isStrict);
   10.38      }
   10.39  
   10.40      /**
   10.41 -     * Constructor
   10.42 +     * Creates a compiler without a code installer. It can only be used to compile code, not install the
   10.43 +     * generated classes and as such it is useful only for implementation of {@code --compile-only} command
   10.44 +     * line option.
   10.45 +     * @param context  the current context
   10.46 +     * @param source   source to compile
   10.47 +     * @param isStrict is this a strict compilation
   10.48 +     * @return a new compiler
   10.49 +     */
   10.50 +    public static Compiler forNoInstallerCompilation(
   10.51 +            final Context context,
   10.52 +            final Source source,
   10.53 +            final boolean isStrict) {
   10.54 +        return new Compiler(context, null, source, context.getErrorManager(), isStrict);
   10.55 +    }
   10.56 +
   10.57 +    /**
   10.58 +     * Creates a compiler for an on-demand compilation job.
   10.59       *
   10.60 -     * @param context                  context
   10.61 -     * @param env                      script environment
   10.62       * @param installer                code installer
   10.63       * @param source                   source to compile
   10.64 -     * @param errors                   error manager
   10.65       * @param isStrict                 is this a strict compilation
   10.66 -     * @param isOnDemand               is this an on demand compilation
   10.67       * @param compiledFunction         compiled function, if any
   10.68       * @param types                    parameter and return value type information, if any is known
   10.69       * @param invalidatedProgramPoints invalidated program points for recompilation
   10.70       * @param typeInformationFile      descriptor of the location where type information is persisted
   10.71       * @param continuationEntryPoints  continuation entry points for restof method
   10.72       * @param runtimeScope             runtime scope for recompilation type lookup in {@code TypeEvaluator}
   10.73 +     * @return a new compiler
   10.74       */
   10.75 -    @SuppressWarnings("unused")
   10.76 -    public Compiler(
   10.77 +    public static Compiler forOnDemandCompilation(
   10.78 +            final CodeInstaller installer,
   10.79 +            final Source source,
   10.80 +            final boolean isStrict,
   10.81 +            final RecompilableScriptFunctionData compiledFunction,
   10.82 +            final TypeMap types,
   10.83 +            final Map<Integer, Type> invalidatedProgramPoints,
   10.84 +            final Object typeInformationFile,
   10.85 +            final int[] continuationEntryPoints,
   10.86 +            final ScriptObject runtimeScope) {
   10.87 +        final Context context = installer.getContext();
   10.88 +        return new Compiler(context, installer, source, context.getErrorManager(), isStrict, true,
   10.89 +                compiledFunction, types, invalidatedProgramPoints, typeInformationFile,
   10.90 +                continuationEntryPoints, runtimeScope);
   10.91 +    }
   10.92 +
   10.93 +    /**
   10.94 +     * Convenience constructor for non on-demand compiler instances.
   10.95 +     */
   10.96 +    private Compiler(
   10.97              final Context context,
   10.98 -            final ScriptEnvironment env,
   10.99 -            final CodeInstaller<ScriptEnvironment> installer,
  10.100 +            final CodeInstaller installer,
  10.101 +            final Source source,
  10.102 +            final ErrorManager errors,
  10.103 +            final boolean isStrict) {
  10.104 +        this(context, installer, source, errors, isStrict, false, null, null, null, null, null, null);
  10.105 +    }
  10.106 +
  10.107 +    private Compiler(
  10.108 +            final Context context,
  10.109 +            final CodeInstaller installer,
  10.110              final Source source,
  10.111              final ErrorManager errors,
  10.112              final boolean isStrict,
  10.113 @@ -403,7 +439,7 @@
  10.114              final int[] continuationEntryPoints,
  10.115              final ScriptObject runtimeScope) {
  10.116          this.context                  = context;
  10.117 -        this.env                      = env;
  10.118 +        this.env                      = context.getEnv();
  10.119          this.installer                = installer;
  10.120          this.constantData             = new ConstantData();
  10.121          this.compileUnits             = CompileUnit.createCompileUnitSet();
  10.122 @@ -425,7 +461,7 @@
  10.123          this.optimistic = env._optimistic_types;
  10.124      }
  10.125  
  10.126 -    private static String safeSourceName(final ScriptEnvironment env, final CodeInstaller<ScriptEnvironment> installer, final Source source) {
  10.127 +    private String safeSourceName() {
  10.128          String baseName = new File(source.getName()).getName();
  10.129  
  10.130          final int index = baseName.lastIndexOf(".js");
  10.131 @@ -484,7 +520,7 @@
  10.132              sb.append('$');
  10.133          }
  10.134  
  10.135 -        sb.append(Compiler.safeSourceName(env, installer, source));
  10.136 +        sb.append(safeSourceName());
  10.137  
  10.138          return sb.toString();
  10.139      }
  10.140 @@ -683,7 +719,7 @@
  10.141          return constantData;
  10.142      }
  10.143  
  10.144 -    CodeInstaller<ScriptEnvironment> getCodeInstaller() {
  10.145 +    CodeInstaller getCodeInstaller() {
  10.146          return installer;
  10.147      }
  10.148  
    11.1 --- a/src/jdk/nashorn/internal/codegen/ConstantData.java	Mon Sep 28 15:36:24 2015 -0700
    11.2 +++ b/src/jdk/nashorn/internal/codegen/ConstantData.java	Tue Oct 06 11:04:55 2015 -0700
    11.3 @@ -30,6 +30,8 @@
    11.4  import java.util.HashMap;
    11.5  import java.util.List;
    11.6  import java.util.Map;
    11.7 +import java.util.Objects;
    11.8 +
    11.9  import jdk.nashorn.internal.runtime.PropertyMap;
   11.10  
   11.11  /**
   11.12 @@ -120,7 +122,7 @@
   11.13          private final int hashCode;
   11.14  
   11.15          public PropertyMapWrapper(final PropertyMap map) {
   11.16 -            this.hashCode = Arrays.hashCode(map.getProperties());
   11.17 +            this.hashCode = Arrays.hashCode(map.getProperties()) + 31 * Objects.hashCode(map.getClassName());
   11.18              this.propertyMap = map;
   11.19          }
   11.20  
   11.21 @@ -131,8 +133,13 @@
   11.22  
   11.23          @Override
   11.24          public boolean equals(final Object other) {
   11.25 -            return other instanceof PropertyMapWrapper &&
   11.26 -                    Arrays.equals(propertyMap.getProperties(), ((PropertyMapWrapper) other).propertyMap.getProperties());
   11.27 +            if (!(other instanceof PropertyMapWrapper)) {
   11.28 +                return false;
   11.29 +            }
   11.30 +            final PropertyMap otherMap = ((PropertyMapWrapper) other).propertyMap;
   11.31 +            return propertyMap == otherMap
   11.32 +                    || (Arrays.equals(propertyMap.getProperties(), otherMap.getProperties())
   11.33 +                        && Objects.equals(propertyMap.getClassName(), otherMap.getClassName()));
   11.34          }
   11.35      }
   11.36  
    12.1 --- a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java	Mon Sep 28 15:36:24 2015 -0700
    12.2 +++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java	Tue Oct 06 11:04:55 2015 -0700
    12.3 @@ -34,7 +34,6 @@
    12.4  import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
    12.5  import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
    12.6  
    12.7 -import java.util.Iterator;
    12.8  import java.util.List;
    12.9  import jdk.nashorn.internal.codegen.types.Type;
   12.10  import jdk.nashorn.internal.ir.Symbol;
   12.11 @@ -91,27 +90,20 @@
   12.12          findClass();
   12.13      }
   12.14  
   12.15 -    /**
   12.16 -     * Construct an object.
   12.17 -     *
   12.18 -     * @param method the method emitter
   12.19 -     */
   12.20      @Override
   12.21 -    protected void makeObject(final MethodEmitter method) {
   12.22 +    public void createObject(final MethodEmitter method) {
   12.23          makeMap();
   12.24          final String className = getClassName();
   12.25 -        try {
   12.26 -            // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects,
   12.27 -            // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type
   12.28 -            // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the
   12.29 -            // exact type information is needed for generating continuations in rest-of methods. If we didn't do this,
   12.30 -            // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the
   12.31 -            // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and
   12.32 -            // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification.
   12.33 -            method._new(Context.forStructureClass(className.replace('/', '.'))).dup();
   12.34 -        } catch (final ClassNotFoundException e) {
   12.35 -            throw new AssertionError(e);
   12.36 -        }
   12.37 +        // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects,
   12.38 +        // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type
   12.39 +        // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the
   12.40 +        // exact type information is needed for generating continuations in rest-of methods. If we didn't do this,
   12.41 +        // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the
   12.42 +        // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and
   12.43 +        // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification.
   12.44 +        assert fieldObjectClass != null;
   12.45 +        method._new(fieldObjectClass).dup();
   12.46 +
   12.47          loadMap(method); //load the map
   12.48  
   12.49          if (isScope()) {
   12.50 @@ -126,14 +118,14 @@
   12.51          } else {
   12.52              method.invoke(constructorNoLookup(className, PropertyMap.class));
   12.53          }
   12.54 +    }
   12.55  
   12.56 -        helpOptimisticRecognizeDuplicateIdentity(method);
   12.57 -
   12.58 +    @Override
   12.59 +    public void populateRange(final MethodEmitter method, final Type objectType, final int objectSlot, final int start, final int end) {
   12.60 +        method.load(objectType, objectSlot);
   12.61          // Set values.
   12.62 -        final Iterator<MapTuple<T>> iter = tuples.iterator();
   12.63 -
   12.64 -        while (iter.hasNext()) {
   12.65 -            final MapTuple<T> tuple = iter.next();
   12.66 +        for (int i = start; i < end; i++) {
   12.67 +            final MapTuple<T> tuple = tuples.get(i);
   12.68              //we only load when we have both symbols and values (which can be == the symbol)
   12.69              //if we didn't load, we need an array property
   12.70              if (tuple.symbol != null && tuple.value != null) {
   12.71 @@ -212,6 +204,11 @@
   12.72          }
   12.73      }
   12.74  
   12.75 +    @Override
   12.76 +    protected Class<? extends ScriptObject> getAllocatorClass() {
   12.77 +        return fieldObjectClass;
   12.78 +    }
   12.79 +
   12.80      /**
   12.81       * Get the class name for the object class,
   12.82       * e.g. {@code com.nashorn.oracle.scripts.JO2P0}
    13.1 --- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Mon Sep 28 15:36:24 2015 -0700
    13.2 +++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Tue Oct 06 11:04:55 2015 -0700
    13.3 @@ -39,7 +39,7 @@
    13.4  import jdk.nashorn.internal.ir.Node;
    13.5  import jdk.nashorn.internal.ir.Symbol;
    13.6  import jdk.nashorn.internal.ir.WithNode;
    13.7 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    13.8 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
    13.9  import jdk.nashorn.internal.runtime.Context;
   13.10  import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
   13.11  import jdk.nashorn.internal.runtime.logging.DebugLogger;
   13.12 @@ -53,7 +53,7 @@
   13.13   * FunctionNode being compiled
   13.14   */
   13.15  @Logger(name="scopedepths")
   13.16 -final class FindScopeDepths extends NodeVisitor<LexicalContext> implements Loggable {
   13.17 +final class FindScopeDepths extends SimpleNodeVisitor implements Loggable {
   13.18  
   13.19      private final Compiler compiler;
   13.20      private final Map<Integer, Map<Integer, RecompilableScriptFunctionData>> fnIdToNestedFunctions = new HashMap<>();
   13.21 @@ -66,7 +66,6 @@
   13.22      private int dynamicScopeCount;
   13.23  
   13.24      FindScopeDepths(final Compiler compiler) {
   13.25 -        super(new LexicalContext());
   13.26          this.compiler = compiler;
   13.27          this.log      = initLogger(compiler.getContext());
   13.28      }
   13.29 @@ -275,17 +274,13 @@
   13.30  
   13.31          //get all symbols that are referenced inside this function body
   13.32          final Set<Symbol> symbols = new HashSet<>();
   13.33 -        block.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   13.34 +        block.accept(new SimpleNodeVisitor() {
   13.35              @Override
   13.36 -            public final boolean enterDefault(final Node node) {
   13.37 -                if (!compiler.isOnDemandCompilation()) {
   13.38 -                    if (node instanceof IdentNode) {
   13.39 -                        final Symbol symbol = ((IdentNode)node).getSymbol();
   13.40 -                        if (symbol != null && symbol.isScope()) {
   13.41 -                            //if this is an internal symbol, skip it.
   13.42 -                            symbols.add(symbol);
   13.43 -                        }
   13.44 -                    }
   13.45 +            public boolean enterIdentNode(final IdentNode identNode) {
   13.46 +                final Symbol symbol = identNode.getSymbol();
   13.47 +                if (symbol != null && symbol.isScope()) {
   13.48 +                    //if this is an internal symbol, skip it.
   13.49 +                    symbols.add(symbol);
   13.50                  }
   13.51                  return true;
   13.52              }
    14.1 --- a/src/jdk/nashorn/internal/codegen/FoldConstants.java	Mon Sep 28 15:36:24 2015 -0700
    14.2 +++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java	Tue Oct 06 11:04:55 2015 -0700
    14.3 @@ -38,7 +38,6 @@
    14.4  import jdk.nashorn.internal.ir.Expression;
    14.5  import jdk.nashorn.internal.ir.FunctionNode;
    14.6  import jdk.nashorn.internal.ir.IfNode;
    14.7 -import jdk.nashorn.internal.ir.LexicalContext;
    14.8  import jdk.nashorn.internal.ir.LiteralNode;
    14.9  import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
   14.10  import jdk.nashorn.internal.ir.Node;
   14.11 @@ -47,7 +46,7 @@
   14.12  import jdk.nashorn.internal.ir.TernaryNode;
   14.13  import jdk.nashorn.internal.ir.UnaryNode;
   14.14  import jdk.nashorn.internal.ir.VarNode;
   14.15 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   14.16 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
   14.17  import jdk.nashorn.internal.runtime.Context;
   14.18  import jdk.nashorn.internal.runtime.JSType;
   14.19  import jdk.nashorn.internal.runtime.ScriptRuntime;
   14.20 @@ -59,12 +58,11 @@
   14.21   * Simple constant folding pass, executed before IR is starting to be lowered.
   14.22   */
   14.23  @Logger(name="fold")
   14.24 -final class FoldConstants extends NodeVisitor<LexicalContext> implements Loggable {
   14.25 +final class FoldConstants extends SimpleNodeVisitor implements Loggable {
   14.26  
   14.27      private final DebugLogger log;
   14.28  
   14.29      FoldConstants(final Compiler compiler) {
   14.30 -        super(new LexicalContext());
   14.31          this.log = initLogger(compiler.getContext());
   14.32      }
   14.33  
   14.34 @@ -116,7 +114,7 @@
   14.35                  statements.addAll(executed.getStatements()); // Get statements form executed branch
   14.36              }
   14.37              if (dropped != null) {
   14.38 -                extractVarNodes(dropped, statements); // Get var-nodes from non-executed branch
   14.39 +                extractVarNodesFromDeadCode(dropped, statements); // Get var-nodes from non-executed branch
   14.40              }
   14.41              if (statements.isEmpty()) {
   14.42                  return new EmptyNode(ifNode);
   14.43 @@ -185,14 +183,27 @@
   14.44          protected abstract LiteralNode<?> eval();
   14.45      }
   14.46  
   14.47 -    private static void extractVarNodes(final Block block, final List<Statement> statements) {
   14.48 -        final LexicalContext lc = new LexicalContext();
   14.49 -        block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
   14.50 +    /**
   14.51 +     * When we eliminate dead code, we must preserve var declarations as they are scoped to the whole
   14.52 +     * function. This method gathers var nodes from code passed to it, removing their initializers.
   14.53 +     *
   14.54 +     * @param deadCodeRoot the root node of eliminated dead code
   14.55 +     * @param statements a list that will be receiving the var nodes from the dead code, with their
   14.56 +     * initializers removed.
   14.57 +     */
   14.58 +    static void extractVarNodesFromDeadCode(final Node deadCodeRoot, final List<Statement> statements) {
   14.59 +        deadCodeRoot.accept(new SimpleNodeVisitor() {
   14.60              @Override
   14.61              public boolean enterVarNode(final VarNode varNode) {
   14.62                  statements.add(varNode.setInit(null));
   14.63                  return false;
   14.64              }
   14.65 +
   14.66 +            @Override
   14.67 +            public boolean enterFunctionNode(final FunctionNode functionNode) {
   14.68 +                // Don't descend into nested functions
   14.69 +                return false;
   14.70 +            }
   14.71          });
   14.72      }
   14.73  
    15.1 --- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Mon Sep 28 15:36:24 2015 -0700
    15.2 +++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Tue Oct 06 11:04:55 2015 -0700
    15.3 @@ -87,6 +87,7 @@
    15.4  import jdk.nashorn.internal.ir.WhileNode;
    15.5  import jdk.nashorn.internal.ir.WithNode;
    15.6  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    15.7 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
    15.8  import jdk.nashorn.internal.parser.TokenType;
    15.9  
   15.10  /**
   15.11 @@ -105,7 +106,7 @@
   15.12   * instances of the calculator to be run on nested functions (when not lazy compiling).
   15.13   *
   15.14   */
   15.15 -final class LocalVariableTypesCalculator extends NodeVisitor<LexicalContext>{
   15.16 +final class LocalVariableTypesCalculator extends SimpleNodeVisitor {
   15.17  
   15.18      private static class JumpOrigin {
   15.19          final JoinPredecessor node;
   15.20 @@ -425,7 +426,6 @@
   15.21      private final Deque<Label> catchLabels = new ArrayDeque<>();
   15.22  
   15.23      LocalVariableTypesCalculator(final Compiler compiler) {
   15.24 -        super(new LexicalContext());
   15.25          this.compiler = compiler;
   15.26      }
   15.27  
   15.28 @@ -1330,7 +1330,7 @@
   15.29          // Sets the return type of the function and also performs the bottom-up pass of applying type and conversion
   15.30          // information to nodes as well as doing the calculation on nested functions as required.
   15.31          FunctionNode newFunction = functionNode;
   15.32 -        final NodeVisitor<LexicalContext> applyChangesVisitor = new NodeVisitor<LexicalContext>(new LexicalContext()) {
   15.33 +        final SimpleNodeVisitor applyChangesVisitor = new SimpleNodeVisitor() {
   15.34              private boolean inOuterFunction = true;
   15.35              private final Deque<JoinPredecessor> joinPredecessors = new ArrayDeque<>();
   15.36  
    16.1 --- a/src/jdk/nashorn/internal/codegen/Lower.java	Mon Sep 28 15:36:24 2015 -0700
    16.2 +++ b/src/jdk/nashorn/internal/codegen/Lower.java	Tue Oct 06 11:04:55 2015 -0700
    16.3 @@ -73,7 +73,7 @@
    16.4  import jdk.nashorn.internal.ir.WhileNode;
    16.5  import jdk.nashorn.internal.ir.WithNode;
    16.6  import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
    16.7 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    16.8 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
    16.9  import jdk.nashorn.internal.parser.Token;
   16.10  import jdk.nashorn.internal.parser.TokenType;
   16.11  import jdk.nashorn.internal.runtime.Context;
   16.12 @@ -120,13 +120,7 @@
   16.13                              terminated = true;
   16.14                          }
   16.15                      } else {
   16.16 -                        statement.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   16.17 -                            @Override
   16.18 -                            public boolean enterVarNode(final VarNode varNode) {
   16.19 -                                newStatements.add(varNode.setInit(null));
   16.20 -                                return false;
   16.21 -                            }
   16.22 -                        });
   16.23 +                        FoldConstants.extractVarNodesFromDeadCode(statement, newStatements);
   16.24                      }
   16.25                  }
   16.26                  return newStatements;
   16.27 @@ -327,7 +321,7 @@
   16.28  
   16.29      @SuppressWarnings("unchecked")
   16.30      private static <T extends Node> T ensureUniqueNamesIn(final T node) {
   16.31 -        return (T)node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   16.32 +        return (T)node.accept(new SimpleNodeVisitor() {
   16.33              @Override
   16.34              public Node leaveFunctionNode(final FunctionNode functionNode) {
   16.35                  final String name = functionNode.getName();
   16.36 @@ -392,7 +386,7 @@
   16.37          final Block finallyBlock = createFinallyBlock(finallyBody);
   16.38          final ArrayList<Block> inlinedFinallies = new ArrayList<>();
   16.39          final FunctionNode fn = lc.getCurrentFunction();
   16.40 -        final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   16.41 +        final TryNode newTryNode = (TryNode)tryNode.accept(new SimpleNodeVisitor() {
   16.42  
   16.43              @Override
   16.44              public boolean enterFunctionNode(final FunctionNode functionNode) {
   16.45 @@ -535,7 +529,7 @@
   16.46          final Block catchAll = catchAllBlock(tryNode);
   16.47  
   16.48          final List<ThrowNode> rethrows = new ArrayList<>(1);
   16.49 -        catchAll.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   16.50 +        catchAll.accept(new SimpleNodeVisitor() {
   16.51              @Override
   16.52              public boolean enterThrowNode(final ThrowNode throwNode) {
   16.53                  rethrows.add(throwNode);
   16.54 @@ -680,7 +674,7 @@
   16.55      private static boolean controlFlowEscapes(final LexicalContext lex, final Block loopBody) {
   16.56          final List<Node> escapes = new ArrayList<>();
   16.57  
   16.58 -        loopBody.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   16.59 +        loopBody.accept(new SimpleNodeVisitor() {
   16.60              @Override
   16.61              public Node leaveBreakNode(final BreakNode node) {
   16.62                  escapes.add(node);
    17.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Mon Sep 28 15:36:24 2015 -0700
    17.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Tue Oct 06 11:04:55 2015 -0700
    17.3 @@ -258,8 +258,7 @@
    17.4       */
    17.5      private Type popType(final Type expected) {
    17.6          final Type type = popType();
    17.7 -        assert type.isObject() && expected.isObject() ||
    17.8 -            type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
    17.9 +        assert type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
   17.10          return type;
   17.11      }
   17.12  
    18.1 --- a/src/jdk/nashorn/internal/codegen/ObjectCreator.java	Mon Sep 28 15:36:24 2015 -0700
    18.2 +++ b/src/jdk/nashorn/internal/codegen/ObjectCreator.java	Tue Oct 06 11:04:55 2015 -0700
    18.3 @@ -36,7 +36,7 @@
    18.4   * Base class for object creation code generation.
    18.5   * @param <T> value type
    18.6   */
    18.7 -public abstract class ObjectCreator<T> {
    18.8 +public abstract class ObjectCreator<T> implements CodeGenerator.SplitLiteralCreator {
    18.9  
   18.10      /** List of keys & symbols to initiate in this ObjectCreator */
   18.11      final List<MapTuple<T>> tuples;
   18.12 @@ -69,7 +69,23 @@
   18.13       * Generate code for making the object.
   18.14       * @param method Script method.
   18.15       */
   18.16 -    protected abstract void makeObject(final MethodEmitter method);
   18.17 +    public void makeObject(final MethodEmitter method) {
   18.18 +        createObject(method);
   18.19 +        // We need to store the object in a temporary slot as populateRange expects to load the
   18.20 +        // object from a slot (as it is also invoked within split methods). Note that this also
   18.21 +        // helps optimistic continuations to handle the stack in case an optimistic assumption
   18.22 +        // fails during initialization (see JDK-8079269).
   18.23 +        final int objectSlot = method.getUsedSlotsWithLiveTemporaries();
   18.24 +        final Type objectType = method.peekType();
   18.25 +        method.storeTemp(objectType, objectSlot);
   18.26 +        populateRange(method, objectType, objectSlot, 0, tuples.size());
   18.27 +    }
   18.28 +
   18.29 +    /**
   18.30 +     * Generate code for creating and initializing the object.
   18.31 +     * @param method the method emitter
   18.32 +     */
   18.33 +    protected abstract void createObject(final MethodEmitter method);
   18.34  
   18.35      /**
   18.36       * Construct the property map appropriate for the object.
   18.37 @@ -125,6 +141,12 @@
   18.38      }
   18.39  
   18.40      /**
   18.41 +     * Get the class of objects created by this ObjectCreator
   18.42 +     * @return class of created object
   18.43 +     */
   18.44 +    abstract protected Class<? extends ScriptObject> getAllocatorClass();
   18.45 +
   18.46 +    /**
   18.47       * Technique for loading an initial value. Defined by anonymous subclasses in code gen.
   18.48       *
   18.49       * @param value Value to load.
   18.50 @@ -145,29 +167,4 @@
   18.51      MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple) {
   18.52          return loadTuple(method, tuple, true);
   18.53      }
   18.54 -
   18.55 -    /**
   18.56 -     * If using optimistic typing, let the code generator realize that the newly created object on the stack
   18.57 -     * when DUP-ed will be the same value. Basically: {NEW, DUP, INVOKESPECIAL init, DUP} will leave a stack
   18.58 -     * load specification {unknown, unknown} on stack (that is "there's two values on the stack, but neither
   18.59 -     * comes from a known local load"). If there's an optimistic operation in the literal initializer,
   18.60 -     * OptimisticOperation.storeStack will allocate two temporary locals for it and store them as
   18.61 -     * {ASTORE 4, ASTORE 3}. If we instead do {NEW, DUP, INVOKESPECIAL init, ASTORE 3, ALOAD 3, DUP} we end up
   18.62 -     * with stack load specification {ALOAD 3, ALOAD 3} (as DUP can track that the value it duplicated came
   18.63 -     * from a local load), so if/when a continuation needs to be recreated from it, it'll be
   18.64 -     * able to emit ALOAD 3, ALOAD 3 to recreate the stack. If we didn't do this, deoptimization within an
   18.65 -     * object literal initialization could in rare cases cause an incompatible change in the shape of the
   18.66 -     * local variable table for the temporaries, e.g. in the following snippet where a variable is reassigned
   18.67 -     * to a wider type in an object initializer:
   18.68 -     * <code>var m = 1; var obj = {p0: m, p1: m = "foo", p2: m}</code>
   18.69 -     * @param method the current method emitter.
   18.70 -     */
   18.71 -    void helpOptimisticRecognizeDuplicateIdentity(final MethodEmitter method) {
   18.72 -        if (codegen.useOptimisticTypes()) {
   18.73 -            final Type objectType = method.peekType();
   18.74 -            final int tempSlot = method.defineTemporaryLocalVariable(objectType.getSlots());
   18.75 -            method.storeHidden(objectType, tempSlot);
   18.76 -            method.load(objectType, tempSlot);
   18.77 -        }
   18.78 -    }
   18.79  }
    19.1 --- a/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java	Mon Sep 28 15:36:24 2015 -0700
    19.2 +++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java	Tue Oct 06 11:04:55 2015 -0700
    19.3 @@ -42,7 +42,6 @@
    19.4  import jdk.nashorn.internal.ir.IfNode;
    19.5  import jdk.nashorn.internal.ir.IndexNode;
    19.6  import jdk.nashorn.internal.ir.JoinPredecessorExpression;
    19.7 -import jdk.nashorn.internal.ir.LexicalContext;
    19.8  import jdk.nashorn.internal.ir.LoopNode;
    19.9  import jdk.nashorn.internal.ir.Node;
   19.10  import jdk.nashorn.internal.ir.Optimistic;
   19.11 @@ -52,7 +51,7 @@
   19.12  import jdk.nashorn.internal.ir.UnaryNode;
   19.13  import jdk.nashorn.internal.ir.VarNode;
   19.14  import jdk.nashorn.internal.ir.WhileNode;
   19.15 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   19.16 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
   19.17  import jdk.nashorn.internal.parser.TokenType;
   19.18  import jdk.nashorn.internal.runtime.ScriptObject;
   19.19  
   19.20 @@ -61,7 +60,7 @@
   19.21   * must not ever be marked as optimistic, assigning narrowest non-invalidated types to program points from the
   19.22   * compilation environment, as well as initializing optimistic types of global properties for scripts.
   19.23   */
   19.24 -final class OptimisticTypesCalculator extends NodeVisitor<LexicalContext> {
   19.25 +final class OptimisticTypesCalculator extends SimpleNodeVisitor {
   19.26  
   19.27      final Compiler compiler;
   19.28  
   19.29 @@ -69,7 +68,6 @@
   19.30      final Deque<BitSet> neverOptimistic = new ArrayDeque<>();
   19.31  
   19.32      OptimisticTypesCalculator(final Compiler compiler) {
   19.33 -        super(new LexicalContext());
   19.34          this.compiler = compiler;
   19.35      }
   19.36  
    20.1 --- a/src/jdk/nashorn/internal/codegen/ProgramPoints.java	Mon Sep 28 15:36:24 2015 -0700
    20.2 +++ b/src/jdk/nashorn/internal/codegen/ProgramPoints.java	Tue Oct 06 11:04:55 2015 -0700
    20.3 @@ -37,25 +37,20 @@
    20.4  import jdk.nashorn.internal.ir.FunctionNode;
    20.5  import jdk.nashorn.internal.ir.IdentNode;
    20.6  import jdk.nashorn.internal.ir.IndexNode;
    20.7 -import jdk.nashorn.internal.ir.LexicalContext;
    20.8  import jdk.nashorn.internal.ir.Node;
    20.9  import jdk.nashorn.internal.ir.Optimistic;
   20.10  import jdk.nashorn.internal.ir.UnaryNode;
   20.11  import jdk.nashorn.internal.ir.VarNode;
   20.12 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   20.13 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
   20.14  
   20.15  /**
   20.16   * Find program points in the code that are needed for optimistic assumptions
   20.17   */
   20.18 -class ProgramPoints extends NodeVisitor<LexicalContext> {
   20.19 +class ProgramPoints extends SimpleNodeVisitor {
   20.20  
   20.21      private final IntDeque nextProgramPoint = new IntDeque();
   20.22      private final Set<Node> noProgramPoint = new HashSet<>();
   20.23  
   20.24 -    ProgramPoints() {
   20.25 -        super(new LexicalContext());
   20.26 -    }
   20.27 -
   20.28      private int next() {
   20.29          final int next = nextProgramPoint.getAndIncrement();
   20.30          if(next > MAX_PROGRAM_POINT_VALUE) {
    21.1 --- a/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java	Mon Sep 28 15:36:24 2015 -0700
    21.2 +++ b/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java	Tue Oct 06 11:04:55 2015 -0700
    21.3 @@ -29,20 +29,17 @@
    21.4  import java.util.List;
    21.5  import jdk.nashorn.internal.ir.CompileUnitHolder;
    21.6  import jdk.nashorn.internal.ir.FunctionNode;
    21.7 -import jdk.nashorn.internal.ir.LexicalContext;
    21.8  import jdk.nashorn.internal.ir.LiteralNode;
    21.9  import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
   21.10 -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
   21.11  import jdk.nashorn.internal.ir.Node;
   21.12 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   21.13 +import jdk.nashorn.internal.ir.ObjectNode;
   21.14 +import jdk.nashorn.internal.ir.Splittable;
   21.15 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
   21.16  
   21.17  /**
   21.18   * Base class for a node visitor that replaces {@link CompileUnit}s in {@link CompileUnitHolder}s.
   21.19   */
   21.20 -abstract class ReplaceCompileUnits extends NodeVisitor<LexicalContext> {
   21.21 -    ReplaceCompileUnits() {
   21.22 -        super(new LexicalContext());
   21.23 -    }
   21.24 +abstract class ReplaceCompileUnits extends SimpleNodeVisitor {
   21.25  
   21.26      /**
   21.27       * Override to provide a replacement for an old compile unit.
   21.28 @@ -70,15 +67,28 @@
   21.29      public Node leaveLiteralNode(final LiteralNode<?> node) {
   21.30          if (node instanceof ArrayLiteralNode) {
   21.31              final ArrayLiteralNode aln = (ArrayLiteralNode)node;
   21.32 -            if (aln.getUnits() == null) {
   21.33 +            if (aln.getSplitRanges() == null) {
   21.34                  return node;
   21.35              }
   21.36 -            final List<ArrayUnit> newArrayUnits = new ArrayList<>();
   21.37 -            for (final ArrayUnit au : aln.getUnits()) {
   21.38 -                newArrayUnits.add(new ArrayUnit(getExistingReplacement(au), au.getLo(), au.getHi()));
   21.39 +            final List<Splittable.SplitRange> newArrayUnits = new ArrayList<>();
   21.40 +            for (final Splittable.SplitRange au : aln.getSplitRanges()) {
   21.41 +                newArrayUnits.add(new Splittable.SplitRange(getExistingReplacement(au), au.getLow(), au.getHigh()));
   21.42              }
   21.43 -            return aln.setUnits(lc, newArrayUnits);
   21.44 +            return aln.setSplitRanges(lc, newArrayUnits);
   21.45          }
   21.46          return node;
   21.47      }
   21.48 +
   21.49 +    @Override
   21.50 +    public Node leaveObjectNode(final ObjectNode objectNode) {
   21.51 +        final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();
   21.52 +        if (ranges != null) {
   21.53 +            final List<Splittable.SplitRange> newRanges = new ArrayList<>();
   21.54 +            for (final Splittable.SplitRange range : ranges) {
   21.55 +                newRanges.add(new Splittable.SplitRange(getExistingReplacement(range), range.getLow(), range.getHigh()));
   21.56 +            }
   21.57 +            return objectNode.setSplitRanges(lc, newRanges);
   21.58 +        }
   21.59 +        return super.leaveObjectNode(objectNode);
   21.60 +    }
   21.61  }
    22.1 --- a/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Mon Sep 28 15:36:24 2015 -0700
    22.2 +++ b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java	Tue Oct 06 11:04:55 2015 -0700
    22.3 @@ -61,7 +61,7 @@
    22.4      }
    22.5  
    22.6      @Override
    22.7 -    protected void makeObject(final MethodEmitter method) {
    22.8 +    public void createObject(final MethodEmitter method) {
    22.9          assert !isScope() : "spill scope objects are not currently supported";
   22.10  
   22.11          final int          length        = tuples.size();
   22.12 @@ -69,9 +69,7 @@
   22.13          final int          spillLength   = ScriptObject.spillAllocationLength(length);
   22.14          final long[]       jpresetValues = dualFields ? new long[spillLength] : null;
   22.15          final Object[]     opresetValues = new Object[spillLength];
   22.16 -        final Set<Integer> postsetValues = new LinkedHashSet<>();
   22.17 -        final int          callSiteFlags = codegen.getCallSiteFlags();
   22.18 -        final Class<?>     objectClass   = dualFields ? JD.class : JO.class;
   22.19 +        final Class<?>     objectClass   = getAllocatorClass();
   22.20          ArrayData          arrayData     = ArrayData.allocate(ScriptRuntime.EMPTY_ARRAY);
   22.21  
   22.22          // Compute constant property values
   22.23 @@ -85,9 +83,7 @@
   22.24  
   22.25              if (value != null) {
   22.26                  final Object constantValue = LiteralNode.objectAsConstant(value);
   22.27 -                if (constantValue == LiteralNode.POSTSET_MARKER) {
   22.28 -                    postsetValues.add(pos);
   22.29 -                } else {
   22.30 +                if (constantValue != LiteralNode.POSTSET_MARKER) {
   22.31                      final Property property = propertyMap.findProperty(key);
   22.32                      if (property != null) {
   22.33                          // normal property key
   22.34 @@ -146,25 +142,34 @@
   22.35          // instantiate the script object with spill objects
   22.36          method.invoke(constructorNoLookup(objectClass, PropertyMap.class, long[].class, Object[].class));
   22.37  
   22.38 -        helpOptimisticRecognizeDuplicateIdentity(method);
   22.39 -
   22.40          // Set prefix array data if any
   22.41          if (arrayData.length() > 0) {
   22.42              method.dup();
   22.43              codegen.loadConstant(arrayData);
   22.44              method.invoke(virtualCallNoLookup(ScriptObject.class, "setArray", void.class, ArrayData.class));
   22.45          }
   22.46 +    }
   22.47 +
   22.48 +    @Override
   22.49 +    public void populateRange(final MethodEmitter method, final Type objectType, final int objectSlot, final int start, final int end) {
   22.50 +        final int  callSiteFlags = codegen.getCallSiteFlags();
   22.51 +        method.load(objectType, objectSlot);
   22.52  
   22.53          // set postfix values
   22.54 -        for (final int i : postsetValues) {
   22.55 +        for (int i = start; i < end; i++) {
   22.56              final MapTuple<Expression> tuple = tuples.get(i);
   22.57 +
   22.58 +            if (LiteralNode.isConstant(tuple.value)) {
   22.59 +                continue;
   22.60 +            }
   22.61 +
   22.62              final Property property = propertyMap.findProperty(tuple.key);
   22.63 +
   22.64              if (property == null) {
   22.65                  final int index = ArrayIndex.getArrayIndex(tuple.key);
   22.66                  assert ArrayIndex.isValidArrayIndex(index);
   22.67                  method.dup();
   22.68                  method.load(ArrayIndex.toLongIndex(index));
   22.69 -                //method.println("putting " + tuple + " into arraydata");
   22.70                  loadTuple(method, tuple);
   22.71                  method.dynamicSetIndex(callSiteFlags);
   22.72              } else {
   22.73 @@ -178,8 +183,7 @@
   22.74      @Override
   22.75      protected PropertyMap makeMap() {
   22.76          assert propertyMap == null : "property map already initialized";
   22.77 -        final boolean dualFields = codegen.useDualFields();
   22.78 -        final Class<? extends ScriptObject> clazz = dualFields ? JD.class : JO.class;
   22.79 +        final Class<? extends ScriptObject> clazz = getAllocatorClass();
   22.80          propertyMap = new MapCreator<>(clazz, tuples).makeSpillMap(false, codegen.useDualFields());
   22.81          return propertyMap;
   22.82      }
   22.83 @@ -188,4 +192,9 @@
   22.84      protected void loadValue(final Expression expr, final Type type) {
   22.85          codegen.loadExpressionAsType(expr, type);
   22.86      }
   22.87 +
   22.88 +    @Override
   22.89 +    protected Class<? extends ScriptObject> getAllocatorClass() {
   22.90 +        return codegen.useDualFields() ? JD.class : JO.class;
   22.91 +    }
   22.92  }
    23.1 --- a/src/jdk/nashorn/internal/codegen/Splitter.java	Mon Sep 28 15:36:24 2015 -0700
    23.2 +++ b/src/jdk/nashorn/internal/codegen/Splitter.java	Tue Oct 06 11:04:55 2015 -0700
    23.3 @@ -33,14 +33,15 @@
    23.4  import java.util.Map;
    23.5  import jdk.nashorn.internal.ir.Block;
    23.6  import jdk.nashorn.internal.ir.FunctionNode;
    23.7 -import jdk.nashorn.internal.ir.LexicalContext;
    23.8  import jdk.nashorn.internal.ir.LiteralNode;
    23.9  import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
   23.10 -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
   23.11  import jdk.nashorn.internal.ir.Node;
   23.12 +import jdk.nashorn.internal.ir.ObjectNode;
   23.13 +import jdk.nashorn.internal.ir.PropertyNode;
   23.14  import jdk.nashorn.internal.ir.SplitNode;
   23.15 +import jdk.nashorn.internal.ir.Splittable;
   23.16  import jdk.nashorn.internal.ir.Statement;
   23.17 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   23.18 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
   23.19  import jdk.nashorn.internal.runtime.Context;
   23.20  import jdk.nashorn.internal.runtime.logging.DebugLogger;
   23.21  import jdk.nashorn.internal.runtime.logging.Loggable;
   23.22 @@ -51,7 +52,7 @@
   23.23   * Split the IR into smaller compile units.
   23.24   */
   23.25  @Logger(name="splitter")
   23.26 -final class Splitter extends NodeVisitor<LexicalContext> implements Loggable {
   23.27 +final class Splitter extends SimpleNodeVisitor implements Loggable {
   23.28      /** Current compiler. */
   23.29      private final Compiler compiler;
   23.30  
   23.31 @@ -77,7 +78,6 @@
   23.32       * @param outermostCompileUnit  compile unit for outermost function, if non-lazy this is the script's compile unit
   23.33       */
   23.34      public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) {
   23.35 -        super(new LexicalContext());
   23.36          this.compiler             = compiler;
   23.37          this.outermost            = functionNode;
   23.38          this.outermostCompileUnit = outermostCompileUnit;
   23.39 @@ -140,7 +140,7 @@
   23.40          final Block body = functionNode.getBody();
   23.41          final List<FunctionNode> dc = directChildren(functionNode);
   23.42  
   23.43 -        final Block newBody = (Block)body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   23.44 +        final Block newBody = (Block)body.accept(new SimpleNodeVisitor() {
   23.45              @Override
   23.46              public boolean enterFunctionNode(final FunctionNode nestedFunction) {
   23.47                  return dc.contains(nestedFunction);
   23.48 @@ -162,7 +162,7 @@
   23.49  
   23.50      private static List<FunctionNode> directChildren(final FunctionNode functionNode) {
   23.51          final List<FunctionNode> dc = new ArrayList<>();
   23.52 -        functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   23.53 +        functionNode.accept(new SimpleNodeVisitor() {
   23.54              @Override
   23.55              public boolean enterFunctionNode(final FunctionNode child) {
   23.56                  if (child == functionNode) {
   23.57 @@ -295,7 +295,7 @@
   23.58              final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal;
   23.59              final Node[]           value            = arrayLiteralNode.getValue();
   23.60              final int[]            postsets         = arrayLiteralNode.getPostsets();
   23.61 -            final List<ArrayUnit>  units            = new ArrayList<>();
   23.62 +            final List<Splittable.SplitRange> ranges = new ArrayList<>();
   23.63  
   23.64              long totalWeight = 0;
   23.65              int  lo          = 0;
   23.66 @@ -309,7 +309,7 @@
   23.67  
   23.68                  if (totalWeight >= SPLIT_THRESHOLD) {
   23.69                      final CompileUnit unit = compiler.findUnit(totalWeight - weight);
   23.70 -                    units.add(new ArrayUnit(unit, lo, i));
   23.71 +                    ranges.add(new Splittable.SplitRange(unit, lo, i));
   23.72                      lo = i;
   23.73                      totalWeight = weight;
   23.74                  }
   23.75 @@ -317,16 +317,59 @@
   23.76  
   23.77              if (lo != postsets.length) {
   23.78                  final CompileUnit unit = compiler.findUnit(totalWeight);
   23.79 -                units.add(new ArrayUnit(unit, lo, postsets.length));
   23.80 +                ranges.add(new Splittable.SplitRange(unit, lo, postsets.length));
   23.81              }
   23.82  
   23.83 -            return arrayLiteralNode.setUnits(lc, units);
   23.84 +            return arrayLiteralNode.setSplitRanges(lc, ranges);
   23.85          }
   23.86  
   23.87          return literal;
   23.88      }
   23.89  
   23.90      @Override
   23.91 +    public Node leaveObjectNode(final ObjectNode objectNode) {
   23.92 +        long weight = WeighNodes.weigh(objectNode);
   23.93 +
   23.94 +        if (weight < SPLIT_THRESHOLD) {
   23.95 +            return objectNode;
   23.96 +        }
   23.97 +
   23.98 +        final FunctionNode functionNode = lc.getCurrentFunction();
   23.99 +        lc.setFlag(functionNode, FunctionNode.IS_SPLIT);
  23.100 +
  23.101 +        final List<Splittable.SplitRange> ranges        = new ArrayList<>();
  23.102 +        final List<PropertyNode>          properties    = objectNode.getElements();
  23.103 +        final boolean                     isSpillObject = properties.size() > CodeGenerator.OBJECT_SPILL_THRESHOLD;
  23.104 +        long totalWeight = 0;
  23.105 +        int  lo          = 0;
  23.106 +
  23.107 +        for (int i = 0; i < properties.size(); i++) {
  23.108 +
  23.109 +            final PropertyNode property = properties.get(i);
  23.110 +            final boolean isConstant = LiteralNode.isConstant(property.getValue());
  23.111 +
  23.112 +            if (!isConstant || !isSpillObject) {
  23.113 +                weight = isConstant ? 0 : WeighNodes.weigh(property.getValue());
  23.114 +                totalWeight += WeighNodes.AASTORE_WEIGHT + weight;
  23.115 +
  23.116 +                if (totalWeight >= SPLIT_THRESHOLD) {
  23.117 +                    final CompileUnit unit = compiler.findUnit(totalWeight - weight);
  23.118 +                    ranges.add(new Splittable.SplitRange(unit, lo, i));
  23.119 +                    lo = i;
  23.120 +                    totalWeight = weight;
  23.121 +                }
  23.122 +            }
  23.123 +        }
  23.124 +
  23.125 +        if (lo != properties.size()) {
  23.126 +            final CompileUnit unit = compiler.findUnit(totalWeight);
  23.127 +            ranges.add(new Splittable.SplitRange(unit, lo, properties.size()));
  23.128 +        }
  23.129 +
  23.130 +        return objectNode.setSplitRanges(lc, ranges);
  23.131 +    }
  23.132 +
  23.133 +    @Override
  23.134      public boolean enterFunctionNode(final FunctionNode node) {
  23.135          //only go into the function node for this splitter. any subfunctions are rejected
  23.136          return node == outermost;
    24.1 --- a/src/jdk/nashorn/internal/codegen/WeighNodes.java	Mon Sep 28 15:36:24 2015 -0700
    24.2 +++ b/src/jdk/nashorn/internal/codegen/WeighNodes.java	Tue Oct 06 11:04:55 2015 -0700
    24.3 @@ -44,12 +44,13 @@
    24.4  import jdk.nashorn.internal.ir.LexicalContext;
    24.5  import jdk.nashorn.internal.ir.LiteralNode;
    24.6  import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
    24.7 -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
    24.8  import jdk.nashorn.internal.ir.Node;
    24.9 +import jdk.nashorn.internal.ir.ObjectNode;
   24.10  import jdk.nashorn.internal.ir.PropertyNode;
   24.11  import jdk.nashorn.internal.ir.ReturnNode;
   24.12  import jdk.nashorn.internal.ir.RuntimeNode;
   24.13  import jdk.nashorn.internal.ir.SplitNode;
   24.14 +import jdk.nashorn.internal.ir.Splittable;
   24.15  import jdk.nashorn.internal.ir.SwitchNode;
   24.16  import jdk.nashorn.internal.ir.ThrowNode;
   24.17  import jdk.nashorn.internal.ir.TryNode;
   24.18 @@ -88,6 +89,8 @@
   24.19      static final long THROW_WEIGHT     =  2;
   24.20      static final long VAR_WEIGHT       = 40;
   24.21      static final long WITH_WEIGHT      =  8;
   24.22 +    static final long OBJECT_WEIGHT    = 16;
   24.23 +    static final long SETPROP_WEIGHT   =  5;
   24.24  
   24.25      /** Accumulated weight. */
   24.26      private long weight;
   24.27 @@ -213,7 +216,7 @@
   24.28              final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode)literalNode;
   24.29              final Node[]           value            = arrayLiteralNode.getValue();
   24.30              final int[]            postsets         = arrayLiteralNode.getPostsets();
   24.31 -            final List<ArrayUnit>  units            = arrayLiteralNode.getUnits();
   24.32 +            final List<Splittable.SplitRange>  units            = arrayLiteralNode.getSplitRanges();
   24.33  
   24.34              if (units == null) {
   24.35                  for (final int postset : postsets) {
   24.36 @@ -233,6 +236,27 @@
   24.37      }
   24.38  
   24.39      @Override
   24.40 +    public boolean enterObjectNode(final ObjectNode objectNode) {
   24.41 +        weight += OBJECT_WEIGHT;
   24.42 +        final List<PropertyNode> properties = objectNode.getElements();
   24.43 +        final boolean isSpillObject = properties.size() > CodeGenerator.OBJECT_SPILL_THRESHOLD;
   24.44 +
   24.45 +        for (final PropertyNode property : properties) {
   24.46 +            if (!LiteralNode.isConstant(property.getValue())) {
   24.47 +                weight += SETPROP_WEIGHT;
   24.48 +                property.getValue().accept(this);
   24.49 +            } else if (!isSpillObject) {
   24.50 +                // constants in spill object are set via preset spill array,
   24.51 +                // but fields objects need to set constants.
   24.52 +                weight += SETPROP_WEIGHT;
   24.53 +            }
   24.54 +
   24.55 +        }
   24.56 +
   24.57 +        return false;
   24.58 +    }
   24.59 +
   24.60 +    @Override
   24.61      public Node leavePropertyNode(final PropertyNode propertyNode) {
   24.62          weight += LITERAL_WEIGHT;
   24.63          return propertyNode;
    25.1 --- a/src/jdk/nashorn/internal/codegen/types/Type.java	Mon Sep 28 15:36:24 2015 -0700
    25.2 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java	Tue Oct 06 11:04:55 2015 -0700
    25.3 @@ -65,6 +65,7 @@
    25.4  import jdk.internal.org.objectweb.asm.Handle;
    25.5  import jdk.internal.org.objectweb.asm.MethodVisitor;
    25.6  import jdk.nashorn.internal.codegen.CompilerConstants.Call;
    25.7 +import jdk.nashorn.internal.runtime.Context;
    25.8  import jdk.nashorn.internal.runtime.ScriptObject;
    25.9  import jdk.nashorn.internal.runtime.Undefined;
   25.10  import jdk.nashorn.internal.runtime.linker.Bootstrap;
   25.11 @@ -256,6 +257,9 @@
   25.12          case jdk.internal.org.objectweb.asm.Type.DOUBLE:
   25.13              return NUMBER;
   25.14          case jdk.internal.org.objectweb.asm.Type.OBJECT:
   25.15 +            if (Context.isStructureClass(itype.getClassName())) {
   25.16 +                return SCRIPT_OBJECT;
   25.17 +            }
   25.18              try {
   25.19                  return Type.typeFor(Class.forName(itype.getClassName()));
   25.20              } catch(final ClassNotFoundException e) {
   25.21 @@ -949,7 +953,7 @@
   25.22      /**
   25.23       * This is the singleton for integer arrays
   25.24       */
   25.25 -    public static final ArrayType INT_ARRAY = new ArrayType(int[].class) {
   25.26 +    public static final ArrayType INT_ARRAY = putInCache(new ArrayType(int[].class) {
   25.27          private static final long serialVersionUID = 1L;
   25.28  
   25.29          @Override
   25.30 @@ -973,12 +977,12 @@
   25.31          public Type getElementType() {
   25.32              return INT;
   25.33          }
   25.34 -    };
   25.35 +    });
   25.36  
   25.37      /**
   25.38       * This is the singleton for long arrays
   25.39       */
   25.40 -    public static final ArrayType LONG_ARRAY = new ArrayType(long[].class) {
   25.41 +    public static final ArrayType LONG_ARRAY = putInCache(new ArrayType(long[].class) {
   25.42          private static final long serialVersionUID = 1L;
   25.43  
   25.44          @Override
   25.45 @@ -1002,12 +1006,12 @@
   25.46          public Type getElementType() {
   25.47              return LONG;
   25.48          }
   25.49 -    };
   25.50 +    });
   25.51  
   25.52      /**
   25.53       * This is the singleton for numeric arrays
   25.54       */
   25.55 -    public static final ArrayType NUMBER_ARRAY = new ArrayType(double[].class) {
   25.56 +    public static final ArrayType NUMBER_ARRAY = putInCache(new ArrayType(double[].class) {
   25.57          private static final long serialVersionUID = 1L;
   25.58  
   25.59          @Override
   25.60 @@ -1031,13 +1035,7 @@
   25.61          public Type getElementType() {
   25.62              return NUMBER;
   25.63          }
   25.64 -    };
   25.65 -
   25.66 -    /** Singleton for method handle arrays used for properties etc. */
   25.67 -    public static final ArrayType METHODHANDLE_ARRAY = putInCache(new ArrayType(MethodHandle[].class));
   25.68 -
   25.69 -    /** This is the singleton for string arrays */
   25.70 -    public static final ArrayType STRING_ARRAY = putInCache(new ArrayType(String[].class));
   25.71 +    });
   25.72  
   25.73      /** This is the singleton for object arrays */
   25.74      public static final ArrayType OBJECT_ARRAY = putInCache(new ArrayType(Object[].class));
    26.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java	Mon Sep 28 15:36:24 2015 -0700
    26.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java	Tue Oct 06 11:04:55 2015 -0700
    26.3 @@ -25,11 +25,9 @@
    26.4  
    26.5  package jdk.nashorn.internal.ir;
    26.6  
    26.7 -import java.io.Serializable;
    26.8  import java.util.Arrays;
    26.9  import java.util.Collections;
   26.10  import java.util.List;
   26.11 -import jdk.nashorn.internal.codegen.CompileUnit;
   26.12  import jdk.nashorn.internal.codegen.types.ArrayType;
   26.13  import jdk.nashorn.internal.codegen.types.Type;
   26.14  import jdk.nashorn.internal.ir.annotations.Immutable;
   26.15 @@ -561,6 +559,15 @@
   26.16          return POSTSET_MARKER;
   26.17      }
   26.18  
   26.19 +    /**
   26.20 +     * Test whether {@code object} represents a constant value.
   26.21 +     * @param object a node or value object
   26.22 +     * @return true if object is a constant value
   26.23 +     */
   26.24 +    public static boolean isConstant(final Object object) {
   26.25 +        return objectAsConstant(object) != POSTSET_MARKER;
   26.26 +    }
   26.27 +
   26.28      private static final class NullLiteralNode extends PrimitiveLiteralNode<Object> {
   26.29          private static final long serialVersionUID = 1L;
   26.30  
   26.31 @@ -592,7 +599,7 @@
   26.32       * Array literal node class.
   26.33       */
   26.34      @Immutable
   26.35 -    public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode {
   26.36 +    public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode, Splittable {
   26.37          private static final long serialVersionUID = 1L;
   26.38  
   26.39          /** Array element type. */
   26.40 @@ -604,59 +611,8 @@
   26.41          /** Indices of array elements requiring computed post sets. */
   26.42          private final int[] postsets;
   26.43  
   26.44 -        /** Sub units with indexes ranges, in which to split up code generation, for large literals */
   26.45 -        private final List<ArrayUnit> units;
   26.46 -
   26.47 -        /**
   26.48 -         * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can
   26.49 -         * be split if they are too large, for bytecode generation reasons
   26.50 -         */
   26.51 -        public static final class ArrayUnit implements CompileUnitHolder, Serializable {
   26.52 -            private static final long serialVersionUID = 1L;
   26.53 -
   26.54 -            /** Compile unit associated with the postsets range. */
   26.55 -            private final CompileUnit compileUnit;
   26.56 -
   26.57 -            /** postsets range associated with the unit (hi not inclusive). */
   26.58 -            private final int lo, hi;
   26.59 -
   26.60 -            /**
   26.61 -             * Constructor
   26.62 -             * @param compileUnit compile unit
   26.63 -             * @param lo lowest array index in unit
   26.64 -             * @param hi highest array index in unit + 1
   26.65 -             */
   26.66 -            public ArrayUnit(final CompileUnit compileUnit, final int lo, final int hi) {
   26.67 -                this.compileUnit = compileUnit;
   26.68 -                this.lo   = lo;
   26.69 -                this.hi   = hi;
   26.70 -            }
   26.71 -
   26.72 -            /**
   26.73 -             * Get the high index position of the ArrayUnit (non inclusive)
   26.74 -             * @return high index position
   26.75 -             */
   26.76 -            public int getHi() {
   26.77 -                return hi;
   26.78 -            }
   26.79 -
   26.80 -            /**
   26.81 -             * Get the low index position of the ArrayUnit (inclusive)
   26.82 -             * @return low index position
   26.83 -             */
   26.84 -            public int getLo() {
   26.85 -                return lo;
   26.86 -            }
   26.87 -
   26.88 -            /**
   26.89 -             * The array compile unit
   26.90 -             * @return array compile unit
   26.91 -             */
   26.92 -            @Override
   26.93 -            public CompileUnit getCompileUnit() {
   26.94 -                return compileUnit;
   26.95 -            }
   26.96 -        }
   26.97 +        /** Ranges for splitting up large literals in code generation */
   26.98 +        private final List<Splittable.SplitRange> splitRanges;
   26.99  
  26.100          private static final class ArrayLiteralInitializer {
  26.101  
  26.102 @@ -664,7 +620,7 @@
  26.103                  final Type elementType = computeElementType(node.value);
  26.104                  final int[] postsets = computePostsets(node.value);
  26.105                  final Object presets = computePresets(node.value, elementType, postsets);
  26.106 -                return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.units);
  26.107 +                return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.splitRanges);
  26.108              }
  26.109  
  26.110              private static Type computeElementType(final Expression[] value) {
  26.111 @@ -697,7 +653,7 @@
  26.112  
  26.113                  for (int i = 0; i < value.length; i++) {
  26.114                      final Expression element = value[i];
  26.115 -                    if (element == null || objectAsConstant(element) == POSTSET_MARKER) {
  26.116 +                    if (element == null || !isConstant(element)) {
  26.117                          computed[nComputed++] = i;
  26.118                      }
  26.119                  }
  26.120 @@ -814,19 +770,19 @@
  26.121              this.elementType = Type.UNKNOWN;
  26.122              this.presets     = null;
  26.123              this.postsets    = null;
  26.124 -            this.units       = null;
  26.125 +            this.splitRanges = null;
  26.126          }
  26.127  
  26.128          /**
  26.129           * Copy constructor
  26.130           * @param node source array literal node
  26.131           */
  26.132 -        private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<ArrayUnit> units) {
  26.133 +        private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<Splittable.SplitRange> splitRanges) {
  26.134              super(node, value);
  26.135              this.elementType = elementType;
  26.136              this.postsets    = postsets;
  26.137              this.presets     = presets;
  26.138 -            this.units       = units;
  26.139 +            this.splitRanges = splitRanges;
  26.140          }
  26.141  
  26.142          /**
  26.143 @@ -917,26 +873,27 @@
  26.144          }
  26.145  
  26.146          /**
  26.147 -         * Get the array units that make up this ArrayLiteral
  26.148 -         * @see ArrayUnit
  26.149 -         * @return list of array units
  26.150 +         * Get the split ranges for this ArrayLiteral, or null if this array does not have to be split.
  26.151 +         * @see Splittable.SplitRange
  26.152 +         * @return list of split ranges
  26.153           */
  26.154 -        public List<ArrayUnit> getUnits() {
  26.155 -            return units == null ? null : Collections.unmodifiableList(units);
  26.156 +        @Override
  26.157 +        public List<Splittable.SplitRange> getSplitRanges() {
  26.158 +            return splitRanges == null ? null : Collections.unmodifiableList(splitRanges);
  26.159          }
  26.160  
  26.161          /**
  26.162 -         * Set the ArrayUnits that make up this ArrayLiteral
  26.163 +         * Set the SplitRanges that make up this ArrayLiteral
  26.164           * @param lc lexical context
  26.165 -         * @see ArrayUnit
  26.166 -         * @param units list of array units
  26.167 -         * @return new or changed arrayliteralnode
  26.168 +         * @see Splittable.SplitRange
  26.169 +         * @param splitRanges list of split ranges
  26.170 +         * @return new or changed node
  26.171           */
  26.172 -        public ArrayLiteralNode setUnits(final LexicalContext lc, final List<ArrayUnit> units) {
  26.173 -            if (this.units == units) {
  26.174 +        public ArrayLiteralNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) {
  26.175 +            if (this.splitRanges == splitRanges) {
  26.176                  return this;
  26.177              }
  26.178 -            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
  26.179 +            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
  26.180          }
  26.181  
  26.182          @Override
  26.183 @@ -958,7 +915,7 @@
  26.184              if (this.value == value) {
  26.185                  return this;
  26.186              }
  26.187 -            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
  26.188 +            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
  26.189          }
  26.190  
  26.191          private ArrayLiteralNode setValue(final LexicalContext lc, final List<Expression> value) {
    27.1 --- a/src/jdk/nashorn/internal/ir/ObjectNode.java	Mon Sep 28 15:36:24 2015 -0700
    27.2 +++ b/src/jdk/nashorn/internal/ir/ObjectNode.java	Tue Oct 06 11:04:55 2015 -0700
    27.3 @@ -27,6 +27,7 @@
    27.4  
    27.5  import java.util.Collections;
    27.6  import java.util.List;
    27.7 +import java.util.RandomAccess;
    27.8  import jdk.nashorn.internal.codegen.types.Type;
    27.9  import jdk.nashorn.internal.ir.annotations.Immutable;
   27.10  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   27.11 @@ -35,12 +36,15 @@
   27.12   * IR representation of an object literal.
   27.13   */
   27.14  @Immutable
   27.15 -public final class ObjectNode extends Expression {
   27.16 +public final class ObjectNode extends Expression implements LexicalContextNode, Splittable {
   27.17      private static final long serialVersionUID = 1L;
   27.18  
   27.19      /** Literal elements. */
   27.20      private final List<PropertyNode> elements;
   27.21  
   27.22 +    /** Ranges for splitting large literals over multiple compile units in codegen. */
   27.23 +    private final List<Splittable.SplitRange> splitRanges;
   27.24 +
   27.25      /**
   27.26       * Constructor
   27.27       *
   27.28 @@ -51,19 +55,27 @@
   27.29      public ObjectNode(final long token, final int finish, final List<PropertyNode> elements) {
   27.30          super(token, finish);
   27.31          this.elements = elements;
   27.32 +        this.splitRanges = null;
   27.33 +        assert elements instanceof RandomAccess : "Splitting requires random access lists";
   27.34      }
   27.35  
   27.36 -    private ObjectNode(final ObjectNode objectNode, final List<PropertyNode> elements) {
   27.37 +    private ObjectNode(final ObjectNode objectNode, final List<PropertyNode> elements,
   27.38 +                       final List<Splittable.SplitRange> splitRanges ) {
   27.39          super(objectNode);
   27.40          this.elements = elements;
   27.41 +        this.splitRanges = splitRanges;
   27.42      }
   27.43  
   27.44      @Override
   27.45      public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
   27.46 +        return Acceptor.accept(this, visitor);
   27.47 +    }
   27.48 +
   27.49 +    @Override
   27.50 +    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
   27.51          if (visitor.enterObjectNode(this)) {
   27.52 -            return visitor.leaveObjectNode(setElements(Node.accept(visitor, elements)));
   27.53 +            return visitor.leaveObjectNode(setElements(lc, Node.accept(visitor, elements)));
   27.54          }
   27.55 -
   27.56          return this;
   27.57      }
   27.58  
   27.59 @@ -102,10 +114,35 @@
   27.60          return Collections.unmodifiableList(elements);
   27.61      }
   27.62  
   27.63 -    private ObjectNode setElements(final List<PropertyNode> elements) {
   27.64 +    private ObjectNode setElements(final LexicalContext lc, final List<PropertyNode> elements) {
   27.65          if (this.elements == elements) {
   27.66              return this;
   27.67          }
   27.68 -        return new ObjectNode(this, elements);
   27.69 +        return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, this.splitRanges));
   27.70      }
   27.71 +
   27.72 +    /**
   27.73 +     * Set the split ranges for this ObjectNode
   27.74 +     * @see Splittable.SplitRange
   27.75 +     * @param lc the lexical context
   27.76 +     * @param splitRanges list of split ranges
   27.77 +     * @return new or changed object node
   27.78 +     */
   27.79 +    public ObjectNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) {
   27.80 +        if (this.splitRanges == splitRanges) {
   27.81 +            return this;
   27.82 +        }
   27.83 +        return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, splitRanges));
   27.84 +    }
   27.85 +
   27.86 +    /**
   27.87 +     * Get the split ranges for this ObjectNode, or null if the object is not split.
   27.88 +     * @see Splittable.SplitRange
   27.89 +     * @return list of split ranges
   27.90 +     */
   27.91 +    @Override
   27.92 +    public List<Splittable.SplitRange> getSplitRanges() {
   27.93 +        return splitRanges == null ? null : Collections.unmodifiableList(splitRanges);
   27.94 +    }
   27.95 +
   27.96  }
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/src/jdk/nashorn/internal/ir/Splittable.java	Tue Oct 06 11:04:55 2015 -0700
    28.3 @@ -0,0 +1,95 @@
    28.4 +/*
    28.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    28.7 + *
    28.8 + * This code is free software; you can redistribute it and/or modify it
    28.9 + * under the terms of the GNU General Public License version 2 only, as
   28.10 + * published by the Free Software Foundation.  Oracle designates this
   28.11 + * particular file as subject to the "Classpath" exception as provided
   28.12 + * by Oracle in the LICENSE file that accompanied this code.
   28.13 + *
   28.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   28.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   28.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   28.17 + * version 2 for more details (a copy is included in the LICENSE file that
   28.18 + * accompanied this code).
   28.19 + *
   28.20 + * You should have received a copy of the GNU General Public License version
   28.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   28.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   28.23 + *
   28.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   28.25 + * or visit www.oracle.com if you need additional information or have any
   28.26 + * questions.
   28.27 + */
   28.28 +
   28.29 +package jdk.nashorn.internal.ir;
   28.30 +
   28.31 +import java.io.Serializable;
   28.32 +import java.util.List;
   28.33 +import jdk.nashorn.internal.codegen.CompileUnit;
   28.34 +
   28.35 +/**
   28.36 + * An interface for splittable expressions.
   28.37 + */
   28.38 +public interface Splittable {
   28.39 +
   28.40 +    /**
   28.41 +     * Get a list of split ranges for this splittable expression, or null
   28.42 +     * if the expression should not be split.
   28.43 +     *
   28.44 +     * @return a list of split ranges
   28.45 +     */
   28.46 +    List<SplitRange> getSplitRanges();
   28.47 +
   28.48 +    /**
   28.49 +     * A SplitRange is a range in a splittable expression. It defines the
   28.50 +     * boundaries of the split range and provides a compile unit for code generation.
   28.51 +     */
   28.52 +    final class SplitRange implements CompileUnitHolder, Serializable {
   28.53 +        private static final long serialVersionUID = 1L;
   28.54 +
   28.55 +        /** Compile unit associated with the postsets range. */
   28.56 +        private final CompileUnit compileUnit;
   28.57 +
   28.58 +        /** postsets range associated with the unit (hi not inclusive). */
   28.59 +        private final int low, high;
   28.60 +
   28.61 +        /**
   28.62 +         * Constructor
   28.63 +         * @param compileUnit compile unit
   28.64 +         * @param low lowest array index in unit
   28.65 +         * @param high highest array index in unit + 1
   28.66 +         */
   28.67 +        public SplitRange(final CompileUnit compileUnit, final int low, final int high) {
   28.68 +            this.compileUnit = compileUnit;
   28.69 +            this.low   = low;
   28.70 +            this.high   = high;
   28.71 +        }
   28.72 +
   28.73 +        /**
   28.74 +         * Get the high index position of the ArrayUnit (exclusive)
   28.75 +         * @return high index position
   28.76 +         */
   28.77 +        public int getHigh() {
   28.78 +            return high;
   28.79 +        }
   28.80 +
   28.81 +        /**
   28.82 +         * Get the low index position of the ArrayUnit (inclusive)
   28.83 +         * @return low index position
   28.84 +         */
   28.85 +        public int getLow() {
   28.86 +            return low;
   28.87 +        }
   28.88 +
   28.89 +        /**
   28.90 +         * The array compile unit
   28.91 +         * @return array compile unit
   28.92 +         */
   28.93 +        @Override
   28.94 +        public CompileUnit getCompileUnit() {
   28.95 +            return compileUnit;
   28.96 +        }
   28.97 +    }
   28.98 +}
    29.1 --- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Mon Sep 28 15:36:24 2015 -0700
    29.2 +++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Tue Oct 06 11:04:55 2015 -0700
    29.3 @@ -48,7 +48,6 @@
    29.4  import jdk.nashorn.internal.ir.IndexNode;
    29.5  import jdk.nashorn.internal.ir.JoinPredecessorExpression;
    29.6  import jdk.nashorn.internal.ir.LabelNode;
    29.7 -import jdk.nashorn.internal.ir.LexicalContext;
    29.8  import jdk.nashorn.internal.ir.LiteralNode;
    29.9  import jdk.nashorn.internal.ir.Node;
   29.10  import jdk.nashorn.internal.ir.ObjectNode;
   29.11 @@ -65,7 +64,7 @@
   29.12  import jdk.nashorn.internal.ir.VarNode;
   29.13  import jdk.nashorn.internal.ir.WhileNode;
   29.14  import jdk.nashorn.internal.ir.WithNode;
   29.15 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   29.16 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
   29.17  import jdk.nashorn.internal.parser.JSONParser;
   29.18  import jdk.nashorn.internal.parser.Lexer.RegexToken;
   29.19  import jdk.nashorn.internal.parser.Parser;
   29.20 @@ -77,7 +76,7 @@
   29.21  /**
   29.22   * This IR writer produces a JSON string that represents AST as a JSON string.
   29.23   */
   29.24 -public final class JSONWriter extends NodeVisitor<LexicalContext> {
   29.25 +public final class JSONWriter extends SimpleNodeVisitor {
   29.26  
   29.27      /**
   29.28       * Returns AST as JSON compatible string.
   29.29 @@ -939,7 +938,6 @@
   29.30      // Internals below
   29.31  
   29.32      private JSONWriter(final boolean includeLocation) {
   29.33 -        super(new LexicalContext());
   29.34          this.buf             = new StringBuilder();
   29.35          this.includeLocation = includeLocation;
   29.36      }
    30.1 --- a/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Mon Sep 28 15:36:24 2015 -0700
    30.2 +++ b/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Tue Oct 06 11:04:55 2015 -0700
    30.3 @@ -41,7 +41,6 @@
    30.4  import jdk.nashorn.internal.ir.JoinPredecessor;
    30.5  import jdk.nashorn.internal.ir.JoinPredecessorExpression;
    30.6  import jdk.nashorn.internal.ir.LabelNode;
    30.7 -import jdk.nashorn.internal.ir.LexicalContext;
    30.8  import jdk.nashorn.internal.ir.LocalVariableConversion;
    30.9  import jdk.nashorn.internal.ir.Node;
   30.10  import jdk.nashorn.internal.ir.SplitNode;
   30.11 @@ -53,7 +52,7 @@
   30.12  import jdk.nashorn.internal.ir.VarNode;
   30.13  import jdk.nashorn.internal.ir.WhileNode;
   30.14  import jdk.nashorn.internal.ir.WithNode;
   30.15 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
   30.16 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
   30.17  
   30.18  /**
   30.19   * Print out the AST as human readable source code.
   30.20 @@ -61,7 +60,7 @@
   30.21   *
   30.22   * see the flags --print-parse and --print-lower-parse
   30.23   */
   30.24 -public final class PrintVisitor extends NodeVisitor<LexicalContext> {
   30.25 +public final class PrintVisitor extends SimpleNodeVisitor {
   30.26      /** Tab width */
   30.27      private static final int TABWIDTH = 4;
   30.28  
   30.29 @@ -96,7 +95,6 @@
   30.30       * @param printTypes        should we print optimistic and inferred types?
   30.31       */
   30.32      public PrintVisitor(final boolean printLineNumbers, final boolean printTypes) {
   30.33 -        super(new LexicalContext());
   30.34          this.EOLN             = System.lineSeparator();
   30.35          this.sb               = new StringBuilder();
   30.36          this.printLineNumbers = printLineNumbers;
    31.1 --- a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Mon Sep 28 15:36:24 2015 -0700
    31.2 +++ b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Tue Oct 06 11:04:55 2015 -0700
    31.3 @@ -34,7 +34,7 @@
    31.4   * Like NodeVisitor but navigating further into operators.
    31.5   * @param <T> Lexical context class for this NodeOperatorVisitor
    31.6   */
    31.7 -public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> {
    31.8 +public abstract class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> {
    31.9      /**
   31.10       * Constructor
   31.11       *
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/src/jdk/nashorn/internal/ir/visitor/SimpleNodeVisitor.java	Tue Oct 06 11:04:55 2015 -0700
    32.3 @@ -0,0 +1,41 @@
    32.4 +/*
    32.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    32.7 + *
    32.8 + * This code is free software; you can redistribute it and/or modify it
    32.9 + * under the terms of the GNU General Public License version 2 only, as
   32.10 + * published by the Free Software Foundation.  Oracle designates this
   32.11 + * particular file as subject to the "Classpath" exception as provided
   32.12 + * by Oracle in the LICENSE file that accompanied this code.
   32.13 + *
   32.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   32.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   32.17 + * version 2 for more details (a copy is included in the LICENSE file that
   32.18 + * accompanied this code).
   32.19 + *
   32.20 + * You should have received a copy of the GNU General Public License version
   32.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   32.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   32.23 + *
   32.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   32.25 + * or visit www.oracle.com if you need additional information or have any
   32.26 + * questions.
   32.27 + */
   32.28 +
   32.29 +package jdk.nashorn.internal.ir.visitor;
   32.30 +
   32.31 +import jdk.nashorn.internal.ir.LexicalContext;
   32.32 +
   32.33 +/**
   32.34 + * Convenience base class for a {@link NodeVisitor} with a plain {@link LexicalContext}.
   32.35 + */
   32.36 +public abstract class SimpleNodeVisitor extends NodeVisitor<LexicalContext> {
   32.37 +
   32.38 +    /**
   32.39 +     * Creates a new simple node visitor.
   32.40 +     */
   32.41 +    public SimpleNodeVisitor() {
   32.42 +        super(new LexicalContext());
   32.43 +    }
   32.44 +}
    33.1 --- a/src/jdk/nashorn/internal/objects/Global.java	Mon Sep 28 15:36:24 2015 -0700
    33.2 +++ b/src/jdk/nashorn/internal/objects/Global.java	Tue Oct 06 11:04:55 2015 -0700
    33.3 @@ -928,8 +928,6 @@
    33.4      private ThreadLocal<ScriptContext> scontext;
    33.5      // current ScriptEngine associated - can be null.
    33.6      private ScriptEngine engine;
    33.7 -    // initial ScriptContext - can be null
    33.8 -    private volatile ScriptContext initscontext;
    33.9  
   33.10      // ES6 global lexical scope.
   33.11      private final LexicalScope lexicalScope;
   33.12 @@ -957,7 +955,7 @@
   33.13  
   33.14      private ScriptContext currentContext() {
   33.15          final ScriptContext sc = scontext != null? scontext.get() : null;
   33.16 -        return sc == null? initscontext : sc;
   33.17 +        return (sc != null)? sc : (engine != null? engine.getContext() : null);
   33.18      }
   33.19  
   33.20      @Override
   33.21 @@ -1067,16 +1065,14 @@
   33.22       * of the global scope object.
   33.23       *
   33.24       * @param eng ScriptEngine to initialize
   33.25 -     * @param ctxt ScriptContext to initialize
   33.26       */
   33.27 -    public void initBuiltinObjects(final ScriptEngine eng, final ScriptContext ctxt) {
   33.28 +    public void initBuiltinObjects(final ScriptEngine eng) {
   33.29          if (this.builtinObject != null) {
   33.30              // already initialized, just return
   33.31              return;
   33.32          }
   33.33  
   33.34          this.engine = eng;
   33.35 -        this.initscontext = ctxt;
   33.36          if (this.engine != null) {
   33.37              this.scontext = new ThreadLocal<>();
   33.38          }
    34.1 --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Mon Sep 28 15:36:24 2015 -0700
    34.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Tue Oct 06 11:04:55 2015 -0700
    34.3 @@ -627,7 +627,7 @@
    34.4                      return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
    34.5                              func.createBound(this, new Object[] { name })), 0, Object.class),
    34.6                              testJSAdaptor(adaptee, null, null, null),
    34.7 -                            adaptee.getProtoSwitchPoint(__call__, find.getOwner()));
    34.8 +                            adaptee.getProtoSwitchPoints(__call__, find.getOwner()), null);
    34.9                  }
   34.10              }
   34.11              throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
   34.12 @@ -698,7 +698,7 @@
   34.13                      return new GuardedInvocation(
   34.14                              methodHandle,
   34.15                              testJSAdaptor(adaptee, findData.getGetter(Object.class, INVALID_PROGRAM_POINT, null), findData.getOwner(), func),
   34.16 -                            adaptee.getProtoSwitchPoint(hook, findData.getOwner()));
   34.17 +                            adaptee.getProtoSwitchPoints(hook, findData.getOwner()), null);
   34.18                  }
   34.19               }
   34.20          }
   34.21 @@ -710,7 +710,7 @@
   34.22              final MethodHandle methodHandle = hook.equals(__put__) ?
   34.23              MH.asType(Lookup.EMPTY_SETTER, type) :
   34.24              Lookup.emptyGetter(type.returnType());
   34.25 -            return new GuardedInvocation(methodHandle, testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoint(hook, null));
   34.26 +            return new GuardedInvocation(methodHandle, testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoints(hook, null), null);
   34.27          }
   34.28      }
   34.29  
    35.1 --- a/src/jdk/nashorn/internal/objects/NativeNumber.java	Mon Sep 28 15:36:24 2015 -0700
    35.2 +++ b/src/jdk/nashorn/internal/objects/NativeNumber.java	Tue Oct 06 11:04:55 2015 -0700
    35.3 @@ -33,6 +33,7 @@
    35.4  import java.lang.invoke.MethodHandle;
    35.5  import java.lang.invoke.MethodHandles;
    35.6  import java.lang.invoke.MethodType;
    35.7 +import java.math.RoundingMode;
    35.8  import java.text.NumberFormat;
    35.9  import java.util.Locale;
   35.10  import jdk.internal.dynalink.linker.GuardedInvocation;
   35.11 @@ -187,6 +188,7 @@
   35.12          format.setMinimumFractionDigits(fractionDigits);
   35.13          format.setMaximumFractionDigits(fractionDigits);
   35.14          format.setGroupingUsed(false);
   35.15 +        format.setRoundingMode(RoundingMode.HALF_UP);
   35.16  
   35.17          return format.format(x);
   35.18      }
    36.1 --- a/src/jdk/nashorn/internal/runtime/AllocationStrategy.java	Mon Sep 28 15:36:24 2015 -0700
    36.2 +++ b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java	Tue Oct 06 11:04:55 2015 -0700
    36.3 @@ -29,6 +29,7 @@
    36.4  import java.io.Serializable;
    36.5  import java.lang.invoke.MethodHandle;
    36.6  import java.lang.invoke.MethodHandles;
    36.7 +import java.lang.ref.WeakReference;
    36.8  import jdk.nashorn.internal.codegen.Compiler;
    36.9  import jdk.nashorn.internal.codegen.CompilerConstants;
   36.10  import jdk.nashorn.internal.codegen.ObjectClassGenerator;
   36.11 @@ -53,6 +54,9 @@
   36.12      /** lazily generated allocator */
   36.13      private transient MethodHandle allocator;
   36.14  
   36.15 +    /** Last used allocator map */
   36.16 +    private transient AllocatorMap lastMap;
   36.17 +
   36.18      /**
   36.19       * Construct an allocation strategy with the given map and class name.
   36.20       * @param fieldCount number of fields in the allocated object
   36.21 @@ -71,11 +75,49 @@
   36.22          return allocatorClassName;
   36.23      }
   36.24  
   36.25 -    PropertyMap getAllocatorMap() {
   36.26 -        // Create a new map for each function instance
   36.27 -        return PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0);
   36.28 +    /**
   36.29 +     * Get the property map for the allocated object.
   36.30 +     * @param prototype the prototype object
   36.31 +     * @return the property map
   36.32 +     */
   36.33 +    synchronized PropertyMap getAllocatorMap(final ScriptObject prototype) {
   36.34 +        assert prototype != null;
   36.35 +        final PropertyMap protoMap = prototype.getMap();
   36.36 +
   36.37 +        if (lastMap != null) {
   36.38 +            if (!lastMap.hasSharedProtoMap()) {
   36.39 +                if (lastMap.hasSamePrototype(prototype)) {
   36.40 +                    return lastMap.allocatorMap;
   36.41 +                }
   36.42 +                if (lastMap.hasSameProtoMap(protoMap) && lastMap.hasUnchangedProtoMap()) {
   36.43 +                    // Convert to shared prototype map. Allocated objects will use the same property map
   36.44 +                    // that can be used as long as none of the prototypes modify the shared proto map.
   36.45 +                    final PropertyMap allocatorMap = PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0);
   36.46 +                    final SharedPropertyMap sharedProtoMap = new SharedPropertyMap(protoMap);
   36.47 +                    allocatorMap.setSharedProtoMap(sharedProtoMap);
   36.48 +                    prototype.setMap(sharedProtoMap);
   36.49 +                    lastMap = new AllocatorMap(prototype, protoMap, allocatorMap);
   36.50 +                    return allocatorMap;
   36.51 +                }
   36.52 +            }
   36.53 +
   36.54 +            if (lastMap.hasValidSharedProtoMap() && lastMap.hasSameProtoMap(protoMap)) {
   36.55 +                prototype.setMap(lastMap.getSharedProtoMap());
   36.56 +                return lastMap.allocatorMap;
   36.57 +            }
   36.58 +        }
   36.59 +
   36.60 +        final PropertyMap allocatorMap = PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0);
   36.61 +        lastMap = new AllocatorMap(prototype, protoMap, allocatorMap);
   36.62 +
   36.63 +        return allocatorMap;
   36.64      }
   36.65  
   36.66 +    /**
   36.67 +     * Allocate an object with the given property map
   36.68 +     * @param map the property map
   36.69 +     * @return the allocated object
   36.70 +     */
   36.71      ScriptObject allocate(final PropertyMap map) {
   36.72          try {
   36.73              if (allocator == null) {
   36.74 @@ -94,4 +136,43 @@
   36.75      public String toString() {
   36.76          return "AllocationStrategy[fieldCount=" + fieldCount + "]";
   36.77      }
   36.78 +
   36.79 +    static class AllocatorMap {
   36.80 +        final private WeakReference<ScriptObject> prototype;
   36.81 +        final private WeakReference<PropertyMap> prototypeMap;
   36.82 +
   36.83 +        private PropertyMap allocatorMap;
   36.84 +
   36.85 +        AllocatorMap(final ScriptObject prototype, final PropertyMap protoMap, final PropertyMap allocMap) {
   36.86 +            this.prototype = new WeakReference<>(prototype);
   36.87 +            this.prototypeMap = new WeakReference<>(protoMap);
   36.88 +            this.allocatorMap = allocMap;
   36.89 +        }
   36.90 +
   36.91 +        boolean hasSamePrototype(final ScriptObject proto) {
   36.92 +            return prototype.get() == proto;
   36.93 +        }
   36.94 +
   36.95 +        boolean hasSameProtoMap(final PropertyMap protoMap) {
   36.96 +            return prototypeMap.get() == protoMap || allocatorMap.getSharedProtoMap() == protoMap;
   36.97 +        }
   36.98 +
   36.99 +        boolean hasUnchangedProtoMap() {
  36.100 +            final ScriptObject proto = prototype.get();
  36.101 +            return proto != null && proto.getMap() == prototypeMap.get();
  36.102 +        }
  36.103 +
  36.104 +        boolean hasSharedProtoMap() {
  36.105 +            return getSharedProtoMap() != null;
  36.106 +        }
  36.107 +
  36.108 +        boolean hasValidSharedProtoMap() {
  36.109 +            return hasSharedProtoMap() && getSharedProtoMap().isValidSharedProtoMap();
  36.110 +        }
  36.111 +
  36.112 +        PropertyMap getSharedProtoMap() {
  36.113 +            return allocatorMap.getSharedProtoMap();
  36.114 +        }
  36.115 +
  36.116 +    }
  36.117  }
    37.1 --- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Mon Sep 28 15:36:24 2015 -0700
    37.2 +++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Tue Oct 06 11:04:55 2015 -0700
    37.3 @@ -38,15 +38,14 @@
    37.4   * The compiler still retains most of the state around code emission
    37.5   * and management internally, so this is to avoid passing around any
    37.6   * logic that isn't directly related to installing a class
    37.7 - * @param <T> owner class type for this code installer
    37.8   *
    37.9   */
   37.10 -public interface CodeInstaller<T> {
   37.11 +public interface CodeInstaller {
   37.12      /**
   37.13 -     * Return the owner for the CodeInstaller, e.g. a {@link Context}
   37.14 -     * @return owner
   37.15 +     * Return the {@link Context} associated with this code installer.
   37.16 +     * @return the context.
   37.17       */
   37.18 -    public T getOwner();
   37.19 +    public Context getContext();
   37.20  
   37.21      /**
   37.22       * Install a class.
   37.23 @@ -106,7 +105,7 @@
   37.24       * new, independent class loader.
   37.25       * @return a new code installer with a new independent class loader.
   37.26       */
   37.27 -    public CodeInstaller<T> withNewLoader();
   37.28 +    public CodeInstaller withNewLoader();
   37.29  
   37.30      /**
   37.31       * Returns true if this code installer is compatible with the other code installer. Compatibility is expected to be
   37.32 @@ -115,6 +114,6 @@
   37.33       * @param other the other code installer tested for compatibility with this code installer.
   37.34       * @return true if this code installer is compatible with the other code installer.
   37.35       */
   37.36 -    public boolean isCompatibleWith(CodeInstaller<T> other);
   37.37 +    public boolean isCompatibleWith(CodeInstaller other);
   37.38  
   37.39  }
    38.1 --- a/src/jdk/nashorn/internal/runtime/Context.java	Mon Sep 28 15:36:24 2015 -0700
    38.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java	Tue Oct 06 11:04:55 2015 -0700
    38.3 @@ -167,7 +167,7 @@
    38.4       * ContextCodeInstaller that has the privilege of installing classes in the Context.
    38.5       * Can only be instantiated from inside the context and is opaque to other classes
    38.6       */
    38.7 -    public static class ContextCodeInstaller implements CodeInstaller<ScriptEnvironment> {
    38.8 +    public static class ContextCodeInstaller implements CodeInstaller {
    38.9          private final Context      context;
   38.10          private final ScriptLoader loader;
   38.11          private final CodeSource   codeSource;
   38.12 @@ -185,13 +185,9 @@
   38.13              this.codeSource = codeSource;
   38.14          }
   38.15  
   38.16 -        /**
   38.17 -         * Return the script environment for this installer
   38.18 -         * @return ScriptEnvironment
   38.19 -         */
   38.20          @Override
   38.21 -        public ScriptEnvironment getOwner() {
   38.22 -            return context.env;
   38.23 +        public Context getContext() {
   38.24 +            return context;
   38.25          }
   38.26  
   38.27          @Override
   38.28 @@ -254,7 +250,7 @@
   38.29          }
   38.30  
   38.31          @Override
   38.32 -        public CodeInstaller<ScriptEnvironment> withNewLoader() {
   38.33 +        public CodeInstaller withNewLoader() {
   38.34              // Reuse this installer if we're within our limits.
   38.35              if (usageCount < MAX_USAGES && bytesDefined < MAX_BYTES_DEFINED) {
   38.36                  return this;
   38.37 @@ -263,7 +259,7 @@
   38.38          }
   38.39  
   38.40          @Override
   38.41 -        public boolean isCompatibleWith(final CodeInstaller<ScriptEnvironment> other) {
   38.42 +        public boolean isCompatibleWith(final CodeInstaller other) {
   38.43              if (other instanceof ContextCodeInstaller) {
   38.44                  final ContextCodeInstaller cci = (ContextCodeInstaller)other;
   38.45                  return cci.context == context && cci.codeSource == codeSource;
   38.46 @@ -987,6 +983,16 @@
   38.47      }
   38.48  
   38.49      /**
   38.50 +     * Is {@code className} the name of a structure class?
   38.51 +     *
   38.52 +     * @param className a class name
   38.53 +     * @return true if className is a structure class name
   38.54 +     */
   38.55 +    public static boolean isStructureClass(final String className) {
   38.56 +        return StructureLoader.isStructureClass(className);
   38.57 +    }
   38.58 +
   38.59 +    /**
   38.60       * Checks that the given Class can be accessed from no permissions context.
   38.61       *
   38.62       * @param clazz Class object
   38.63 @@ -1129,17 +1135,16 @@
   38.64       *
   38.65       * @param global the global
   38.66       * @param engine the associated ScriptEngine instance, can be null
   38.67 -     * @param ctxt the initial ScriptContext, can be null
   38.68       * @return the initialized global scope object.
   38.69       */
   38.70 -    public Global initGlobal(final Global global, final ScriptEngine engine, final ScriptContext ctxt) {
   38.71 +    public Global initGlobal(final Global global, final ScriptEngine engine) {
   38.72          // Need only minimal global object, if we are just compiling.
   38.73          if (!env._compile_only) {
   38.74              final Global oldGlobal = Context.getGlobal();
   38.75              try {
   38.76                  Context.setGlobal(global);
   38.77                  // initialize global scope with builtin global objects
   38.78 -                global.initBuiltinObjects(engine, ctxt);
   38.79 +                global.initBuiltinObjects(engine);
   38.80              } finally {
   38.81                  Context.setGlobal(oldGlobal);
   38.82              }
   38.83 @@ -1155,7 +1160,7 @@
   38.84       * @return the initialized global scope object.
   38.85       */
   38.86      public Global initGlobal(final Global global) {
   38.87 -        return initGlobal(global, null, null);
   38.88 +        return initGlobal(global, null);
   38.89      }
   38.90  
   38.91      /**
   38.92 @@ -1300,14 +1305,12 @@
   38.93          final URL          url    = source.getURL();
   38.94          final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
   38.95          final CodeSource   cs     = new CodeSource(url, (CodeSigner[])null);
   38.96 -        final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
   38.97 +        final CodeInstaller installer = new ContextCodeInstaller(this, loader, cs);
   38.98  
   38.99          if (storedScript == null) {
  38.100              final CompilationPhases phases = Compiler.CompilationPhases.COMPILE_ALL;
  38.101  
  38.102 -            final Compiler compiler = new Compiler(
  38.103 -                    this,
  38.104 -                    env,
  38.105 +            final Compiler compiler = Compiler.forInitialCompilation(
  38.106                      installer,
  38.107                      source,
  38.108                      errMan,
    39.1 --- a/src/jdk/nashorn/internal/runtime/Debug.java	Mon Sep 28 15:36:24 2015 -0700
    39.2 +++ b/src/jdk/nashorn/internal/runtime/Debug.java	Tue Oct 06 11:04:55 2015 -0700
    39.3 @@ -26,6 +26,8 @@
    39.4  package jdk.nashorn.internal.runtime;
    39.5  
    39.6  import static jdk.nashorn.internal.parser.TokenType.EOF;
    39.7 +
    39.8 +import jdk.nashorn.api.scripting.NashornException;
    39.9  import jdk.nashorn.internal.parser.Lexer;
   39.10  import jdk.nashorn.internal.parser.Token;
   39.11  import jdk.nashorn.internal.parser.TokenStream;
   39.12 @@ -63,6 +65,15 @@
   39.13      }
   39.14  
   39.15      /**
   39.16 +     * Return a formatted script stack trace string with frames information separated by '\n'.
   39.17 +     * This is a shortcut for {@code NashornException.getScriptStackString(new Throwable())}.
   39.18 +     * @return formatted stack trace string
   39.19 +     */
   39.20 +    public static String scriptStack() {
   39.21 +        return NashornException.getScriptStackString(new Throwable());
   39.22 +    }
   39.23 +
   39.24 +    /**
   39.25       * Return the system identity hashcode for an object as a human readable
   39.26       * string
   39.27       *
    40.1 --- a/src/jdk/nashorn/internal/runtime/PropertyListeners.java	Mon Sep 28 15:36:24 2015 -0700
    40.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyListeners.java	Tue Oct 06 11:04:55 2015 -0700
    40.3 @@ -75,16 +75,20 @@
    40.4      }
    40.5  
    40.6      /**
    40.7 -     * Return listeners added to this ScriptObject.
    40.8 +     * Return number of listeners added to a ScriptObject.
    40.9       * @param obj the object
   40.10       * @return the listener count
   40.11       */
   40.12      public static int getListenerCount(final ScriptObject obj) {
   40.13 -        final PropertyListeners propertyListeners = obj.getMap().getListeners();
   40.14 -        if (propertyListeners != null) {
   40.15 -            return propertyListeners.listeners == null ? 0 : propertyListeners.listeners.size();
   40.16 -        }
   40.17 -        return 0;
   40.18 +        return obj.getMap().getListenerCount();
   40.19 +    }
   40.20 +
   40.21 +    /**
   40.22 +     * Return the number of listeners added to this PropertyListeners instance.
   40.23 +     * @return the listener count;
   40.24 +     */
   40.25 +    public int getListenerCount() {
   40.26 +        return listeners == null ? 0 : listeners.size();
   40.27      }
   40.28  
   40.29      // Property listener management methods
   40.30 @@ -156,7 +160,7 @@
   40.31              final WeakPropertyMapSet set = listeners.get(prop.getKey());
   40.32              if (set != null) {
   40.33                  for (final PropertyMap propertyMap : set.elements()) {
   40.34 -                    propertyMap.propertyAdded(prop);
   40.35 +                    propertyMap.propertyAdded(prop, false);
   40.36                  }
   40.37                  listeners.remove(prop.getKey());
   40.38                  if (Context.DEBUG) {
   40.39 @@ -176,7 +180,7 @@
   40.40              final WeakPropertyMapSet set = listeners.get(prop.getKey());
   40.41              if (set != null) {
   40.42                  for (final PropertyMap propertyMap : set.elements()) {
   40.43 -                    propertyMap.propertyDeleted(prop);
   40.44 +                    propertyMap.propertyDeleted(prop, false);
   40.45                  }
   40.46                  listeners.remove(prop.getKey());
   40.47                  if (Context.DEBUG) {
   40.48 @@ -198,7 +202,7 @@
   40.49              final WeakPropertyMapSet set = listeners.get(oldProp.getKey());
   40.50              if (set != null) {
   40.51                  for (final PropertyMap propertyMap : set.elements()) {
   40.52 -                    propertyMap.propertyModified(oldProp, newProp);
   40.53 +                    propertyMap.propertyModified(oldProp, newProp, false);
   40.54                  }
   40.55                  listeners.remove(oldProp.getKey());
   40.56                  if (Context.DEBUG) {
   40.57 @@ -215,7 +219,7 @@
   40.58          if (listeners != null) {
   40.59              for (final WeakPropertyMapSet set : listeners.values()) {
   40.60                  for (final PropertyMap propertyMap : set.elements()) {
   40.61 -                    propertyMap.protoChanged();
   40.62 +                    propertyMap.protoChanged(false);
   40.63                  }
   40.64              }
   40.65              listeners.clear();
    41.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java	Mon Sep 28 15:36:24 2015 -0700
    41.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java	Tue Oct 06 11:04:55 2015 -0700
    41.3 @@ -34,7 +34,9 @@
    41.4  import java.io.ObjectOutputStream;
    41.5  import java.io.Serializable;
    41.6  import java.lang.invoke.SwitchPoint;
    41.7 +import java.lang.ref.Reference;
    41.8  import java.lang.ref.SoftReference;
    41.9 +import java.lang.ref.WeakReference;
   41.10  import java.util.Arrays;
   41.11  import java.util.BitSet;
   41.12  import java.util.Collection;
   41.13 @@ -43,6 +45,7 @@
   41.14  import java.util.NoSuchElementException;
   41.15  import java.util.WeakHashMap;
   41.16  import java.util.concurrent.atomic.LongAdder;
   41.17 +import jdk.nashorn.internal.runtime.options.Options;
   41.18  import jdk.nashorn.internal.scripts.JO;
   41.19  
   41.20  /**
   41.21 @@ -54,35 +57,49 @@
   41.22   * All property maps are immutable. If a property is added, modified or removed, the mutator
   41.23   * will return a new map.
   41.24   */
   41.25 -public final class PropertyMap implements Iterable<Object>, Serializable {
   41.26 +public class PropertyMap implements Iterable<Object>, Serializable {
   41.27 +    private static final int INITIAL_SOFT_REFERENCE_DERIVATION_LIMIT =
   41.28 +            Math.max(0, Options.getIntProperty("nashorn.propertyMap.softReferenceDerivationLimit", 32));
   41.29 +
   41.30      /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
   41.31 -    public static final int NOT_EXTENSIBLE        = 0b0000_0001;
   41.32 +    private static final int NOT_EXTENSIBLE         = 0b0000_0001;
   41.33      /** Does this map contain valid array keys? */
   41.34 -    public static final int CONTAINS_ARRAY_KEYS   = 0b0000_0010;
   41.35 +    private static final int CONTAINS_ARRAY_KEYS    = 0b0000_0010;
   41.36  
   41.37      /** Map status flags. */
   41.38 -    private int flags;
   41.39 +    private final int flags;
   41.40  
   41.41      /** Map of properties. */
   41.42      private transient PropertyHashMap properties;
   41.43  
   41.44      /** Number of fields in use. */
   41.45 -    private int fieldCount;
   41.46 +    private final int fieldCount;
   41.47  
   41.48      /** Number of fields available. */
   41.49      private final int fieldMaximum;
   41.50  
   41.51      /** Length of spill in use. */
   41.52 -    private int spillLength;
   41.53 +    private final int spillLength;
   41.54  
   41.55      /** Structure class name */
   41.56 -    private String className;
   41.57 +    private final String className;
   41.58 +
   41.59 +    /**
   41.60 +     * Countdown of number of times this property map has been derived from another property map. When it
   41.61 +     * reaches zero, the property map will start using weak references instead of soft references to hold on
   41.62 +     * to its history elements.
   41.63 +     */
   41.64 +    private final int softReferenceDerivationLimit;
   41.65 +
   41.66 +    /** A reference to the expected shared prototype property map. If this is set this
   41.67 +     * property map should only be used if it the same as the actual prototype map. */
   41.68 +    private transient SharedPropertyMap sharedProtoMap;
   41.69  
   41.70      /** {@link SwitchPoint}s for gets on inherited properties. */
   41.71 -    private transient HashMap<String, SwitchPoint> protoGetSwitches;
   41.72 +    private transient HashMap<String, SwitchPoint> protoSwitches;
   41.73  
   41.74      /** History of maps, used to limit map duplication. */
   41.75 -    private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
   41.76 +    private transient WeakHashMap<Property, Reference<PropertyMap>> history;
   41.77  
   41.78      /** History of prototypes, used to limit map duplication. */
   41.79      private transient WeakHashMap<ScriptObject, SoftReference<PropertyMap>> protoHistory;
   41.80 @@ -95,24 +112,22 @@
   41.81      private static final long serialVersionUID = -7041836752008732533L;
   41.82  
   41.83      /**
   41.84 -     * Constructor.
   41.85 +     * Constructs a new property map.
   41.86       *
   41.87       * @param properties   A {@link PropertyHashMap} with initial contents.
   41.88       * @param fieldCount   Number of fields in use.
   41.89       * @param fieldMaximum Number of fields available.
   41.90       * @param spillLength  Number of spill slots used.
   41.91 -     * @param containsArrayKeys True if properties contain numeric keys
   41.92       */
   41.93 -    private PropertyMap(final PropertyHashMap properties, final String className, final int fieldCount,
   41.94 -                        final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) {
   41.95 +    private PropertyMap(final PropertyHashMap properties, final int flags, final String className,
   41.96 +                        final int fieldCount, final int fieldMaximum, final int spillLength) {
   41.97          this.properties   = properties;
   41.98          this.className    = className;
   41.99          this.fieldCount   = fieldCount;
  41.100          this.fieldMaximum = fieldMaximum;
  41.101          this.spillLength  = spillLength;
  41.102 -        if (containsArrayKeys) {
  41.103 -            setContainsArrayKeys();
  41.104 -        }
  41.105 +        this.flags        = flags;
  41.106 +        this.softReferenceDerivationLimit = INITIAL_SOFT_REFERENCE_DERIVATION_LIMIT;
  41.107  
  41.108          if (Context.DEBUG) {
  41.109              count.increment();
  41.110 @@ -120,20 +135,23 @@
  41.111      }
  41.112  
  41.113      /**
  41.114 -     * Cloning constructor.
  41.115 +     * Constructs a clone of {@code propertyMap} with changed properties, flags, or boundaries.
  41.116       *
  41.117       * @param propertyMap Existing property map.
  41.118       * @param properties  A {@link PropertyHashMap} with a new set of properties.
  41.119       */
  41.120 -    private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) {
  41.121 +    private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties, final int flags, final int fieldCount, final int spillLength, final int softReferenceDerivationLimit) {
  41.122          this.properties   = properties;
  41.123 -        this.flags        = propertyMap.flags;
  41.124 -        this.spillLength  = propertyMap.spillLength;
  41.125 -        this.fieldCount   = propertyMap.fieldCount;
  41.126 +        this.flags        = flags;
  41.127 +        this.spillLength  = spillLength;
  41.128 +        this.fieldCount   = fieldCount;
  41.129          this.fieldMaximum = propertyMap.fieldMaximum;
  41.130 +        this.className    = propertyMap.className;
  41.131          // We inherit the parent property listeners instance. It will be cloned when a new listener is added.
  41.132          this.listeners    = propertyMap.listeners;
  41.133          this.freeSlots    = propertyMap.freeSlots;
  41.134 +        this.sharedProtoMap = propertyMap.sharedProtoMap;
  41.135 +        this.softReferenceDerivationLimit = softReferenceDerivationLimit;
  41.136  
  41.137          if (Context.DEBUG) {
  41.138              count.increment();
  41.139 @@ -142,12 +160,12 @@
  41.140      }
  41.141  
  41.142      /**
  41.143 -     * Cloning constructor.
  41.144 +     * Constructs an exact clone of {@code propertyMap}.
  41.145       *
  41.146       * @param propertyMap Existing property map.
  41.147        */
  41.148 -    private PropertyMap(final PropertyMap propertyMap) {
  41.149 -        this(propertyMap, propertyMap.properties);
  41.150 +    protected PropertyMap(final PropertyMap propertyMap) {
  41.151 +        this(propertyMap, propertyMap.properties, propertyMap.flags, propertyMap.fieldCount, propertyMap.spillLength, propertyMap.softReferenceDerivationLimit);
  41.152      }
  41.153  
  41.154      private void writeObject(final ObjectOutputStream out) throws IOException {
  41.155 @@ -183,7 +201,7 @@
  41.156       */
  41.157      public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum,  final int spillLength) {
  41.158          final PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
  41.159 -        return new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength, false);
  41.160 +        return new PropertyMap(newProperties, 0, className, fieldCount, fieldMaximum, spillLength);
  41.161      }
  41.162  
  41.163      /**
  41.164 @@ -205,7 +223,7 @@
  41.165       * @return New empty {@link PropertyMap}.
  41.166       */
  41.167      public static PropertyMap newMap(final Class<? extends ScriptObject> clazz) {
  41.168 -        return new PropertyMap(EMPTY_HASHMAP, clazz.getName(), 0, 0, 0, false);
  41.169 +        return new PropertyMap(EMPTY_HASHMAP, 0, clazz.getName(), 0, 0, 0);
  41.170      }
  41.171  
  41.172      /**
  41.173 @@ -227,12 +245,12 @@
  41.174      }
  41.175  
  41.176      /**
  41.177 -     * Get the listeners of this map, or null if none exists
  41.178 +     * Get the number of listeners of this map
  41.179       *
  41.180 -     * @return the listeners
  41.181 +     * @return the number of listeners
  41.182       */
  41.183 -    public PropertyListeners getListeners() {
  41.184 -        return listeners;
  41.185 +    public int getListenerCount() {
  41.186 +        return listeners == null ? 0 : listeners.getListenerCount();
  41.187      }
  41.188  
  41.189      /**
  41.190 @@ -253,9 +271,12 @@
  41.191       * A new property is being added.
  41.192       *
  41.193       * @param property The new Property added.
  41.194 +     * @param isSelf was the property added to this map?
  41.195       */
  41.196 -    public void propertyAdded(final Property property) {
  41.197 -        invalidateProtoGetSwitchPoint(property);
  41.198 +    public void propertyAdded(final Property property, final boolean isSelf) {
  41.199 +        if (!isSelf) {
  41.200 +            invalidateProtoSwitchPoint(property.getKey());
  41.201 +        }
  41.202          if (listeners != null) {
  41.203              listeners.propertyAdded(property);
  41.204          }
  41.205 @@ -265,9 +286,12 @@
  41.206       * An existing property is being deleted.
  41.207       *
  41.208       * @param property The property being deleted.
  41.209 +     * @param isSelf was the property deleted from this map?
  41.210       */
  41.211 -    public void propertyDeleted(final Property property) {
  41.212 -        invalidateProtoGetSwitchPoint(property);
  41.213 +    public void propertyDeleted(final Property property, final boolean isSelf) {
  41.214 +        if (!isSelf) {
  41.215 +            invalidateProtoSwitchPoint(property.getKey());
  41.216 +        }
  41.217          if (listeners != null) {
  41.218              listeners.propertyDeleted(property);
  41.219          }
  41.220 @@ -278,9 +302,12 @@
  41.221       *
  41.222       * @param oldProperty The old property
  41.223       * @param newProperty The new property
  41.224 +     * @param isSelf was the property modified on this map?
  41.225       */
  41.226 -    public void propertyModified(final Property oldProperty, final Property newProperty) {
  41.227 -        invalidateProtoGetSwitchPoint(oldProperty);
  41.228 +    public void propertyModified(final Property oldProperty, final Property newProperty, final boolean isSelf) {
  41.229 +        if (!isSelf) {
  41.230 +            invalidateProtoSwitchPoint(oldProperty.getKey());
  41.231 +        }
  41.232          if (listeners != null) {
  41.233              listeners.propertyModified(oldProperty, newProperty);
  41.234          }
  41.235 @@ -288,9 +315,15 @@
  41.236  
  41.237      /**
  41.238       * The prototype of an object associated with this {@link PropertyMap} is changed.
  41.239 +     *
  41.240 +     * @param isSelf was the prototype changed on the object using this map?
  41.241       */
  41.242 -    public void protoChanged() {
  41.243 -        invalidateAllProtoGetSwitchPoints();
  41.244 +    public void protoChanged(final boolean isSelf) {
  41.245 +        if (!isSelf) {
  41.246 +            invalidateAllProtoSwitchPoints();
  41.247 +        } else if (sharedProtoMap != null) {
  41.248 +            sharedProtoMap.invalidateSwitchPoint();
  41.249 +        }
  41.250          if (listeners != null) {
  41.251              listeners.protoChanged();
  41.252          }
  41.253 @@ -303,14 +336,14 @@
  41.254       * @return A shared {@link SwitchPoint} for the property.
  41.255       */
  41.256      public synchronized SwitchPoint getSwitchPoint(final String key) {
  41.257 -        if (protoGetSwitches == null) {
  41.258 -            protoGetSwitches = new HashMap<>();
  41.259 +        if (protoSwitches == null) {
  41.260 +            protoSwitches = new HashMap<>();
  41.261          }
  41.262  
  41.263 -        SwitchPoint switchPoint = protoGetSwitches.get(key);
  41.264 +        SwitchPoint switchPoint = protoSwitches.get(key);
  41.265          if (switchPoint == null) {
  41.266              switchPoint = new SwitchPoint();
  41.267 -            protoGetSwitches.put(key, switchPoint);
  41.268 +            protoSwitches.put(key, switchPoint);
  41.269          }
  41.270  
  41.271          return switchPoint;
  41.272 @@ -319,19 +352,17 @@
  41.273      /**
  41.274       * Indicate that a prototype property has changed.
  41.275       *
  41.276 -     * @param property {@link Property} to invalidate.
  41.277 +     * @param key {@link Property} key to invalidate.
  41.278       */
  41.279 -    synchronized void invalidateProtoGetSwitchPoint(final Property property) {
  41.280 -        if (protoGetSwitches != null) {
  41.281 -
  41.282 -            final String key = property.getKey();
  41.283 -            final SwitchPoint sp = protoGetSwitches.get(key);
  41.284 +    synchronized void invalidateProtoSwitchPoint(final String key) {
  41.285 +        if (protoSwitches != null) {
  41.286 +            final SwitchPoint sp = protoSwitches.get(key);
  41.287              if (sp != null) {
  41.288 -                protoGetSwitches.remove(key);
  41.289 +                protoSwitches.remove(key);
  41.290                  if (Context.DEBUG) {
  41.291                      protoInvalidations.increment();
  41.292                  }
  41.293 -                SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
  41.294 +                SwitchPoint.invalidateAll(new SwitchPoint[]{sp});
  41.295              }
  41.296          }
  41.297      }
  41.298 @@ -339,15 +370,15 @@
  41.299      /**
  41.300       * Indicate that proto itself has changed in hierarchy somewhere.
  41.301       */
  41.302 -    synchronized void invalidateAllProtoGetSwitchPoints() {
  41.303 -        if (protoGetSwitches != null) {
  41.304 -            final int size = protoGetSwitches.size();
  41.305 +    synchronized void invalidateAllProtoSwitchPoints() {
  41.306 +        if (protoSwitches != null) {
  41.307 +            final int size = protoSwitches.size();
  41.308              if (size > 0) {
  41.309                  if (Context.DEBUG) {
  41.310                      protoInvalidations.add(size);
  41.311                  }
  41.312 -                SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[size]));
  41.313 -                protoGetSwitches.clear();
  41.314 +                SwitchPoint.invalidateAll(protoSwitches.values().toArray(new SwitchPoint[size]));
  41.315 +                protoSwitches.clear();
  41.316              }
  41.317          }
  41.318      }
  41.319 @@ -363,7 +394,7 @@
  41.320       * @return New {@link PropertyMap} with {@link Property} added.
  41.321       */
  41.322      PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) {
  41.323 -        // No need to store bound property in the history as bound properties can't be reused.
  41.324 +        // We must not store bound property in the history as bound properties can't be reused.
  41.325          return addPropertyNoHistory(new AccessorProperty(property, bindTo));
  41.326      }
  41.327  
  41.328 @@ -376,16 +407,16 @@
  41.329          return property.isSpill() ? slot + fieldMaximum : slot;
  41.330      }
  41.331  
  41.332 -    // Update boundaries and flags after a property has been added
  41.333 -    private void updateFlagsAndBoundaries(final Property newProperty) {
  41.334 -        if(newProperty.isSpill()) {
  41.335 -            spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
  41.336 -        } else {
  41.337 -            fieldCount = Math.max(fieldCount, newProperty.getSlot() + 1);
  41.338 -        }
  41.339 -        if (isValidArrayIndex(getArrayIndex(newProperty.getKey()))) {
  41.340 -            setContainsArrayKeys();
  41.341 -        }
  41.342 +    private int newSpillLength(final Property newProperty) {
  41.343 +        return newProperty.isSpill() ? Math.max(spillLength, newProperty.getSlot() + 1) : spillLength;
  41.344 +    }
  41.345 +
  41.346 +    private int newFieldCount(final Property newProperty) {
  41.347 +        return !newProperty.isSpill() ? Math.max(fieldCount, newProperty.getSlot() + 1) : fieldCount;
  41.348 +    }
  41.349 +
  41.350 +    private int newFlags(final Property newProperty) {
  41.351 +        return isValidArrayIndex(getArrayIndex(newProperty.getKey())) ? flags | CONTAINS_ARRAY_KEYS : flags;
  41.352      }
  41.353  
  41.354      // Update the free slots bitmap for a property that has been deleted and/or added. This method is not synchronized
  41.355 @@ -420,16 +451,9 @@
  41.356       * @param property {@link Property} being added.
  41.357       * @return New {@link PropertyMap} with {@link Property} added.
  41.358       */
  41.359 -    public PropertyMap addPropertyNoHistory(final Property property) {
  41.360 -        if (listeners != null) {
  41.361 -            listeners.propertyAdded(property);
  41.362 -        }
  41.363 -        final PropertyHashMap newProperties = properties.immutableAdd(property);
  41.364 -        final PropertyMap newMap = new PropertyMap(this, newProperties);
  41.365 -        newMap.updateFlagsAndBoundaries(property);
  41.366 -        newMap.updateFreeSlots(null, property);
  41.367 -
  41.368 -        return newMap;
  41.369 +    public final PropertyMap addPropertyNoHistory(final Property property) {
  41.370 +        propertyAdded(property, true);
  41.371 +        return addPropertyInternal(property);
  41.372      }
  41.373  
  41.374      /**
  41.375 @@ -439,23 +463,29 @@
  41.376       *
  41.377       * @return New {@link PropertyMap} with {@link Property} added.
  41.378       */
  41.379 -    public synchronized PropertyMap addProperty(final Property property) {
  41.380 -        if (listeners != null) {
  41.381 -            listeners.propertyAdded(property);
  41.382 -        }
  41.383 +    public final synchronized PropertyMap addProperty(final Property property) {
  41.384 +        propertyAdded(property, true);
  41.385          PropertyMap newMap = checkHistory(property);
  41.386  
  41.387          if (newMap == null) {
  41.388 -            final PropertyHashMap newProperties = properties.immutableAdd(property);
  41.389 -            newMap = new PropertyMap(this, newProperties);
  41.390 -            newMap.updateFlagsAndBoundaries(property);
  41.391 -            newMap.updateFreeSlots(null, property);
  41.392 +            newMap = addPropertyInternal(property);
  41.393              addToHistory(property, newMap);
  41.394          }
  41.395  
  41.396          return newMap;
  41.397      }
  41.398  
  41.399 +    private PropertyMap deriveMap(final PropertyHashMap newProperties, final int newFlags, final int newFieldCount, final int newSpillLength) {
  41.400 +        return new PropertyMap(this, newProperties, newFlags, newFieldCount, newSpillLength, softReferenceDerivationLimit == 0 ? 0 : softReferenceDerivationLimit - 1);
  41.401 +    }
  41.402 +
  41.403 +    private PropertyMap addPropertyInternal(final Property property) {
  41.404 +        final PropertyHashMap newProperties = properties.immutableAdd(property);
  41.405 +        final PropertyMap newMap = deriveMap(newProperties, newFlags(property), newFieldCount(property), newSpillLength(property));
  41.406 +        newMap.updateFreeSlots(null, property);
  41.407 +        return newMap;
  41.408 +    }
  41.409 +
  41.410      /**
  41.411       * Remove a property from a map. Cloning or using an existing map if available.
  41.412       *
  41.413 @@ -463,10 +493,8 @@
  41.414       *
  41.415       * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found.
  41.416       */
  41.417 -    public synchronized PropertyMap deleteProperty(final Property property) {
  41.418 -        if (listeners != null) {
  41.419 -            listeners.propertyDeleted(property);
  41.420 -        }
  41.421 +    public final synchronized PropertyMap deleteProperty(final Property property) {
  41.422 +        propertyDeleted(property, true);
  41.423          PropertyMap newMap = checkHistory(property);
  41.424          final String key = property.getKey();
  41.425  
  41.426 @@ -477,13 +505,13 @@
  41.427              // If deleted property was last field or spill slot we can make it reusable by reducing field/slot count.
  41.428              // Otherwise mark it as free in free slots bitset.
  41.429              if (isSpill && slot >= 0 && slot == spillLength - 1) {
  41.430 -                newMap = new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength - 1, containsArrayKeys());
  41.431 +                newMap = deriveMap(newProperties, flags, fieldCount, spillLength - 1);
  41.432                  newMap.freeSlots = freeSlots;
  41.433              } else if (!isSpill && slot >= 0 && slot == fieldCount - 1) {
  41.434 -                newMap = new PropertyMap(newProperties, className, fieldCount - 1, fieldMaximum, spillLength, containsArrayKeys());
  41.435 +                newMap = deriveMap(newProperties, flags, fieldCount - 1, spillLength);
  41.436                  newMap.freeSlots = freeSlots;
  41.437              } else {
  41.438 -                newMap = new PropertyMap(this, newProperties);
  41.439 +                newMap = deriveMap(newProperties, flags, fieldCount, spillLength);
  41.440                  newMap.updateFreeSlots(property, null);
  41.441              }
  41.442              addToHistory(property, newMap);
  41.443 @@ -500,13 +528,8 @@
  41.444       *
  41.445       * @return New {@link PropertyMap} with {@link Property} replaced.
  41.446       */
  41.447 -    public PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
  41.448 -        if (listeners != null) {
  41.449 -            listeners.propertyModified(oldProperty, newProperty);
  41.450 -        }
  41.451 -        // Add replaces existing property.
  41.452 -        final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
  41.453 -        final PropertyMap newMap = new PropertyMap(this, newProperties);
  41.454 +    public final PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
  41.455 +        propertyModified(oldProperty, newProperty, true);
  41.456          /*
  41.457           * See ScriptObject.modifyProperty and ScriptObject.setUserAccessors methods.
  41.458           *
  41.459 @@ -528,14 +551,17 @@
  41.460                  newProperty instanceof UserAccessorProperty :
  41.461              "arbitrary replaceProperty attempted " + sameType + " oldProperty=" + oldProperty.getClass() + " newProperty=" + newProperty.getClass() + " [" + oldProperty.getLocalType() + " => " + newProperty.getLocalType() + "]";
  41.462  
  41.463 -        newMap.flags = flags;
  41.464 -
  41.465          /*
  41.466           * spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
  41.467           * to add spill count of the newly added UserAccessorProperty property.
  41.468           */
  41.469 +        final int newSpillLength = sameType ? spillLength : Math.max(spillLength, newProperty.getSlot() + 1);
  41.470 +
  41.471 +        // Add replaces existing property.
  41.472 +        final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
  41.473 +        final PropertyMap newMap = deriveMap(newProperties, flags, fieldCount, newSpillLength);
  41.474 +
  41.475          if (!sameType) {
  41.476 -            newMap.spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
  41.477              newMap.updateFreeSlots(oldProperty, newProperty);
  41.478          }
  41.479          return newMap;
  41.480 @@ -551,7 +577,7 @@
  41.481       * @param propertyFlags attribute flags of the property
  41.482       * @return the newly created UserAccessorProperty
  41.483       */
  41.484 -    public UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
  41.485 +    public final UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
  41.486          return new UserAccessorProperty(key, propertyFlags, getFreeSpillSlot());
  41.487      }
  41.488  
  41.489 @@ -562,7 +588,7 @@
  41.490       *
  41.491       * @return {@link Property} matching key.
  41.492       */
  41.493 -    public Property findProperty(final String key) {
  41.494 +    public final Property findProperty(final String key) {
  41.495          return properties.find(key);
  41.496      }
  41.497  
  41.498 @@ -573,12 +599,12 @@
  41.499       *
  41.500       * @return New {@link PropertyMap} with added properties.
  41.501       */
  41.502 -    public PropertyMap addAll(final PropertyMap other) {
  41.503 +    public final PropertyMap addAll(final PropertyMap other) {
  41.504          assert this != other : "adding property map to itself";
  41.505          final Property[] otherProperties = other.properties.getProperties();
  41.506          final PropertyHashMap newProperties = properties.immutableAdd(otherProperties);
  41.507  
  41.508 -        final PropertyMap newMap = new PropertyMap(this, newProperties);
  41.509 +        final PropertyMap newMap = deriveMap(newProperties, flags, fieldCount, spillLength);
  41.510          for (final Property property : otherProperties) {
  41.511              // This method is only safe to use with non-slotted, native getter/setter properties
  41.512              assert property.getSlot() == -1;
  41.513 @@ -593,19 +619,26 @@
  41.514       *
  41.515       * @return Properties as an array.
  41.516       */
  41.517 -    public Property[] getProperties() {
  41.518 +    public final Property[] getProperties() {
  41.519          return properties.getProperties();
  41.520      }
  41.521  
  41.522      /**
  41.523 +     * Return the name of the class of objects using this property map.
  41.524 +     *
  41.525 +     * @return class name of owner objects.
  41.526 +     */
  41.527 +    public final String getClassName() {
  41.528 +        return className;
  41.529 +    }
  41.530 +
  41.531 +    /**
  41.532       * Prevents the map from having additional properties.
  41.533       *
  41.534       * @return New map with {@link #NOT_EXTENSIBLE} flag set.
  41.535       */
  41.536      PropertyMap preventExtensions() {
  41.537 -        final PropertyMap newMap = new PropertyMap(this);
  41.538 -        newMap.flags |= NOT_EXTENSIBLE;
  41.539 -        return newMap;
  41.540 +        return deriveMap(properties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
  41.541      }
  41.542  
  41.543      /**
  41.544 @@ -621,10 +654,7 @@
  41.545              newProperties = newProperties.immutableAdd(oldProperty.addFlags(Property.NOT_CONFIGURABLE));
  41.546          }
  41.547  
  41.548 -        final PropertyMap newMap = new PropertyMap(this, newProperties);
  41.549 -        newMap.flags |= NOT_EXTENSIBLE;
  41.550 -
  41.551 -        return newMap;
  41.552 +        return deriveMap(newProperties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
  41.553      }
  41.554  
  41.555      /**
  41.556 @@ -646,10 +676,7 @@
  41.557              newProperties = newProperties.immutableAdd(oldProperty.addFlags(propertyFlags));
  41.558          }
  41.559  
  41.560 -        final PropertyMap newMap = new PropertyMap(this, newProperties);
  41.561 -        newMap.flags |= NOT_EXTENSIBLE;
  41.562 -
  41.563 -        return newMap;
  41.564 +        return deriveMap(newProperties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
  41.565      }
  41.566  
  41.567      /**
  41.568 @@ -736,7 +763,7 @@
  41.569              history = new WeakHashMap<>();
  41.570          }
  41.571  
  41.572 -        history.put(property, new SoftReference<>(newMap));
  41.573 +        history.put(property, softReferenceDerivationLimit == 0 ? new WeakReference<>(newMap) : new SoftReference<>(newMap));
  41.574      }
  41.575  
  41.576      /**
  41.577 @@ -749,7 +776,7 @@
  41.578      private PropertyMap checkHistory(final Property property) {
  41.579  
  41.580          if (history != null) {
  41.581 -            final SoftReference<PropertyMap> ref = history.get(property);
  41.582 +            final Reference<PropertyMap> ref = history.get(property);
  41.583              final PropertyMap historicMap = ref == null ? null : ref.get();
  41.584  
  41.585              if (historicMap != null) {
  41.586 @@ -821,13 +848,6 @@
  41.587      }
  41.588  
  41.589      /**
  41.590 -     * Flag this object as having array keys in defined properties
  41.591 -     */
  41.592 -    private void setContainsArrayKeys() {
  41.593 -        flags |= CONTAINS_ARRAY_KEYS;
  41.594 -    }
  41.595 -
  41.596 -    /**
  41.597       * Test to see if {@link PropertyMap} is extensible.
  41.598       *
  41.599       * @return {@code true} if {@link PropertyMap} can be added to.
  41.600 @@ -905,12 +925,72 @@
  41.601              setProtoNewMapCount.increment();
  41.602          }
  41.603  
  41.604 -        final PropertyMap newMap = new PropertyMap(this);
  41.605 +        final PropertyMap newMap = makeUnsharedCopy();
  41.606          addToProtoHistory(newProto, newMap);
  41.607  
  41.608          return newMap;
  41.609      }
  41.610  
  41.611 +    /**
  41.612 +     * Make a copy of this property map with the shared prototype field set to null. Note that this is
  41.613 +     * only necessary for shared maps of top-level objects. Shared prototype maps represented by
  41.614 +     * {@link SharedPropertyMap} are automatically converted to plain property maps when they evolve.
  41.615 +     *
  41.616 +     * @return a copy with the shared proto map unset
  41.617 +     */
  41.618 +    PropertyMap makeUnsharedCopy() {
  41.619 +        final PropertyMap newMap = new PropertyMap(this);
  41.620 +        newMap.sharedProtoMap = null;
  41.621 +        return newMap;
  41.622 +    }
  41.623 +
  41.624 +    /**
  41.625 +     * Set a reference to the expected parent prototype map. This is used for class-like
  41.626 +     * structures where we only want to use a top-level property map if all of the
  41.627 +     * prototype property maps have not been modified.
  41.628 +     *
  41.629 +     * @param protoMap weak reference to the prototype property map
  41.630 +     */
  41.631 +    void setSharedProtoMap(final SharedPropertyMap protoMap) {
  41.632 +        sharedProtoMap = protoMap;
  41.633 +    }
  41.634 +
  41.635 +    /**
  41.636 +     * Get the expected prototype property map if it is known, or null.
  41.637 +     *
  41.638 +     * @return parent map or null
  41.639 +     */
  41.640 +    public PropertyMap getSharedProtoMap() {
  41.641 +        return sharedProtoMap;
  41.642 +    }
  41.643 +
  41.644 +    /**
  41.645 +     * Returns {@code true} if this map has been used as a shared prototype map (i.e. as a prototype
  41.646 +     * for a JavaScript constructor function) and has not had properties added, deleted or replaced since then.
  41.647 +     * @return true if this is a valid shared prototype map
  41.648 +     */
  41.649 +    boolean isValidSharedProtoMap() {
  41.650 +        return false;
  41.651 +    }
  41.652 +
  41.653 +    /**
  41.654 +     * Returns the shared prototype switch point, or null if this is not a shared prototype map.
  41.655 +     * @return the shared prototype switch point, or null
  41.656 +     */
  41.657 +    SwitchPoint getSharedProtoSwitchPoint() {
  41.658 +        return null;
  41.659 +    }
  41.660 +
  41.661 +    /**
  41.662 +     * Return true if this map has a shared prototype map which has either been invalidated or does
  41.663 +     * not match the map of {@code proto}.
  41.664 +     * @param prototype the prototype object
  41.665 +     * @return true if this is an invalid shared map for {@code prototype}
  41.666 +     */
  41.667 +    boolean isInvalidSharedMapFor(final ScriptObject prototype) {
  41.668 +        return sharedProtoMap != null
  41.669 +                && (!sharedProtoMap.isValidSharedProtoMap() || prototype == null || sharedProtoMap != prototype.getMap());
  41.670 +    }
  41.671  
  41.672      /**
  41.673       * {@link PropertyMap} iterator.
    42.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Mon Sep 28 15:36:24 2015 -0700
    42.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Tue Oct 06 11:04:55 2015 -0700
    42.3 @@ -63,7 +63,7 @@
    42.4  import jdk.nashorn.internal.ir.SwitchNode;
    42.5  import jdk.nashorn.internal.ir.Symbol;
    42.6  import jdk.nashorn.internal.ir.TryNode;
    42.7 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    42.8 +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
    42.9  import jdk.nashorn.internal.objects.Global;
   42.10  import jdk.nashorn.internal.parser.Parser;
   42.11  import jdk.nashorn.internal.parser.Token;
   42.12 @@ -120,7 +120,7 @@
   42.13      private final Object endParserState;
   42.14  
   42.15      /** Code installer used for all further recompilation/specialization of this ScriptFunction */
   42.16 -    private transient CodeInstaller<ScriptEnvironment> installer;
   42.17 +    private transient CodeInstaller installer;
   42.18  
   42.19      private final Map<Integer, RecompilableScriptFunctionData> nestedFunctions;
   42.20  
   42.21 @@ -154,7 +154,7 @@
   42.22       */
   42.23      public RecompilableScriptFunctionData(
   42.24          final FunctionNode functionNode,
   42.25 -        final CodeInstaller<ScriptEnvironment> installer,
   42.26 +        final CodeInstaller installer,
   42.27          final AllocationStrategy allocationStrategy,
   42.28          final Map<Integer, RecompilableScriptFunctionData> nestedFunctions,
   42.29          final Map<String, Integer> externalScopeDepths,
   42.30 @@ -286,7 +286,7 @@
   42.31       * @param src source
   42.32       * @param inst code installer
   42.33       */
   42.34 -    public void initTransients(final Source src, final CodeInstaller<ScriptEnvironment> inst) {
   42.35 +    public void initTransients(final Source src, final CodeInstaller inst) {
   42.36          if (this.source == null && this.installer == null) {
   42.37              this.source    = src;
   42.38              this.installer = inst;
   42.39 @@ -369,8 +369,8 @@
   42.40      }
   42.41  
   42.42      @Override
   42.43 -    PropertyMap getAllocatorMap() {
   42.44 -        return allocationStrategy.getAllocatorMap();
   42.45 +    PropertyMap getAllocatorMap(final ScriptObject prototype) {
   42.46 +        return allocationStrategy.getAllocatorMap(prototype);
   42.47      }
   42.48  
   42.49      @Override
   42.50 @@ -507,7 +507,7 @@
   42.51      }
   42.52  
   42.53      private FunctionNode deserialize(final byte[] serializedAst) {
   42.54 -        final ScriptEnvironment env = installer.getOwner();
   42.55 +        final ScriptEnvironment env = installer.getContext().getEnv();
   42.56          final Timing timing = env._timing;
   42.57          final long t1 = System.nanoTime();
   42.58          try {
   42.59 @@ -525,7 +525,7 @@
   42.60          // don't cache non-split functions from the eager pass); those already cached, or those not split
   42.61          // don't need this step.
   42.62          final Set<Symbol> blockDefinedSymbols = fn.isSplit() && !cached ? Collections.newSetFromMap(new IdentityHashMap<Symbol, Boolean>()) : null;
   42.63 -        FunctionNode newFn = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
   42.64 +        FunctionNode newFn = (FunctionNode)fn.accept(new SimpleNodeVisitor() {
   42.65  
   42.66              private Symbol getReplacement(final Symbol original) {
   42.67                  if (original == null) {
   42.68 @@ -654,8 +654,8 @@
   42.69       * a new class loader with optimistic typing so that deoptimized code can get reclaimed by GC.
   42.70       * @return a code installer for installing new code.
   42.71       */
   42.72 -    private CodeInstaller<ScriptEnvironment> getInstallerForNewCode() {
   42.73 -        final ScriptEnvironment env = installer.getOwner();
   42.74 +    private CodeInstaller getInstallerForNewCode() {
   42.75 +        final ScriptEnvironment env = installer.getContext().getEnv();
   42.76          return env._optimistic_types || env._loader_per_compile ? installer.withNewLoader() : installer;
   42.77      }
   42.78  
   42.79 @@ -665,15 +665,10 @@
   42.80          final TypeMap typeMap = typeMap(actualCallSiteType);
   42.81          final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
   42.82          final Object typeInformationFile = OptimisticTypesPersistence.getLocationDescriptor(source, functionNodeId, paramTypes);
   42.83 -        final Context context = Context.getContextTrusted();
   42.84 -        return new Compiler(
   42.85 -                context,
   42.86 -                context.getEnv(),
   42.87 +        return Compiler.forOnDemandCompilation(
   42.88                  getInstallerForNewCode(),
   42.89                  functionNode.getSource(),  // source
   42.90 -                context.getErrorManager(),
   42.91                  isStrict() | functionNode.isStrict(), // is strict
   42.92 -                true,       // is on demand
   42.93                  this,       // compiledFunction, i.e. this RecompilableScriptFunctionData
   42.94                  typeMap,    // type map
   42.95                  getEffectiveInvalidatedProgramPoints(invalidatedProgramPoints, typeInformationFile), // invalidated program points
   42.96 @@ -716,7 +711,7 @@
   42.97              final TypeMap typeMap = typeMap(actualCallSiteType);
   42.98              final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
   42.99              cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes);
  42.100 -            final CodeInstaller<ScriptEnvironment> newInstaller = getInstallerForNewCode();
  42.101 +            final CodeInstaller newInstaller = getInstallerForNewCode();
  42.102              final StoredScript script = newInstaller.loadScript(source, cacheKey);
  42.103  
  42.104              if (script != null) {
  42.105 @@ -737,7 +732,7 @@
  42.106      }
  42.107  
  42.108      boolean usePersistentCodeCache() {
  42.109 -        return installer != null && installer.getOwner()._persistent_cache;
  42.110 +        return installer != null && installer.getContext().getEnv()._persistent_cache;
  42.111      }
  42.112  
  42.113      private MethodType explicitParams(final MethodType callSiteType) {
  42.114 @@ -769,7 +764,7 @@
  42.115  
  42.116      private FunctionNode extractFunctionFromScript(final FunctionNode script) {
  42.117          final Set<FunctionNode> fns = new HashSet<>();
  42.118 -        script.getBody().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
  42.119 +        script.getBody().accept(new SimpleNodeVisitor() {
  42.120              @Override
  42.121              public boolean enterFunctionNode(final FunctionNode fn) {
  42.122                  fns.add(fn);
    43.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Mon Sep 28 15:36:24 2015 -0700
    43.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Tue Oct 06 11:04:55 2015 -0700
    43.3 @@ -521,35 +521,39 @@
    43.4  
    43.5          assert !isBoundFunction(); // allocate never invoked on bound functions
    43.6  
    43.7 -        final ScriptObject object = data.allocate(getAllocatorMap());
    43.8 +        final ScriptObject prototype = getAllocatorPrototype();
    43.9 +        final ScriptObject object = data.allocate(getAllocatorMap(prototype));
   43.10  
   43.11          if (object != null) {
   43.12 -            final Object prototype = getPrototype();
   43.13 -            if (prototype instanceof ScriptObject) {
   43.14 -                object.setInitialProto((ScriptObject) prototype);
   43.15 -            }
   43.16 -
   43.17 -            if (object.getProto() == null) {
   43.18 -                object.setInitialProto(getObjectPrototype());
   43.19 -            }
   43.20 +            object.setInitialProto(prototype);
   43.21          }
   43.22  
   43.23          return object;
   43.24      }
   43.25  
   43.26 -    private PropertyMap getAllocatorMap() {
   43.27 -        if (allocatorMap == null) {
   43.28 -            allocatorMap = data.getAllocatorMap();
   43.29 +    /**
   43.30 +     * Get the property map used by "allocate"
   43.31 +     * @param prototype actual prototype object
   43.32 +     * @return property map
   43.33 +     */
   43.34 +    private synchronized PropertyMap getAllocatorMap(final ScriptObject prototype) {
   43.35 +        if (allocatorMap == null || allocatorMap.isInvalidSharedMapFor(prototype)) {
   43.36 +            // The prototype map has changed since this function was last used as constructor.
   43.37 +            // Get a new allocator map.
   43.38 +            allocatorMap = data.getAllocatorMap(prototype);
   43.39          }
   43.40          return allocatorMap;
   43.41      }
   43.42  
   43.43      /**
   43.44 -     * Return Object.prototype - used by "allocate"
   43.45 -     *
   43.46 -     * @return Object.prototype
   43.47 +     * Return the actual prototype used by "allocate"
   43.48 +     * @return allocator prototype
   43.49       */
   43.50 -    protected final ScriptObject getObjectPrototype() {
   43.51 +    private ScriptObject getAllocatorPrototype() {
   43.52 +        final Object prototype = getPrototype();
   43.53 +        if (prototype instanceof ScriptObject) {
   43.54 +            return (ScriptObject) prototype;
   43.55 +        }
   43.56          return Global.objectPrototype();
   43.57      }
   43.58  
   43.59 @@ -591,10 +595,10 @@
   43.60       *
   43.61       * @param newPrototype new prototype object
   43.62       */
   43.63 -    public final void setPrototype(final Object newPrototype) {
   43.64 +    public synchronized final void setPrototype(final Object newPrototype) {
   43.65          if (newPrototype instanceof ScriptObject && newPrototype != this.prototype && allocatorMap != null) {
   43.66 -            // Replace our current allocator map with one that is associated with the new prototype.
   43.67 -            allocatorMap = allocatorMap.changeProto((ScriptObject) newPrototype);
   43.68 +            // Unset allocator map to be replaced with one matching the new prototype.
   43.69 +            allocatorMap = null;
   43.70          }
   43.71          this.prototype = newPrototype;
   43.72      }
    44.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Mon Sep 28 15:36:24 2015 -0700
    44.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Tue Oct 06 11:04:55 2015 -0700
    44.3 @@ -389,9 +389,10 @@
    44.4      /**
    44.5       * Get the property map to use for objects allocated by this function.
    44.6       *
    44.7 +     * @param prototype the prototype of the allocated object
    44.8       * @return the property map for allocated objects.
    44.9       */
   44.10 -    PropertyMap getAllocatorMap() {
   44.11 +    PropertyMap getAllocatorMap(final ScriptObject prototype) {
   44.12          return null;
   44.13      }
   44.14  
    45.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Sep 28 15:36:24 2015 -0700
    45.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Oct 06 11:04:55 2015 -0700
    45.3 @@ -710,8 +710,7 @@
    45.4          final long longIndex = ArrayIndex.toLongIndex(index);
    45.5          final long oldLength = getArray().length();
    45.6          if (longIndex >= oldLength) {
    45.7 -            setArray(getArray().ensure(longIndex));
    45.8 -            doesNotHaveEnsureDelete(longIndex, oldLength, false);
    45.9 +            setArray(getArray().ensure(longIndex).safeDelete(oldLength, longIndex - 1, false));
   45.10          }
   45.11          setArray(getArray().set(index, value, false));
   45.12      }
   45.13 @@ -809,9 +808,11 @@
   45.14  
   45.15          if (deep) {
   45.16              final ScriptObject myProto = getProto();
   45.17 -            if (myProto != null) {
   45.18 -                return myProto.findProperty(key, deep, start);
   45.19 -            }
   45.20 +            final FindProperty find = myProto == null ? null : myProto.findProperty(key, true, start);
   45.21 +            // checkSharedProtoMap must be invoked after myProto.checkSharedProtoMap to propagate
   45.22 +            // shared proto invalidation up the prototype chain. It also must be invoked when prototype is null.
   45.23 +            checkSharedProtoMap();
   45.24 +            return find;
   45.25          }
   45.26  
   45.27          return null;
   45.28 @@ -832,7 +833,7 @@
   45.29          if (deep) {
   45.30              final ScriptObject myProto = getProto();
   45.31              if (myProto != null) {
   45.32 -                return myProto.hasProperty(key, deep);
   45.33 +                return myProto.hasProperty(key, true);
   45.34              }
   45.35          }
   45.36  
   45.37 @@ -1258,11 +1259,8 @@
   45.38          if (oldProto != newProto) {
   45.39              proto = newProto;
   45.40  
   45.41 -            // Let current listeners know that the prototype has changed and set our map
   45.42 -            final PropertyListeners listeners = getMap().getListeners();
   45.43 -            if (listeners != null) {
   45.44 -                listeners.protoChanged();
   45.45 -            }
   45.46 +            // Let current listeners know that the prototype has changed
   45.47 +            getMap().protoChanged(true);
   45.48              // Replace our current allocator map with one that is associated with the new prototype.
   45.49              setMap(getMap().changeProto(newProto));
   45.50          }
   45.51 @@ -1314,7 +1312,7 @@
   45.52                  }
   45.53                  p = p.getProto();
   45.54              }
   45.55 -            setProto((ScriptObject)newProto);
   45.56 +            setProto((ScriptObject) newProto);
   45.57          } else {
   45.58              throw typeError("cant.set.proto.to.non.object", ScriptRuntime.safeToString(this), ScriptRuntime.safeToString(newProto));
   45.59          }
   45.60 @@ -1997,11 +1995,11 @@
   45.61          final ScriptObject owner = find.getOwner();
   45.62          final Class<ClassCastException> exception = explicitInstanceOfCheck ? null : ClassCastException.class;
   45.63  
   45.64 -        final SwitchPoint protoSwitchPoint;
   45.65 +        final SwitchPoint[] protoSwitchPoints;
   45.66  
   45.67          if (mh == null) {
   45.68              mh = Lookup.emptyGetter(returnType);
   45.69 -            protoSwitchPoint = getProtoSwitchPoint(name, owner);
   45.70 +            protoSwitchPoints = getProtoSwitchPoints(name, owner);
   45.71          } else if (!find.isSelf()) {
   45.72              assert mh.type().returnType().equals(returnType) :
   45.73                      "return type mismatch for getter " + mh.type().returnType() + " != " + returnType;
   45.74 @@ -2009,12 +2007,12 @@
   45.75                  // Add a filter that replaces the self object with the prototype owning the property.
   45.76                  mh = addProtoFilter(mh, find.getProtoChainLength());
   45.77              }
   45.78 -            protoSwitchPoint = getProtoSwitchPoint(name, owner);
   45.79 +            protoSwitchPoints = getProtoSwitchPoints(name, owner);
   45.80          } else {
   45.81 -            protoSwitchPoint = null;
   45.82 +            protoSwitchPoints = null;
   45.83          }
   45.84  
   45.85 -        final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoint, exception);
   45.86 +        final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoints, exception);
   45.87          return inv.addSwitchPoint(findBuiltinSwitchPoint(name));
   45.88      }
   45.89  
   45.90 @@ -2113,17 +2111,32 @@
   45.91       * @param owner the property owner, null if property is not defined
   45.92       * @return a SwitchPoint or null
   45.93       */
   45.94 -    public final SwitchPoint getProtoSwitchPoint(final String name, final ScriptObject owner) {
   45.95 +    public final SwitchPoint[] getProtoSwitchPoints(final String name, final ScriptObject owner) {
   45.96          if (owner == this || getProto() == null) {
   45.97              return null;
   45.98          }
   45.99  
  45.100 +        final List<SwitchPoint> switchPoints = new ArrayList<>();
  45.101          for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
  45.102              final ScriptObject parent = obj.getProto();
  45.103              parent.getMap().addListener(name, obj.getMap());
  45.104 +            final SwitchPoint sp = parent.getMap().getSharedProtoSwitchPoint();
  45.105 +            if (sp != null && !sp.hasBeenInvalidated()) {
  45.106 +                switchPoints.add(sp);
  45.107 +            }
  45.108          }
  45.109  
  45.110 -        return getMap().getSwitchPoint(name);
  45.111 +        switchPoints.add(getMap().getSwitchPoint(name));
  45.112 +        return switchPoints.toArray(new SwitchPoint[switchPoints.size()]);
  45.113 +    }
  45.114 +
  45.115 +    private void checkSharedProtoMap() {
  45.116 +        // Check if our map has an expected shared prototype property map. If it has, make sure that
  45.117 +        // the prototype map has not been invalidated, and that it does match the actual map of the prototype.
  45.118 +        if (getMap().isInvalidSharedMapFor(getProto())) {
  45.119 +            // Change our own map to one that does not assume a shared prototype map.
  45.120 +            setMap(getMap().makeUnsharedCopy());
  45.121 +        }
  45.122      }
  45.123  
  45.124      /**
  45.125 @@ -2205,7 +2218,7 @@
  45.126          return new GuardedInvocation(
  45.127                  Lookup.EMPTY_SETTER,
  45.128                  NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck),
  45.129 -                getProtoSwitchPoint(name, null),
  45.130 +                getProtoSwitchPoints(name, null),
  45.131                  explicitInstanceOfCheck ? null : ClassCastException.class);
  45.132      }
  45.133  
  45.134 @@ -2351,7 +2364,7 @@
  45.135                                  find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
  45.136                                  find.getProtoChainLength(),
  45.137                                  func),
  45.138 -                        getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
  45.139 +                        getProtoSwitchPoints(NO_SUCH_PROPERTY_NAME, find.getOwner()),
  45.140                          //TODO this doesn't need a ClassCastException as guard always checks script object
  45.141                          null);
  45.142              }
  45.143 @@ -2424,7 +2437,7 @@
  45.144          }
  45.145  
  45.146          return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
  45.147 -                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoint(name, null),
  45.148 +                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoints(name, null),
  45.149                  explicitInstanceOfCheck ? null : ClassCastException.class);
  45.150      }
  45.151  
  45.152 @@ -2664,11 +2677,7 @@
  45.153          }
  45.154  
  45.155          if (newLength > arrayLength) {
  45.156 -            data = data.ensure(newLength - 1);
  45.157 -            if (data.canDelete(arrayLength, newLength - 1, false)) {
  45.158 -               data = data.delete(arrayLength, newLength - 1);
  45.159 -            }
  45.160 -            setArray(data);
  45.161 +            setArray(data.ensure(newLength - 1).safeDelete(arrayLength, newLength - 1, false));
  45.162              return;
  45.163          }
  45.164  
  45.165 @@ -3089,23 +3098,12 @@
  45.166          return false;
  45.167      }
  45.168  
  45.169 -    private void doesNotHaveEnsureDelete(final long longIndex, final long oldLength, final boolean strict) {
  45.170 -        if (longIndex > oldLength) {
  45.171 -            ArrayData array = getArray();
  45.172 -            if (array.canDelete(oldLength, longIndex - 1, strict)) {
  45.173 -                array = array.delete(oldLength, longIndex - 1);
  45.174 -            }
  45.175 -            setArray(array);
  45.176 -        }
  45.177 -    }
  45.178 -
  45.179      private void doesNotHave(final int index, final int value, final int callSiteFlags) {
  45.180          final long oldLength = getArray().length();
  45.181          final long longIndex = ArrayIndex.toLongIndex(index);
  45.182          if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
  45.183              final boolean strict = isStrictFlag(callSiteFlags);
  45.184 -            setArray(getArray().set(index, value, strict));
  45.185 -            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
  45.186 +            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
  45.187          }
  45.188      }
  45.189  
  45.190 @@ -3114,8 +3112,7 @@
  45.191          final long longIndex = ArrayIndex.toLongIndex(index);
  45.192          if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
  45.193              final boolean strict = isStrictFlag(callSiteFlags);
  45.194 -            setArray(getArray().set(index, value, strict));
  45.195 -            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
  45.196 +            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
  45.197          }
  45.198      }
  45.199  
  45.200 @@ -3124,8 +3121,7 @@
  45.201          final long longIndex = ArrayIndex.toLongIndex(index);
  45.202          if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
  45.203              final boolean strict = isStrictFlag(callSiteFlags);
  45.204 -            setArray(getArray().set(index, value, strict));
  45.205 -            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
  45.206 +            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
  45.207          }
  45.208      }
  45.209  
  45.210 @@ -3134,8 +3130,7 @@
  45.211          final long longIndex = ArrayIndex.toLongIndex(index);
  45.212          if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
  45.213              final boolean strict = isStrictFlag(callSiteFlags);
  45.214 -            setArray(getArray().set(index, value, strict));
  45.215 -            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
  45.216 +            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
  45.217          }
  45.218      }
  45.219  
    46.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Mon Sep 28 15:36:24 2015 -0700
    46.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Tue Oct 06 11:04:55 2015 -0700
    46.3 @@ -186,10 +186,7 @@
    46.4  
    46.5      private SetMethod createNewPropertySetter(final SwitchPoint builtinSwitchPoint) {
    46.6          final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter(builtinSwitchPoint) : createNewSpillPropertySetter(builtinSwitchPoint);
    46.7 -        final PropertyListeners listeners = map.getListeners();
    46.8 -        if (listeners != null) {
    46.9 -            listeners.propertyAdded(sm.property);
   46.10 -        }
   46.11 +        map.propertyAdded(sm.property, true);
   46.12          return sm;
   46.13      }
   46.14  
   46.15 @@ -204,7 +201,7 @@
   46.16          //fast type specific setter
   46.17          final MethodHandle fastSetter = property.getSetter(type, newMap); //0 sobj, 1 value, slot folded for spill property already
   46.18  
   46.19 -        //slow setter, that calls ScriptObject.set with appropraite type and key name
   46.20 +        //slow setter, that calls ScriptObject.set with appropriate type and key name
   46.21          MethodHandle slowSetter = ScriptObject.SET_SLOW[getAccessorTypeIndex(type)];
   46.22          slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.getFlags(desc));
   46.23          slowSetter = MH.insertArguments(slowSetter, 1, name);
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/src/jdk/nashorn/internal/runtime/SharedPropertyMap.java	Tue Oct 06 11:04:55 2015 -0700
    47.3 @@ -0,0 +1,100 @@
    47.4 +/*
    47.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    47.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    47.7 + *
    47.8 + * This code is free software; you can redistribute it and/or modify it
    47.9 + * under the terms of the GNU General Public License version 2 only, as
   47.10 + * published by the Free Software Foundation.  Oracle designates this
   47.11 + * particular file as subject to the "Classpath" exception as provided
   47.12 + * by Oracle in the LICENSE file that accompanied this code.
   47.13 + *
   47.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   47.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   47.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   47.17 + * version 2 for more details (a copy is included in the LICENSE file that
   47.18 + * accompanied this code).
   47.19 + *
   47.20 + * You should have received a copy of the GNU General Public License version
   47.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   47.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   47.23 + *
   47.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   47.25 + * or visit www.oracle.com if you need additional information or have any
   47.26 + * questions.
   47.27 + */
   47.28 +
   47.29 +package jdk.nashorn.internal.runtime;
   47.30 +
   47.31 +import java.lang.invoke.SwitchPoint;
   47.32 +
   47.33 +/**
   47.34 + * This class represents a property map that can be shared among multiple prototype objects, allowing all inheriting
   47.35 + * top-level objects to also share one property map. This is class is only used for prototype objects, the
   47.36 + * top-level objects use ordinary {@link PropertyMap}s with the {@link PropertyMap#sharedProtoMap} field
   47.37 + * set to the expected shared prototype map.
   47.38 + *
   47.39 + * <p>When an instance of this class is evolved because a property is added, removed, or modified in an object
   47.40 + * using it, the {@link #invalidateSwitchPoint()} method is invoked to signal to all callsites and inheriting
   47.41 + * objects that the assumption of a single shared prototype map is no longer valid. The property map resulting
   47.42 + * from the modification will no longer be an instance of this class.</p>
   47.43 + */
   47.44 +public final class SharedPropertyMap extends PropertyMap {
   47.45 +
   47.46 +    private SwitchPoint switchPoint;
   47.47 +
   47.48 +    private static final long serialVersionUID = 2166297719721778876L;
   47.49 +
   47.50 +    /**
   47.51 +     * Create a new shared property map from the given {@code map}.
   47.52 +     * @param map property map to copy
   47.53 +     */
   47.54 +    public SharedPropertyMap(final PropertyMap map) {
   47.55 +        super(map);
   47.56 +        this.switchPoint = new SwitchPoint();
   47.57 +    }
   47.58 +
   47.59 +    @Override
   47.60 +    public void propertyAdded(final Property property, final boolean isSelf) {
   47.61 +        if (isSelf) {
   47.62 +            invalidateSwitchPoint();
   47.63 +        }
   47.64 +        super.propertyAdded(property, isSelf);
   47.65 +    }
   47.66 +
   47.67 +    @Override
   47.68 +    public void propertyDeleted(final Property property, final boolean isSelf) {
   47.69 +        if (isSelf) {
   47.70 +            invalidateSwitchPoint();
   47.71 +        }
   47.72 +        super.propertyDeleted(property, isSelf);
   47.73 +    }
   47.74 +
   47.75 +    @Override
   47.76 +    public void propertyModified(final Property oldProperty, final Property newProperty, final boolean isSelf) {
   47.77 +        if (isSelf) {
   47.78 +            invalidateSwitchPoint();
   47.79 +        }
   47.80 +        super.propertyModified(oldProperty, newProperty, isSelf);
   47.81 +    }
   47.82 +
   47.83 +    @Override
   47.84 +    synchronized boolean isValidSharedProtoMap() {
   47.85 +        return switchPoint != null;
   47.86 +    }
   47.87 +
   47.88 +    @Override
   47.89 +    synchronized SwitchPoint getSharedProtoSwitchPoint() {
   47.90 +        return switchPoint;
   47.91 +    }
   47.92 +
   47.93 +    /**
   47.94 +     * Invalidate the shared prototype switch point if this is a shared prototype map.
   47.95 +     */
   47.96 +    synchronized void invalidateSwitchPoint() {
   47.97 +        if (switchPoint != null) {
   47.98 +            assert !switchPoint.hasBeenInvalidated();
   47.99 +            SwitchPoint.invalidateAll(new SwitchPoint[]{ switchPoint });
  47.100 +            switchPoint = null;
  47.101 +        }
  47.102 +    }
  47.103 +}
    48.1 --- a/src/jdk/nashorn/internal/runtime/StoredScript.java	Mon Sep 28 15:36:24 2015 -0700
    48.2 +++ b/src/jdk/nashorn/internal/runtime/StoredScript.java	Tue Oct 06 11:04:55 2015 -0700
    48.3 @@ -77,7 +77,7 @@
    48.4          return compilationId;
    48.5      }
    48.6  
    48.7 -    private Map<String, Class<?>> installClasses(final Source source, final CodeInstaller<ScriptEnvironment> installer) {
    48.8 +    private Map<String, Class<?>> installClasses(final Source source, final CodeInstaller installer) {
    48.9          final Map<String, Class<?>> installedClasses = new HashMap<>();
   48.10          final byte[]   mainClassBytes = classBytes.get(mainClassName);
   48.11          final Class<?> mainClass      = installer.install(mainClassName, mainClassBytes);
   48.12 @@ -96,7 +96,7 @@
   48.13          return installedClasses;
   48.14      }
   48.15  
   48.16 -    FunctionInitializer installFunction(final RecompilableScriptFunctionData data, final CodeInstaller<ScriptEnvironment> installer) {
   48.17 +    FunctionInitializer installFunction(final RecompilableScriptFunctionData data, final CodeInstaller installer) {
   48.18          final Map<String, Class<?>> installedClasses = installClasses(data.getSource(), installer);
   48.19  
   48.20          assert initializers != null;
   48.21 @@ -124,7 +124,7 @@
   48.22       * @param installer the installer
   48.23       * @return main script class
   48.24       */
   48.25 -    Class<?> installScript(final Source source, final CodeInstaller<ScriptEnvironment> installer) {
   48.26 +    Class<?> installScript(final Source source, final CodeInstaller installer) {
   48.27  
   48.28          final Map<String, Class<?>> installedClasses = installClasses(source, installer);
   48.29  
    49.1 --- a/src/jdk/nashorn/internal/runtime/WithObject.java	Mon Sep 28 15:36:24 2015 -0700
    49.2 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java	Tue Oct 06 11:04:55 2015 -0700
    49.3 @@ -46,7 +46,7 @@
    49.4   *
    49.5   */
    49.6  public final class WithObject extends Scope {
    49.7 -    private static final MethodHandle WITHEXPRESSIONGUARD    = findOwnMH("withExpressionGuard",  boolean.class, Object.class, PropertyMap.class, SwitchPoint.class);
    49.8 +    private static final MethodHandle WITHEXPRESSIONGUARD    = findOwnMH("withExpressionGuard",  boolean.class, Object.class, PropertyMap.class, SwitchPoint[].class);
    49.9      private static final MethodHandle WITHEXPRESSIONFILTER   = findOwnMH("withFilterExpression", Object.class, Object.class);
   49.10      private static final MethodHandle WITHSCOPEFILTER        = findOwnMH("withFilterScope",      Object.class, Object.class);
   49.11      private static final MethodHandle BIND_TO_EXPRESSION_OBJ = findOwnMH("bindToExpression",     Object.class, Object.class, Object.class);
   49.12 @@ -360,13 +360,24 @@
   49.13  
   49.14      private MethodHandle expressionGuard(final String name, final ScriptObject owner) {
   49.15          final PropertyMap map = expression.getMap();
   49.16 -        final SwitchPoint sp = expression.getProtoSwitchPoint(name, owner);
   49.17 +        final SwitchPoint[] sp = expression.getProtoSwitchPoints(name, owner);
   49.18          return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp);
   49.19      }
   49.20  
   49.21      @SuppressWarnings("unused")
   49.22 -    private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint sp) {
   49.23 -        return ((WithObject)receiver).expression.getMap() == map && (sp == null || !sp.hasBeenInvalidated());
   49.24 +    private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint[] sp) {
   49.25 +        return ((WithObject)receiver).expression.getMap() == map && !hasBeenInvalidated(sp);
   49.26 +    }
   49.27 +
   49.28 +    private static boolean hasBeenInvalidated(final SwitchPoint[] switchPoints) {
   49.29 +        if (switchPoints != null) {
   49.30 +            for (final SwitchPoint switchPoint : switchPoints) {
   49.31 +                if (switchPoint.hasBeenInvalidated()) {
   49.32 +                    return true;
   49.33 +                }
   49.34 +            }
   49.35 +        }
   49.36 +        return false;
   49.37      }
   49.38  
   49.39      /**
    50.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Mon Sep 28 15:36:24 2015 -0700
    50.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java	Tue Oct 06 11:04:55 2015 -0700
    50.3 @@ -258,7 +258,7 @@
    50.4       * Factory method for unspecified array - start as int
    50.5       * @return ArrayData
    50.6       */
    50.7 -    public final static ArrayData initialArray() {
    50.8 +    public static ArrayData initialArray() {
    50.9          return new IntArrayData();
   50.10      }
   50.11  
   50.12 @@ -278,7 +278,7 @@
   50.13       * @param size size required
   50.14       * @return size given, always &gt;= size
   50.15       */
   50.16 -    protected final static int alignUp(final int size) {
   50.17 +    protected static int alignUp(final int size) {
   50.18          return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1);
   50.19      }
   50.20  
   50.21 @@ -288,7 +288,7 @@
   50.22       * @param length the initial length
   50.23       * @return ArrayData
   50.24       */
   50.25 -    public static final ArrayData allocate(final int length) {
   50.26 +    public static ArrayData allocate(final int length) {
   50.27          if (length == 0) {
   50.28              return new IntArrayData();
   50.29          } else if (length >= SparseArrayData.MAX_DENSE_LENGTH) {
   50.30 @@ -304,7 +304,7 @@
   50.31       * @param  array the array
   50.32       * @return ArrayData wrapping this array
   50.33       */
   50.34 -    public static final ArrayData allocate(final Object array) {
   50.35 +    public static ArrayData allocate(final Object array) {
   50.36          final Class<?> clazz = array.getClass();
   50.37  
   50.38          if (clazz == int[].class) {
   50.39 @@ -324,7 +324,7 @@
   50.40       * @param array the array to use for initial elements
   50.41       * @return the ArrayData
   50.42       */
   50.43 -    public static final ArrayData allocate(final int[] array) {
   50.44 +    public static ArrayData allocate(final int[] array) {
   50.45           return new IntArrayData(array, array.length);
   50.46      }
   50.47  
   50.48 @@ -334,7 +334,7 @@
   50.49       * @param array the array to use for initial elements
   50.50       * @return the ArrayData
   50.51       */
   50.52 -    public static final ArrayData allocate(final long[] array) {
   50.53 +    public static ArrayData allocate(final long[] array) {
   50.54          return new LongArrayData(array, array.length);
   50.55      }
   50.56  
   50.57 @@ -344,7 +344,7 @@
   50.58       * @param array the array to use for initial elements
   50.59       * @return the ArrayData
   50.60       */
   50.61 -    public static final ArrayData allocate(final double[] array) {
   50.62 +    public static ArrayData allocate(final double[] array) {
   50.63          return new NumberArrayData(array, array.length);
   50.64      }
   50.65  
   50.66 @@ -354,7 +354,7 @@
   50.67       * @param array the array to use for initial elements
   50.68       * @return the ArrayData
   50.69       */
   50.70 -    public static final ArrayData allocate(final Object[] array) {
   50.71 +    public static ArrayData allocate(final Object[] array) {
   50.72          return new ObjectArrayData(array, array.length);
   50.73      }
   50.74  
   50.75 @@ -364,7 +364,7 @@
   50.76       * @param buf the nio ByteBuffer to wrap
   50.77       * @return the ArrayData
   50.78       */
   50.79 -    public static final ArrayData allocate(final ByteBuffer buf) {
   50.80 +    public static ArrayData allocate(final ByteBuffer buf) {
   50.81          return new ByteBufferArrayData(buf);
   50.82      }
   50.83  
   50.84 @@ -374,7 +374,7 @@
   50.85       * @param underlying  the underlying ArrayData to wrap in the freeze filter
   50.86       * @return the frozen ArrayData
   50.87       */
   50.88 -    public static final ArrayData freeze(final ArrayData underlying) {
   50.89 +    public static ArrayData freeze(final ArrayData underlying) {
   50.90          return new FrozenArrayFilter(underlying);
   50.91      }
   50.92  
   50.93 @@ -384,7 +384,7 @@
   50.94       * @param underlying  the underlying ArrayData to wrap in the seal filter
   50.95       * @return the sealed ArrayData
   50.96       */
   50.97 -    public static final ArrayData seal(final ArrayData underlying) {
   50.98 +    public static ArrayData seal(final ArrayData underlying) {
   50.99          return new SealedArrayFilter(underlying);
  50.100      }
  50.101  
  50.102 @@ -394,7 +394,7 @@
  50.103       * @param  underlying the underlying ArrayData to wrap in the non extensible filter
  50.104       * @return new array data, filtered
  50.105       */
  50.106 -    public static final ArrayData preventExtension(final ArrayData underlying) {
  50.107 +    public static ArrayData preventExtension(final ArrayData underlying) {
  50.108          return new NonExtensibleArrayFilter(underlying);
  50.109      }
  50.110  
  50.111 @@ -404,7 +404,7 @@
  50.112       * @param underlying the underlying ArrayDAta to wrap in the non extensible filter
  50.113       * @return new array data, filtered
  50.114       */
  50.115 -    public static final ArrayData setIsLengthNotWritable(final ArrayData underlying) {
  50.116 +    public static ArrayData setIsLengthNotWritable(final ArrayData underlying) {
  50.117          return new LengthNotWritableFilter(underlying);
  50.118      }
  50.119  
  50.120 @@ -676,19 +676,34 @@
  50.121      }
  50.122  
  50.123      /**
  50.124 -     * Returns if element at specific index range can be deleted or not.
  50.125 +     * Returns if element at specific index can be deleted or not.
  50.126       *
  50.127 -     * @param fromIndex  the start index
  50.128 -     * @param toIndex    the end index
  50.129 +     * @param longIndex  the index
  50.130       * @param strict     are we in strict mode
  50.131       *
  50.132       * @return true if range can be deleted
  50.133       */
  50.134 -    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
  50.135 +    public boolean canDelete(final long longIndex, final boolean strict) {
  50.136          return true;
  50.137      }
  50.138  
  50.139      /**
  50.140 +     * Delete a range from the array if {@code fromIndex} is less than or equal to {@code toIndex}
  50.141 +     * and the array supports deletion.
  50.142 +     *
  50.143 +     * @param fromIndex  the start index (inclusive)
  50.144 +     * @param toIndex    the end index (inclusive)
  50.145 +     * @param strict     are we in strict mode
  50.146 +     * @return an array with the range deleted, or this array if no deletion took place
  50.147 +     */
  50.148 +    public final ArrayData safeDelete(final long fromIndex, final long toIndex, final boolean strict) {
  50.149 +        if (fromIndex <= toIndex && canDelete(fromIndex, strict)) {
  50.150 +            return delete(fromIndex, toIndex);
  50.151 +        }
  50.152 +        return this;
  50.153 +    }
  50.154 +
  50.155 +    /**
  50.156       * Returns property descriptor for element at a given index
  50.157       *
  50.158       * @param global the global object
    51.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java	Mon Sep 28 15:36:24 2015 -0700
    51.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java	Tue Oct 06 11:04:55 2015 -0700
    51.3 @@ -164,7 +164,7 @@
    51.4      }
    51.5  
    51.6      @Override
    51.7 -    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
    51.8 +    public boolean canDelete(final long longIndex, final boolean strict) {
    51.9          return false;
   51.10      }
   51.11  
    52.1 --- a/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java	Mon Sep 28 15:36:24 2015 -0700
    52.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java	Tue Oct 06 11:04:55 2015 -0700
    52.3 @@ -50,15 +50,15 @@
    52.4  
    52.5      @Override
    52.6      public boolean canDelete(final int index, final boolean strict) {
    52.7 -        if (strict) {
    52.8 -            throw typeError("cant.delete.property", Integer.toString(index), "sealed array");
    52.9 -        }
   52.10 -        return false;
   52.11 +        return canDelete(ArrayIndex.toLongIndex(index), strict);
   52.12      }
   52.13  
   52.14      @Override
   52.15 -    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
   52.16 -        return canDelete((int) fromIndex, strict);
   52.17 +    public boolean canDelete(final long longIndex, final boolean strict) {
   52.18 +        if (strict) {
   52.19 +            throw typeError("cant.delete.property", Long.toString(longIndex), "sealed array");
   52.20 +        }
   52.21 +        return false;
   52.22      }
   52.23  
   52.24      @Override
    53.1 --- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Mon Sep 28 15:36:24 2015 -0700
    53.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Tue Oct 06 11:04:55 2015 -0700
    53.3 @@ -36,7 +36,7 @@
    53.4   * Handle arrays where the index is very large.
    53.5   */
    53.6  class SparseArrayData extends ArrayData {
    53.7 -    static final int MAX_DENSE_LENGTH = 8 * 1024 * 1024;
    53.8 +    static final int MAX_DENSE_LENGTH = 1024 * 1024;
    53.9  
   53.10      /** Underlying array. */
   53.11      private ArrayData underlying;
   53.12 @@ -166,8 +166,9 @@
   53.13      @Override
   53.14      public ArrayData set(final int index, final Object value, final boolean strict) {
   53.15          if (index >= 0 && index < maxDenseLength) {
   53.16 +            final long oldLength = underlying.length();
   53.17              ensure(index);
   53.18 -            underlying = underlying.set(index, value, strict);
   53.19 +            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
   53.20              setLength(Math.max(underlying.length(), length()));
   53.21          } else {
   53.22              final Long longIndex = indexToKey(index);
   53.23 @@ -181,8 +182,9 @@
   53.24      @Override
   53.25      public ArrayData set(final int index, final int value, final boolean strict) {
   53.26          if (index >= 0 && index < maxDenseLength) {
   53.27 +            final long oldLength = underlying.length();
   53.28              ensure(index);
   53.29 -            underlying = underlying.set(index, value, strict);
   53.30 +            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
   53.31              setLength(Math.max(underlying.length(), length()));
   53.32          } else {
   53.33              final Long longIndex = indexToKey(index);
   53.34 @@ -195,8 +197,9 @@
   53.35      @Override
   53.36      public ArrayData set(final int index, final long value, final boolean strict) {
   53.37          if (index >= 0 && index < maxDenseLength) {
   53.38 +            final long oldLength = underlying.length();
   53.39              ensure(index);
   53.40 -            underlying = underlying.set(index, value, strict);
   53.41 +            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
   53.42              setLength(Math.max(underlying.length(), length()));
   53.43          } else {
   53.44              final Long longIndex = indexToKey(index);
   53.45 @@ -209,8 +212,9 @@
   53.46      @Override
   53.47      public ArrayData set(final int index, final double value, final boolean strict) {
   53.48          if (index >= 0 && index < maxDenseLength) {
   53.49 +            final long oldLength = underlying.length();
   53.50              ensure(index);
   53.51 -            underlying = underlying.set(index, value, strict);
   53.52 +            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
   53.53              setLength(Math.max(underlying.length(), length()));
   53.54          } else {
   53.55              final Long longIndex = indexToKey(index);
    54.1 --- a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Mon Sep 28 15:36:24 2015 -0700
    54.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Tue Oct 06 11:04:55 2015 -0700
    54.3 @@ -83,7 +83,7 @@
    54.4      }
    54.5  
    54.6      @Override
    54.7 -    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
    54.8 +    public boolean canDelete(final long longIndex, final boolean strict) {
    54.9          return false;
   54.10      }
   54.11  
    55.1 --- a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Mon Sep 28 15:36:24 2015 -0700
    55.2 +++ b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Tue Oct 06 11:04:55 2015 -0700
    55.3 @@ -99,9 +99,10 @@
    55.4              return null;
    55.5          }
    55.6  
    55.7 -        final GuardedInvocation inv;
    55.8 +        GuardedInvocation inv;
    55.9          if (jsObjectClass.isInstance(self)) {
   55.10              inv = lookup(desc, request, linkerServices);
   55.11 +            inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard());
   55.12          } else {
   55.13              throw new AssertionError(); // Should never reach here.
   55.14          }
    56.1 --- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Mon Sep 28 15:36:24 2015 -0700
    56.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Tue Oct 06 11:04:55 2015 -0700
    56.3 @@ -77,9 +77,10 @@
    56.4              return null;
    56.5          }
    56.6  
    56.7 -        final GuardedInvocation inv;
    56.8 +        GuardedInvocation inv;
    56.9          if (self instanceof JSObject) {
   56.10              inv = lookup(desc, request, linkerServices);
   56.11 +            inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard());
   56.12          } else if (self instanceof Map || self instanceof Bindings) {
   56.13              // guard to make sure the Map or Bindings does not turn into JSObject later!
   56.14              final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices);
    57.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Mon Sep 28 15:36:24 2015 -0700
    57.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Tue Oct 06 11:04:55 2015 -0700
    57.3 @@ -203,6 +203,8 @@
    57.4  
    57.5      // This is the superclass for our generated adapter.
    57.6      private final Class<?> superClass;
    57.7 +    // Interfaces implemented by our generated adapter.
    57.8 +    private final List<Class<?>> interfaces;
    57.9      // Class loader used as the parent for the class loader we'll create to load the generated class. It will be a class
   57.10      // loader that has the visibility of all original types (class to extend and interfaces to implement) and of the
   57.11      // Nashorn classes.
   57.12 @@ -254,6 +256,7 @@
   57.13          assert interfaces != null;
   57.14  
   57.15          this.superClass = superClass;
   57.16 +        this.interfaces = interfaces;
   57.17          this.classOverride = classOverride;
   57.18          this.commonLoader = commonLoader;
   57.19          cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
   57.20 @@ -1031,6 +1034,24 @@
   57.21          endMethod(mv);
   57.22      }
   57.23  
   57.24 +    // find the appropriate super type to use for invokespecial on the given interface
   57.25 +    private Class<?> findInvokespecialOwnerFor(final Class<?> cl) {
   57.26 +        assert Modifier.isInterface(cl.getModifiers()) : cl + " is not an interface";
   57.27 +
   57.28 +        if (cl.isAssignableFrom(superClass)) {
   57.29 +            return superClass;
   57.30 +        }
   57.31 +
   57.32 +        for (final Class<?> iface : interfaces) {
   57.33 +             if (cl.isAssignableFrom(iface)) {
   57.34 +                 return iface;
   57.35 +             }
   57.36 +        }
   57.37 +
   57.38 +        // we better that interface that extends the given interface!
   57.39 +        throw new AssertionError("can't find the class/interface that extends " + cl);
   57.40 +    }
   57.41 +
   57.42      private void emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name, final String methodDesc) {
   57.43          mv.visitVarInsn(ALOAD, 0);
   57.44          int nextParam = 1;
   57.45 @@ -1042,7 +1063,9 @@
   57.46  
   57.47          // default method - non-abstract, interface method
   57.48          if (Modifier.isInterface(owner.getModifiers())) {
   57.49 -            mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false);
   57.50 +            // we should call default method on the immediate "super" type - not on (possibly)
   57.51 +            // the indirectly inherited interface class!
   57.52 +            mv.invokespecial(Type.getInternalName(findInvokespecialOwnerFor(owner)), name, methodDesc, false);
   57.53          } else {
   57.54              mv.invokespecial(superClassName, name, methodDesc, false);
   57.55          }
    58.1 --- a/src/jdk/nashorn/tools/Shell.java	Mon Sep 28 15:36:24 2015 -0700
    58.2 +++ b/src/jdk/nashorn/tools/Shell.java	Tue Oct 06 11:04:55 2015 -0700
    58.3 @@ -54,7 +54,6 @@
    58.4  import jdk.nashorn.internal.runtime.ScriptEnvironment;
    58.5  import jdk.nashorn.internal.runtime.ScriptFunction;
    58.6  import jdk.nashorn.internal.runtime.ScriptRuntime;
    58.7 -import jdk.nashorn.internal.runtime.Source;
    58.8  import jdk.nashorn.internal.runtime.options.Options;
    58.9  
   58.10  /**
   58.11 @@ -255,12 +254,9 @@
   58.12                      return COMPILATION_ERROR;
   58.13                  }
   58.14  
   58.15 -                new Compiler(
   58.16 +                Compiler.forNoInstallerCompilation(
   58.17                         context,
   58.18 -                       env,
   58.19 -                       null, //null - pass no code installer - this is compile only
   58.20                         functionNode.getSource(),
   58.21 -                       context.getErrorManager(),
   58.22                         env._strict | functionNode.isStrict()).
   58.23                         compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL);
   58.24  
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/test/script/basic/JDK-8087312.js	Tue Oct 06 11:04:55 2015 -0700
    59.3 @@ -0,0 +1,53 @@
    59.4 +/*
    59.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    59.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    59.7 + * 
    59.8 + * This code is free software; you can redistribute it and/or modify it
    59.9 + * under the terms of the GNU General Public License version 2 only, as
   59.10 + * published by the Free Software Foundation.
   59.11 + * 
   59.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   59.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   59.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   59.15 + * version 2 for more details (a copy is included in the LICENSE file that
   59.16 + * accompanied this code).
   59.17 + * 
   59.18 + * You should have received a copy of the GNU General Public License version
   59.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   59.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   59.21 + * 
   59.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   59.23 + * or visit www.oracle.com if you need additional information or have any
   59.24 + * questions.
   59.25 + */
   59.26 +
   59.27 +/**
   59.28 + * JDK-8087312: PropertyMapWrapper.equals should compare className
   59.29 + *
   59.30 + * @test
   59.31 + * @run
   59.32 + * @fork
   59.33 + * @option -Dnashorn.debug=true
   59.34 + */
   59.35 +
   59.36 +function createObject(type) {
   59.37 +    // we want to make sure two different object literals with the same keys and types share the same property map.
   59.38 +    if (type) {
   59.39 +        return {
   59.40 +            a: "a",
   59.41 +            b: 1,
   59.42 +            c: 0.1
   59.43 +        }
   59.44 +    } else {
   59.45 +        return {
   59.46 +            a: "x",
   59.47 +            b: 10,
   59.48 +            c: 3.4
   59.49 +        }
   59.50 +    }
   59.51 +}
   59.52 +
   59.53 +var o1 = createObject(false);
   59.54 +var o2 = createObject(true);
   59.55 +Assert.assertTrue(Debug.map(o1) === Debug.map(o2));
   59.56 +
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/test/script/basic/JDK-8134488.js	Tue Oct 06 11:04:55 2015 -0700
    60.3 @@ -0,0 +1,46 @@
    60.4 +/*
    60.5 + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
    60.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    60.7 + * 
    60.8 + * This code is free software; you can redistribute it and/or modify it
    60.9 + * under the terms of the GNU General Public License version 2 only, as
   60.10 + * published by the Free Software Foundation.
   60.11 + * 
   60.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   60.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   60.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   60.15 + * version 2 for more details (a copy is included in the LICENSE file that
   60.16 + * accompanied this code).
   60.17 + * 
   60.18 + * You should have received a copy of the GNU General Public License version
   60.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   60.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   60.21 + * 
   60.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   60.23 + * or visit www.oracle.com if you need additional information or have any
   60.24 + * questions.
   60.25 + */
   60.26 +
   60.27 +/**
   60.28 + * JDK-8134488: var statement in if(false) block incorrectly evacuated into enclosing function
   60.29 + *
   60.30 + * @test
   60.31 + * @run
   60.32 + */
   60.33 +
   60.34 +var x = "string"; 
   60.35 +print(x); 
   60.36 +
   60.37 +(function f1() { 
   60.38 +    (function f2() { 
   60.39 +        // If it finds both 'print' and 'x', it'll print 'string'.
   60.40 +        print(x); 
   60.41 +    })(); 
   60.42 +
   60.43 +    if (false) { 
   60.44 +        (function f3() { 
   60.45 +            var x; 
   60.46 +        })(); 
   60.47 +    } 
   60.48 +
   60.49 +})(); 
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/test/script/basic/JDK-8134488.js.EXPECTED	Tue Oct 06 11:04:55 2015 -0700
    61.3 @@ -0,0 +1,2 @@
    61.4 +string
    61.5 +string
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/test/script/basic/JDK-8134490.js	Tue Oct 06 11:04:55 2015 -0700
    62.3 @@ -0,0 +1,41 @@
    62.4 +/*
    62.5 + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
    62.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    62.7 + * 
    62.8 + * This code is free software; you can redistribute it and/or modify it
    62.9 + * under the terms of the GNU General Public License version 2 only, as
   62.10 + * published by the Free Software Foundation.
   62.11 + * 
   62.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   62.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   62.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   62.15 + * version 2 for more details (a copy is included in the LICENSE file that
   62.16 + * accompanied this code).
   62.17 + * 
   62.18 + * You should have received a copy of the GNU General Public License version
   62.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   62.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   62.21 + * 
   62.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   62.23 + * or visit www.oracle.com if you need additional information or have any
   62.24 + * questions.
   62.25 + */
   62.26 +
   62.27 +/**
   62.28 + * JDK-8134490: Dead var statement evacuation incorrectly descends into nested functions
   62.29 + *
   62.30 + * @test
   62.31 + * @run
   62.32 + */
   62.33 +
   62.34 +var v1; 
   62.35 +
   62.36 +function f1() 
   62.37 +{ 
   62.38 +v1 = 1; 
   62.39 +return true; 
   62.40 +(function () { var v1; })(); 
   62.41 +} 
   62.42 +
   62.43 +f1(); 
   62.44 +// If it executes without throwing an exception in code generator, it's working.
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/test/script/basic/JDK-8134569.js	Tue Oct 06 11:04:55 2015 -0700
    63.3 @@ -0,0 +1,207 @@
    63.4 +/*
    63.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    63.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    63.7 + * 
    63.8 + * This code is free software; you can redistribute it and/or modify it
    63.9 + * under the terms of the GNU General Public License version 2 only, as
   63.10 + * published by the Free Software Foundation.
   63.11 + * 
   63.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   63.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   63.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   63.15 + * version 2 for more details (a copy is included in the LICENSE file that
   63.16 + * accompanied this code).
   63.17 + * 
   63.18 + * You should have received a copy of the GNU General Public License version
   63.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   63.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   63.21 + * 
   63.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   63.23 + * or visit www.oracle.com if you need additional information or have any
   63.24 + * questions.
   63.25 + */
   63.26 +
   63.27 +/**
   63.28 + * JDK-8134569: Add tests for prototype callsites
   63.29 + *
   63.30 + * @test
   63.31 + * @run
   63.32 + */
   63.33 +
   63.34 +function create() {
   63.35 +    function C() {
   63.36 +        this.i1 = 1;
   63.37 +        this.i2 = 2;
   63.38 +        this.i3 = 3;
   63.39 +        return this;
   63.40 +    }
   63.41 +    return new C();
   63.42 +}
   63.43 +
   63.44 +function createEmpty() {
   63.45 +    function C() {
   63.46 +        return this;
   63.47 +    }
   63.48 +    return new C();
   63.49 +}
   63.50 +
   63.51 +function createDeep() {
   63.52 +    function C() {
   63.53 +        this.i1 = 1;
   63.54 +        this.i2 = 2;
   63.55 +        this.i3 = 3;
   63.56 +        return this;
   63.57 +    }
   63.58 +    function D() {
   63.59 +        this.p1 = 1;
   63.60 +        this.p2 = 2;
   63.61 +        this.p3 = 3;
   63.62 +        return this;
   63.63 +    }
   63.64 +    C.prototype = new D();
   63.65 +    return new C();
   63.66 +}
   63.67 +
   63.68 +function createDeeper() {
   63.69 +    function C() {
   63.70 +        this.i1 = 1;
   63.71 +        this.i2 = 2;
   63.72 +        this.i3 = 3;
   63.73 +        return this;
   63.74 +    }
   63.75 +    function D() {
   63.76 +        this.p1 = 1;
   63.77 +        this.p2 = 2;
   63.78 +        this.p3 = 3;
   63.79 +        return this;
   63.80 +    }
   63.81 +    function E() {
   63.82 +        this.e1 = 1;
   63.83 +        this.e2 = 2;
   63.84 +        this.e3 = 3;
   63.85 +        return this;
   63.86 +    }
   63.87 +    D.prototype = new E();
   63.88 +    C.prototype = new D();
   63.89 +    return new C();
   63.90 +}
   63.91 +
   63.92 +function createEval() {
   63.93 +    return eval("Object.create({})");
   63.94 +}
   63.95 +
   63.96 +function p(o) { print(o.x) }
   63.97 +
   63.98 +function e(o) { print(o.e1) }
   63.99 +
  63.100 +var a, b, c;
  63.101 +
  63.102 +create();
  63.103 +a = create();
  63.104 +b = create();
  63.105 +c = create();
  63.106 +a.__proto__.x = 123;
  63.107 +
  63.108 +p(a);
  63.109 +p(b);
  63.110 +p(c);
  63.111 +
  63.112 +a = create();
  63.113 +b = create();
  63.114 +c = create();
  63.115 +b.__proto__.x = 123;
  63.116 +
  63.117 +p(a);
  63.118 +p(b);
  63.119 +p(c);
  63.120 +
  63.121 +a = createEmpty();
  63.122 +b = createEmpty();
  63.123 +c = createEmpty();
  63.124 +a.__proto__.x = 123;
  63.125 +
  63.126 +p(a);
  63.127 +p(b);
  63.128 +p(c);
  63.129 +
  63.130 +a = createEmpty();
  63.131 +b = createEmpty();
  63.132 +c = createEmpty();
  63.133 +b.__proto__.x = 123;
  63.134 +
  63.135 +p(a);
  63.136 +p(b);
  63.137 +p(c);
  63.138 +
  63.139 +a = createDeep();
  63.140 +b = createDeep();
  63.141 +c = createDeep();
  63.142 +a.__proto__.__proto__.x = 123;
  63.143 +
  63.144 +p(a);
  63.145 +p(b);
  63.146 +p(c);
  63.147 +
  63.148 +a = createDeep();
  63.149 +b = createDeep();
  63.150 +c = createDeep();
  63.151 +b.__proto__.__proto__.x = 123;
  63.152 +
  63.153 +p(a);
  63.154 +p(b);
  63.155 +p(c);
  63.156 +
  63.157 +a = createDeeper();
  63.158 +b = createDeeper();
  63.159 +c = createDeeper();
  63.160 +a.__proto__.__proto__.__proto__.x = 123;
  63.161 +
  63.162 +p(a);
  63.163 +p(b);
  63.164 +p(c);
  63.165 +
  63.166 +a = createDeeper();
  63.167 +b = createDeeper();
  63.168 +c = createDeeper();
  63.169 +b.__proto__.__proto__.__proto__.x = 123;
  63.170 +
  63.171 +p(a);
  63.172 +p(b);
  63.173 +p(c);
  63.174 +
  63.175 +a = createDeeper();
  63.176 +b = createDeeper();
  63.177 +c = createDeeper();
  63.178 +a.__proto__.__proto__ = null;
  63.179 +
  63.180 +e(a);
  63.181 +e(b);
  63.182 +e(c);
  63.183 +
  63.184 +a = createDeeper();
  63.185 +b = createDeeper();
  63.186 +c = createDeeper();
  63.187 +b.__proto__.__proto__ = null;
  63.188 +
  63.189 +e(a);
  63.190 +e(b);
  63.191 +e(c);
  63.192 +
  63.193 +
  63.194 +a = createEval();
  63.195 +b = createEval();
  63.196 +c = createEval();
  63.197 +a.__proto__.x = 123;
  63.198 +
  63.199 +p(a);
  63.200 +p(b);
  63.201 +p(c);
  63.202 +
  63.203 +a = createEval();
  63.204 +b = createEval();
  63.205 +c = createEval();
  63.206 +b.__proto__.x = 123;
  63.207 +
  63.208 +p(a);
  63.209 +p(b);
  63.210 +p(c);
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/test/script/basic/JDK-8134569.js.EXPECTED	Tue Oct 06 11:04:55 2015 -0700
    64.3 @@ -0,0 +1,36 @@
    64.4 +123
    64.5 +undefined
    64.6 +undefined
    64.7 +undefined
    64.8 +123
    64.9 +undefined
   64.10 +123
   64.11 +undefined
   64.12 +undefined
   64.13 +undefined
   64.14 +123
   64.15 +undefined
   64.16 +123
   64.17 +undefined
   64.18 +undefined
   64.19 +undefined
   64.20 +123
   64.21 +undefined
   64.22 +123
   64.23 +undefined
   64.24 +undefined
   64.25 +undefined
   64.26 +123
   64.27 +undefined
   64.28 +undefined
   64.29 +1
   64.30 +1
   64.31 +1
   64.32 +undefined
   64.33 +1
   64.34 +123
   64.35 +undefined
   64.36 +undefined
   64.37 +undefined
   64.38 +123
   64.39 +undefined
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/test/script/basic/JDK-8134609.js	Tue Oct 06 11:04:55 2015 -0700
    65.3 @@ -0,0 +1,95 @@
    65.4 +/*
    65.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    65.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    65.7 + * 
    65.8 + * This code is free software; you can redistribute it and/or modify it
    65.9 + * under the terms of the GNU General Public License version 2 only, as
   65.10 + * published by the Free Software Foundation.
   65.11 + * 
   65.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   65.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   65.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   65.15 + * version 2 for more details (a copy is included in the LICENSE file that
   65.16 + * accompanied this code).
   65.17 + * 
   65.18 + * You should have received a copy of the GNU General Public License version
   65.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   65.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   65.21 + * 
   65.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   65.23 + * or visit www.oracle.com if you need additional information or have any
   65.24 + * questions.
   65.25 + */
   65.26 +
   65.27 +/**
   65.28 + * JDK-8134609: Allow constructors with same prototoype map to share the allocator map
   65.29 + *
   65.30 + * @test
   65.31 + * @run
   65.32 + * @fork
   65.33 + * @option -Dnashorn.debug
   65.34 + */
   65.35 +
   65.36 +function createProto(members) {
   65.37 +    function P() {
   65.38 +        for (var id in members) {
   65.39 +            if (members.hasOwnProperty(id)) {
   65.40 +                this[id] = members[id];
   65.41 +            }
   65.42 +        }
   65.43 +        return this;
   65.44 +    }
   65.45 +    return new P();
   65.46 +}
   65.47 +
   65.48 +function createSubclass(prototype, members) {
   65.49 +    function C() {
   65.50 +        for (var id in members) {
   65.51 +            if (members.hasOwnProperty(id)) {
   65.52 +                this[id] = members[id];
   65.53 +            }
   65.54 +        }
   65.55 +        return this;
   65.56 +    }
   65.57 +
   65.58 +    C.prototype = prototype;
   65.59 +
   65.60 +    return new C();
   65.61 +}
   65.62 +
   65.63 +function assertP1(object, value) {
   65.64 +    Assert.assertTrue(object.p1 === value);
   65.65 +}
   65.66 +
   65.67 +// First prototype will have non-shared proto-map. Second and third will be shared.
   65.68 +var proto0 = createProto({p1: 0, p2: 1});
   65.69 +var proto1 = createProto({p1: 1, p2: 2});
   65.70 +var proto2 = createProto({p1: 2, p2: 3});
   65.71 +
   65.72 +Assert.assertTrue(Debug.map(proto1) === Debug.map(proto2));
   65.73 +
   65.74 +assertP1(proto1, 1);
   65.75 +assertP1(proto2, 2);
   65.76 +
   65.77 +// First instantiation will have a non-shared prototype map, from the second one
   65.78 +// maps will be shared until a different proto map comes along.
   65.79 +var child0 = createSubclass(proto1, {c1: 1, c2: 2});
   65.80 +var child1 = createSubclass(proto2, {c1: 2, c2: 3});
   65.81 +var child2 = createSubclass(proto1, {c1: 3, c2: 4});
   65.82 +var child3 = createSubclass(proto2, {c1: 1, c2: 2});
   65.83 +var child4 = createSubclass(proto0, {c1: 3, c2: 2});
   65.84 +
   65.85 +Assert.assertTrue(Debug.map(child1) === Debug.map(child2));
   65.86 +Assert.assertTrue(Debug.map(child1) === Debug.map(child3));
   65.87 +Assert.assertTrue(Debug.map(child3) !== Debug.map(child4));
   65.88 +
   65.89 +assertP1(child1, 2);
   65.90 +assertP1(child2, 1);
   65.91 +assertP1(child3, 2);
   65.92 +assertP1(child4, 0);
   65.93 +
   65.94 +Assert.assertTrue(delete proto2.p1);
   65.95 +
   65.96 +assertP1(child3, undefined);
   65.97 +assertP1(child2, 1);
   65.98 +Assert.assertTrue(Debug.map(child1) !== Debug.map(child3));
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/test/script/basic/JDK-8135000.js	Tue Oct 06 11:04:55 2015 -0700
    66.3 @@ -0,0 +1,48 @@
    66.4 +/*
    66.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    66.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    66.7 + * 
    66.8 + * This code is free software; you can redistribute it and/or modify it
    66.9 + * under the terms of the GNU General Public License version 2 only, as
   66.10 + * published by the Free Software Foundation.
   66.11 + * 
   66.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   66.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   66.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   66.15 + * version 2 for more details (a copy is included in the LICENSE file that
   66.16 + * accompanied this code).
   66.17 + * 
   66.18 + * You should have received a copy of the GNU General Public License version
   66.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   66.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   66.21 + * 
   66.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   66.23 + * or visit www.oracle.com if you need additional information or have any
   66.24 + * questions.
   66.25 + */
   66.26 +
   66.27 +/**
   66.28 + * JDK-8135000: Number.prototype.toFixed returns wrong string for 0.5 and -0.5
   66.29 + *
   66.30 + * @test
   66.31 + * @run
   66.32 + */
   66.33 +
   66.34 +print(-2.6.toFixed());
   66.35 +print(-2.5.toFixed());
   66.36 +print(-2.4.toFixed());
   66.37 +print(-1.6.toFixed());
   66.38 +print(-1.5.toFixed());
   66.39 +print(-1.4.toFixed());
   66.40 +print(-0.6.toFixed());
   66.41 +print(-0.5.toFixed());
   66.42 +print(-0.4.toFixed());
   66.43 +print(0.4.toFixed());
   66.44 +print(0.5.toFixed());
   66.45 +print(0.6.toFixed());
   66.46 +print(1.4.toFixed());
   66.47 +print(1.5.toFixed());
   66.48 +print(1.6.toFixed());
   66.49 +print(2.4.toFixed());
   66.50 +print(2.5.toFixed());
   66.51 +print(2.6.toFixed());
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/test/script/basic/JDK-8135000.js.EXPECTED	Tue Oct 06 11:04:55 2015 -0700
    67.3 @@ -0,0 +1,18 @@
    67.4 +-3
    67.5 +-3
    67.6 +-2
    67.7 +-2
    67.8 +-2
    67.9 +-1
   67.10 +-1
   67.11 +-1
   67.12 +0
   67.13 +0
   67.14 +1
   67.15 +1
   67.16 +1
   67.17 +2
   67.18 +2
   67.19 +2
   67.20 +3
   67.21 +3
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/test/script/basic/JDK-8135190.js	Tue Oct 06 11:04:55 2015 -0700
    68.3 @@ -0,0 +1,67 @@
    68.4 +/*
    68.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    68.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    68.7 + * 
    68.8 + * This code is free software; you can redistribute it and/or modify it
    68.9 + * under the terms of the GNU General Public License version 2 only, as
   68.10 + * published by the Free Software Foundation.
   68.11 + * 
   68.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   68.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   68.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   68.15 + * version 2 for more details (a copy is included in the LICENSE file that
   68.16 + * accompanied this code).
   68.17 + * 
   68.18 + * You should have received a copy of the GNU General Public License version
   68.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   68.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   68.21 + * 
   68.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   68.23 + * or visit www.oracle.com if you need additional information or have any
   68.24 + * questions.
   68.25 + */
   68.26 +
   68.27 +/**
   68.28 + * JDK-8135190: Method code too large in Babel browser.js script
   68.29 + *
   68.30 + * @test
   68.31 + * @run
   68.32 + */
   68.33 +
   68.34 +// Make sure huge object literals are parsed correctly and don't throw
   68.35 +// (using buildObject -> JSON.stringify -> eval -> testObject)
   68.36 +
   68.37 +function buildObject(n, d) {
   68.38 +    if (n < 2) {
   68.39 +        return {name: "property", type: "identifier"};
   68.40 +    }
   68.41 +    var obj = {};
   68.42 +    for (var i = 0; i < n; i++) {
   68.43 +        obj["expr" + i] = buildObject(Math.floor(n / d), d);
   68.44 +    }
   68.45 +    return obj;
   68.46 +}
   68.47 +
   68.48 +function testObject(obj, n, d) {
   68.49 +    var keys = Object.keys(obj);
   68.50 +    if (n < 2) {
   68.51 +        Assert.assertTrue(keys.length === 2);
   68.52 +        Assert.assertTrue(keys[0] === "name");
   68.53 +        Assert.assertTrue(keys[1] === "type");
   68.54 +    } else {
   68.55 +        Assert.assertTrue(keys.length === n);
   68.56 +        for (var i = 0; i < n; i++) {
   68.57 +            Assert.assertTrue(keys[i] === "expr" + i);
   68.58 +        }
   68.59 +    }
   68.60 +    if (n >= 2) {
   68.61 +        for (var k in keys) {
   68.62 +            testObject(obj[keys[k]], Math.floor(n / d), d)
   68.63 +        }
   68.64 +    }
   68.65 +}
   68.66 +
   68.67 +var fieldObject = (eval("(" + JSON.stringify(buildObject(25, 2)) + ")"));
   68.68 +testObject(fieldObject, 25, 2);
   68.69 +var spillObject = (eval("(" + JSON.stringify(buildObject(1000, 100)) + ")"));
   68.70 +testObject(spillObject, 1000, 100);
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/test/script/basic/JDK-8137134.js	Tue Oct 06 11:04:55 2015 -0700
    69.3 @@ -0,0 +1,55 @@
    69.4 +/*
    69.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    69.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    69.7 + * 
    69.8 + * This code is free software; you can redistribute it and/or modify it
    69.9 + * under the terms of the GNU General Public License version 2 only, as
   69.10 + * published by the Free Software Foundation.
   69.11 + * 
   69.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   69.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   69.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   69.15 + * version 2 for more details (a copy is included in the LICENSE file that
   69.16 + * accompanied this code).
   69.17 + * 
   69.18 + * You should have received a copy of the GNU General Public License version
   69.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   69.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   69.21 + * 
   69.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   69.23 + * or visit www.oracle.com if you need additional information or have any
   69.24 + * questions.
   69.25 + */
   69.26 +
   69.27 +/**
   69.28 + * JDK-8137134: invokespecial on indirect super interface is generated by Java adapter generator
   69.29 + *
   69.30 + * @test
   69.31 + * @run
   69.32 + */
   69.33 +
   69.34 +var B = Java.type("jdk.nashorn.test.models.B");
   69.35 +var b1 = new B() {}
   69.36 +print(b1.a());
   69.37 +print(b1.b());
   69.38 +
   69.39 +var b2 = new B() {
   69.40 +    b: function() {
   69.41 +        return "from B.b in script";
   69.42 +    }
   69.43 +};
   69.44 +
   69.45 +print(b2.a());
   69.46 +print(b2.b());
   69.47 +
   69.48 +var b3 = new B() {
   69.49 +    a: function() {
   69.50 +        return "from A.a in script";
   69.51 +    },
   69.52 +    b: function() {
   69.53 +        return "from B.b in script";
   69.54 +    }
   69.55 +};
   69.56 +
   69.57 +print(b3.a());
   69.58 +print(b3.b());
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/test/script/basic/JDK-8137134.js.EXPECTED	Tue Oct 06 11:04:55 2015 -0700
    70.3 @@ -0,0 +1,6 @@
    70.4 +from A.a
    70.5 +from B.b
    70.6 +from A.a
    70.7 +from B.b in script
    70.8 +from A.a in script
    70.9 +from B.b in script
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/test/script/basic/JDK-8137281.js	Tue Oct 06 11:04:55 2015 -0700
    71.3 @@ -0,0 +1,49 @@
    71.4 +/*
    71.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    71.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    71.7 + * 
    71.8 + * This code is free software; you can redistribute it and/or modify it
    71.9 + * under the terms of the GNU General Public License version 2 only, as
   71.10 + * published by the Free Software Foundation.
   71.11 + * 
   71.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   71.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   71.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   71.15 + * version 2 for more details (a copy is included in the LICENSE file that
   71.16 + * accompanied this code).
   71.17 + * 
   71.18 + * You should have received a copy of the GNU General Public License version
   71.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   71.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   71.21 + * 
   71.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   71.23 + * or visit www.oracle.com if you need additional information or have any
   71.24 + * questions.
   71.25 + */
   71.26 +
   71.27 +/**
   71.28 + * JDK-8137281: OutOfMemoryError with large numeric keys in JSON.parse
   71.29 + *
   71.30 + * @test
   71.31 + * @run
   71.32 + */
   71.33 +
   71.34 +function createObject(startKey, level1, level2) {
   71.35 +    var root = {};
   71.36 +    var key = startKey;
   71.37 +    for (var i = 0; i < level1; i++) {
   71.38 +        var child = {};
   71.39 +        for (var j = 0; j < level2; j++) {
   71.40 +            child[key++] = {};
   71.41 +        }
   71.42 +        root[key++] = child;
   71.43 +    }
   71.44 +    return root;
   71.45 +}
   71.46 +
   71.47 +JSON.parse(JSON.stringify(createObject(500000, 20, 20)));
   71.48 +JSON.parse(JSON.stringify(createObject(1000000, 20, 20)));
   71.49 +JSON.parse(JSON.stringify(createObject(2000000, 20, 20)));
   71.50 +JSON.parse(JSON.stringify(createObject(4000000, 20, 20)));
   71.51 +JSON.parse(JSON.stringify(createObject(8000000, 20, 20)));
   71.52 +JSON.parse(JSON.stringify(createObject(16000000, 20, 20)));
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/test/script/basic/JDK-8138632.js	Tue Oct 06 11:04:55 2015 -0700
    72.3 @@ -0,0 +1,35 @@
    72.4 +/*
    72.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    72.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    72.7 + * 
    72.8 + * This code is free software; you can redistribute it and/or modify it
    72.9 + * under the terms of the GNU General Public License version 2 only, as
   72.10 + * published by the Free Software Foundation.
   72.11 + * 
   72.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   72.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   72.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   72.15 + * version 2 for more details (a copy is included in the LICENSE file that
   72.16 + * accompanied this code).
   72.17 + * 
   72.18 + * You should have received a copy of the GNU General Public License version
   72.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   72.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   72.21 + * 
   72.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   72.23 + * or visit www.oracle.com if you need additional information or have any
   72.24 + * questions.
   72.25 + */
   72.26 +
   72.27 +/**
   72.28 + * JDK-8138632: Sparse array does not handle growth of underlying dense array
   72.29 + *
   72.30 + * @test
   72.31 + * @run
   72.32 + */
   72.33 +
   72.34 +var x = [];
   72.35 +x[10000000] = 1;
   72.36 +x[10] = 1;
   72.37 +x[20] = 1;
   72.38 +print(Object.keys(x));
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/test/script/basic/JDK-8138632.js.EXPECTED	Tue Oct 06 11:04:55 2015 -0700
    73.3 @@ -0,0 +1,1 @@
    73.4 +10,20,10000000
    74.1 --- a/test/script/trusted/JDK-8006529.js	Mon Sep 28 15:36:24 2015 -0700
    74.2 +++ b/test/script/trusted/JDK-8006529.js	Tue Oct 06 11:04:55 2015 -0700
    74.3 @@ -120,7 +120,7 @@
    74.4  
    74.5  var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class)
    74.6  var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class)
    74.7 -var CompilerConstructor = Compiler.class.getConstructor(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, ErrorManager.class, boolean.class);
    74.8 +var CompilerConstructor = Compiler.class.getMethod("forNoInstallerCompilation", Context.class, Source.class, boolean.class);
    74.9  
   74.10  // compile(script) -- compiles a script specified as a string with its
   74.11  // source code, returns a jdk.nashorn.internal.ir.FunctionNode object
   74.12 @@ -134,7 +134,7 @@
   74.13      var parser   = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance());
   74.14      var func     = parseMethod.invoke(parser);
   74.15  
   74.16 -    var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, null, false);
   74.17 +    var compiler = CompilerConstructor.invoke(null, ctxt, source, false);
   74.18  
   74.19      return compileMethod.invoke(compiler, func, phases);
   74.20  };
    75.1 --- a/test/src/jdk/nashorn/api/scripting/JSONCompatibleTest.java	Mon Sep 28 15:36:24 2015 -0700
    75.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.3 @@ -1,117 +0,0 @@
    75.4 -/*
    75.5 - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    75.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    75.7 - *
    75.8 - * This code is free software; you can redistribute it and/or modify it
    75.9 - * under the terms of the GNU General Public License version 2 only, as
   75.10 - * published by the Free Software Foundation.  Oracle designates this
   75.11 - * particular file as subject to the "Classpath" exception as provided
   75.12 - * by Oracle in the LICENSE file that accompanied this code.
   75.13 - *
   75.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   75.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   75.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   75.17 - * version 2 for more details (a copy is included in the LICENSE file that
   75.18 - * accompanied this code).
   75.19 - *
   75.20 - * You should have received a copy of the GNU General Public License version
   75.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   75.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   75.23 - *
   75.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   75.25 - * or visit www.oracle.com if you need additional information or have any
   75.26 - * questions.
   75.27 - */
   75.28 -
   75.29 -package jdk.nashorn.api.scripting;
   75.30 -
   75.31 -import static org.testng.Assert.assertEquals;
   75.32 -import static org.testng.Assert.assertTrue;
   75.33 -
   75.34 -import java.util.Arrays;
   75.35 -import java.util.List;
   75.36 -import java.util.Map;
   75.37 -import javax.script.ScriptEngine;
   75.38 -import javax.script.ScriptException;
   75.39 -import org.testng.Assert;
   75.40 -import org.testng.annotations.Test;
   75.41 -
   75.42 -public class JSONCompatibleTest {
   75.43 -
   75.44 -    /**
   75.45 -     * Wrap a top-level array as a list.
   75.46 -     */
   75.47 -    @Test
   75.48 -    public void testWrapArray() throws ScriptException {
   75.49 -        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
   75.50 -        final Object val = engine.eval("Java.asJSONCompatible([1, 2, 3])");
   75.51 -        assertEquals(asList(val), Arrays.asList(1, 2, 3));
   75.52 -    }
   75.53 -
   75.54 -    /**
   75.55 -     * Wrap an embedded array as a list.
   75.56 -     */
   75.57 -    @Test
   75.58 -    public void testWrapObjectWithArray() throws ScriptException {
   75.59 -        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
   75.60 -        final Object val = engine.eval("Java.asJSONCompatible({x: [1, 2, 3]})");
   75.61 -        assertEquals(asList(asMap(val).get("x")), Arrays.asList(1, 2, 3));
   75.62 -    }
   75.63 -
   75.64 -    /**
   75.65 -     * Check it all works transitively several more levels down.
   75.66 -     */
   75.67 -    @Test
   75.68 -    public void testDeepWrapping() throws ScriptException {
   75.69 -        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
   75.70 -        final Object val = engine.eval("Java.asJSONCompatible({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
   75.71 -        final Map<String, Object> root = asMap(val);
   75.72 -        final List<Object> x = asList(root.get("x"));
   75.73 -        assertEquals(x.get(0), 1);
   75.74 -        final Map<String, Object> x1 = asMap(x.get(1));
   75.75 -        final List<Object> y = asList(x1.get("y"));
   75.76 -        assertEquals(y.get(0), 2);
   75.77 -        final Map<String, Object> y1 = asMap(y.get(1));
   75.78 -        assertEquals(asList(y1.get("z")), Arrays.asList(3));
   75.79 -        assertEquals(asList(x.get(2)), Arrays.asList(4, 5));
   75.80 -    }
   75.81 -
   75.82 -    /**
   75.83 -     * Ensure that the old behaviour (every object is a Map) is unchanged.
   75.84 -     */
   75.85 -    @Test
   75.86 -    public void testNonWrapping() throws ScriptException {
   75.87 -        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
   75.88 -        final Object val = engine.eval("({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
   75.89 -        final Map<String, Object> root = asMap(val);
   75.90 -        final Map<String, Object> x = asMap(root.get("x"));
   75.91 -        assertEquals(x.get("0"), 1);
   75.92 -        final Map<String, Object> x1 = asMap(x.get("1"));
   75.93 -        final Map<String, Object> y = asMap(x1.get("y"));
   75.94 -        assertEquals(y.get("0"), 2);
   75.95 -        final Map<String, Object> y1 = asMap(y.get("1"));
   75.96 -        final Map<String, Object> z = asMap(y1.get("z"));
   75.97 -        assertEquals(z.get("0"), 3);
   75.98 -        final Map<String, Object> x2 = asMap(x.get("2"));
   75.99 -        assertEquals(x2.get("0"), 4);
  75.100 -        assertEquals(x2.get("1"), 5);
  75.101 -    }
  75.102 -
  75.103 -    @SuppressWarnings("unchecked")
  75.104 -    private static List<Object> asList(final Object obj) {
  75.105 -        assertJSObject(obj);
  75.106 -        Assert.assertTrue(obj instanceof List);
  75.107 -        return (List)obj;
  75.108 -    }
  75.109 -
  75.110 -    @SuppressWarnings("unchecked")
  75.111 -    private static Map<String, Object> asMap(final Object obj) {
  75.112 -        assertJSObject(obj);
  75.113 -        Assert.assertTrue(obj instanceof Map);
  75.114 -        return (Map)obj;
  75.115 -    }
  75.116 -
  75.117 -    private static void assertJSObject(final Object obj) {
  75.118 -        assertTrue(obj instanceof JSObject);
  75.119 -    }
  75.120 -}
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/test/src/jdk/nashorn/api/scripting/test/JSONCompatibleTest.java	Tue Oct 06 11:04:55 2015 -0700
    76.3 @@ -0,0 +1,120 @@
    76.4 +/*
    76.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    76.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    76.7 + *
    76.8 + * This code is free software; you can redistribute it and/or modify it
    76.9 + * under the terms of the GNU General Public License version 2 only, as
   76.10 + * published by the Free Software Foundation.  Oracle designates this
   76.11 + * particular file as subject to the "Classpath" exception as provided
   76.12 + * by Oracle in the LICENSE file that accompanied this code.
   76.13 + *
   76.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   76.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   76.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   76.17 + * version 2 for more details (a copy is included in the LICENSE file that
   76.18 + * accompanied this code).
   76.19 + *
   76.20 + * You should have received a copy of the GNU General Public License version
   76.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   76.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   76.23 + *
   76.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   76.25 + * or visit www.oracle.com if you need additional information or have any
   76.26 + * questions.
   76.27 + */
   76.28 +
   76.29 +package jdk.nashorn.api.scripting.test;
   76.30 +
   76.31 +import static org.testng.Assert.assertEquals;
   76.32 +import static org.testng.Assert.assertTrue;
   76.33 +
   76.34 +import java.util.Arrays;
   76.35 +import java.util.List;
   76.36 +import java.util.Map;
   76.37 +import javax.script.ScriptEngine;
   76.38 +import javax.script.ScriptException;
   76.39 +import jdk.nashorn.api.scripting.JSObject;
   76.40 +import jdk.nashorn.api.scripting.NashornScriptEngine;
   76.41 +import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
   76.42 +import org.testng.Assert;
   76.43 +import org.testng.annotations.Test;
   76.44 +
   76.45 +public class JSONCompatibleTest {
   76.46 +
   76.47 +    /**
   76.48 +     * Wrap a top-level array as a list.
   76.49 +     */
   76.50 +    @Test
   76.51 +    public void testWrapArray() throws ScriptException {
   76.52 +        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
   76.53 +        final Object val = engine.eval("Java.asJSONCompatible([1, 2, 3])");
   76.54 +        assertEquals(asList(val), Arrays.asList(1, 2, 3));
   76.55 +    }
   76.56 +
   76.57 +    /**
   76.58 +     * Wrap an embedded array as a list.
   76.59 +     */
   76.60 +    @Test
   76.61 +    public void testWrapObjectWithArray() throws ScriptException {
   76.62 +        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
   76.63 +        final Object val = engine.eval("Java.asJSONCompatible({x: [1, 2, 3]})");
   76.64 +        assertEquals(asList(asMap(val).get("x")), Arrays.asList(1, 2, 3));
   76.65 +    }
   76.66 +
   76.67 +    /**
   76.68 +     * Check it all works transitively several more levels down.
   76.69 +     */
   76.70 +    @Test
   76.71 +    public void testDeepWrapping() throws ScriptException {
   76.72 +        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
   76.73 +        final Object val = engine.eval("Java.asJSONCompatible({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
   76.74 +        final Map<String, Object> root = asMap(val);
   76.75 +        final List<Object> x = asList(root.get("x"));
   76.76 +        assertEquals(x.get(0), 1);
   76.77 +        final Map<String, Object> x1 = asMap(x.get(1));
   76.78 +        final List<Object> y = asList(x1.get("y"));
   76.79 +        assertEquals(y.get(0), 2);
   76.80 +        final Map<String, Object> y1 = asMap(y.get(1));
   76.81 +        assertEquals(asList(y1.get("z")), Arrays.asList(3));
   76.82 +        assertEquals(asList(x.get(2)), Arrays.asList(4, 5));
   76.83 +    }
   76.84 +
   76.85 +    /**
   76.86 +     * Ensure that the old behaviour (every object is a Map) is unchanged.
   76.87 +     */
   76.88 +    @Test
   76.89 +    public void testNonWrapping() throws ScriptException {
   76.90 +        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
   76.91 +        final Object val = engine.eval("({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
   76.92 +        final Map<String, Object> root = asMap(val);
   76.93 +        final Map<String, Object> x = asMap(root.get("x"));
   76.94 +        assertEquals(x.get("0"), 1);
   76.95 +        final Map<String, Object> x1 = asMap(x.get("1"));
   76.96 +        final Map<String, Object> y = asMap(x1.get("y"));
   76.97 +        assertEquals(y.get("0"), 2);
   76.98 +        final Map<String, Object> y1 = asMap(y.get("1"));
   76.99 +        final Map<String, Object> z = asMap(y1.get("z"));
  76.100 +        assertEquals(z.get("0"), 3);
  76.101 +        final Map<String, Object> x2 = asMap(x.get("2"));
  76.102 +        assertEquals(x2.get("0"), 4);
  76.103 +        assertEquals(x2.get("1"), 5);
  76.104 +    }
  76.105 +
  76.106 +    @SuppressWarnings("unchecked")
  76.107 +    private static List<Object> asList(final Object obj) {
  76.108 +        assertJSObject(obj);
  76.109 +        Assert.assertTrue(obj instanceof List);
  76.110 +        return (List)obj;
  76.111 +    }
  76.112 +
  76.113 +    @SuppressWarnings("unchecked")
  76.114 +    private static Map<String, Object> asMap(final Object obj) {
  76.115 +        assertJSObject(obj);
  76.116 +        Assert.assertTrue(obj instanceof Map);
  76.117 +        return (Map)obj;
  76.118 +    }
  76.119 +
  76.120 +    private static void assertJSObject(final Object obj) {
  76.121 +        assertTrue(obj instanceof JSObject);
  76.122 +    }
  76.123 +}
    77.1 --- a/test/src/jdk/nashorn/api/scripting/test/PluggableJSObjectTest.java	Mon Sep 28 15:36:24 2015 -0700
    77.2 +++ b/test/src/jdk/nashorn/api/scripting/test/PluggableJSObjectTest.java	Tue Oct 06 11:04:55 2015 -0700
    77.3 @@ -27,6 +27,7 @@
    77.4  
    77.5  import static org.testng.Assert.assertEquals;
    77.6  import static org.testng.Assert.assertFalse;
    77.7 +import static org.testng.Assert.assertTrue;
    77.8  import static org.testng.Assert.fail;
    77.9  
   77.10  import java.nio.IntBuffer;
   77.11 @@ -34,9 +35,11 @@
   77.12  import java.util.HashMap;
   77.13  import java.util.LinkedHashMap;
   77.14  import java.util.Set;
   77.15 +import javax.script.Invocable;
   77.16  import javax.script.ScriptEngine;
   77.17  import javax.script.ScriptEngineManager;
   77.18  import jdk.nashorn.api.scripting.AbstractJSObject;
   77.19 +import jdk.nashorn.api.scripting.ScriptObjectMirror;
   77.20  import org.testng.annotations.Test;
   77.21  
   77.22  /**
   77.23 @@ -286,4 +289,23 @@
   77.24              fail(exp.getMessage());
   77.25          }
   77.26      }
   77.27 +
   77.28 +    // @bug 8137258: JSObjectLinker and BrowserJSObjectLinker should not expose internal JS objects
   77.29 +    @Test
   77.30 +    public void hidingInternalObjectsForJSObjectTest() throws Exception {
   77.31 +        final ScriptEngineManager engineManager = new ScriptEngineManager();
   77.32 +        final ScriptEngine e = engineManager.getEngineByName("nashorn");
   77.33 +
   77.34 +        final String code = "function func(obj) { obj.foo = [5, 5]; obj.bar = {} }";
   77.35 +        e.eval(code);
   77.36 +
   77.37 +        // call the exposed function but pass user defined JSObject impl as argument
   77.38 +        ((Invocable)e).invokeFunction("func", new AbstractJSObject() {
   77.39 +            @Override
   77.40 +            public void setMember(final String name, final Object value) {
   77.41 +                // make sure that wrapped objects are passed (and not internal impl. objects)
   77.42 +                assertTrue(value.getClass() == ScriptObjectMirror.class);
   77.43 +            }
   77.44 +        });
   77.45 +    }
   77.46  }
    78.1 --- a/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java	Mon Sep 28 15:36:24 2015 -0700
    78.2 +++ b/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java	Tue Oct 06 11:04:55 2015 -0700
    78.3 @@ -30,6 +30,7 @@
    78.4  import static org.testng.Assert.assertTrue;
    78.5  import static org.testng.Assert.fail;
    78.6  import javax.script.Bindings;
    78.7 +import javax.script.Invocable;
    78.8  import javax.script.ScriptContext;
    78.9  import javax.script.ScriptEngine;
   78.10  import javax.script.ScriptEngineFactory;
   78.11 @@ -855,4 +856,59 @@
   78.12              assertTrue(ret, "Expected true in iteration " + i);
   78.13          }
   78.14      }
   78.15 +
   78.16 +    // @bug 8138616: invokeFunction fails if function calls a function defined in GLOBAL_SCOPE
   78.17 +    @Test
   78.18 +    public void invokeFunctionInGlobalScopeTest() throws Exception {
   78.19 +         final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
   78.20 +         final ScriptContext ctxt = engine.getContext();
   78.21 +
   78.22 +         // define a function called "func"
   78.23 +         engine.eval("func = function() { return 42 }");
   78.24 +
   78.25 +         // move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
   78.26 +         ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
   78.27 +
   78.28 +         // create a new Bindings and set as ENGINE_SCOPE
   78.29 +         ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
   78.30 +
   78.31 +         // define new function that calls "func" now in GLOBAL_SCOPE
   78.32 +         engine.eval("newfunc = function() { return func() }");
   78.33 +
   78.34 +         // call "newfunc" and check the return value
   78.35 +         Object value = ((Invocable)engine).invokeFunction("newfunc");
   78.36 +         assertTrue(((Number)value).intValue() == 42);
   78.37 +    }
   78.38 +
   78.39 +
   78.40 +    // @bug 8138616: invokeFunction fails if function calls a function defined in GLOBAL_SCOPE
   78.41 +    // variant of above that replaces default ScriptContext of the engine with a fresh instance!
   78.42 +    @Test
   78.43 +    public void invokeFunctionInGlobalScopeTest2() throws Exception {
   78.44 +         final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
   78.45 +
   78.46 +         // create a new ScriptContext instance
   78.47 +         final ScriptContext ctxt = new SimpleScriptContext();
   78.48 +         // set it as 'default' ScriptContext
   78.49 +         engine.setContext(ctxt);
   78.50 +
   78.51 +         // create a new Bindings and set as ENGINE_SCOPE
   78.52 +         ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
   78.53 +
   78.54 +         // define a function called "func"
   78.55 +         engine.eval("func = function() { return 42 }");
   78.56 +
   78.57 +         // move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
   78.58 +         ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
   78.59 +
   78.60 +         // create a new Bindings and set as ENGINE_SCOPE
   78.61 +         ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
   78.62 +
   78.63 +         // define new function that calls "func" now in GLOBAL_SCOPE
   78.64 +         engine.eval("newfunc = function() { return func() }");
   78.65 +
   78.66 +         // call "newfunc" and check the return value
   78.67 +         Object value = ((Invocable)engine).invokeFunction("newfunc");
   78.68 +         assertTrue(((Number)value).intValue() == 42);
   78.69 +    }
   78.70  }
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/test/src/jdk/nashorn/test/models/A.java	Tue Oct 06 11:04:55 2015 -0700
    79.3 @@ -0,0 +1,32 @@
    79.4 +/*
    79.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    79.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    79.7 + *
    79.8 + * This code is free software; you can redistribute it and/or modify it
    79.9 + * under the terms of the GNU General Public License version 2 only, as
   79.10 + * published by the Free Software Foundation.  Oracle designates this
   79.11 + * particular file as subject to the "Classpath" exception as provided
   79.12 + * by Oracle in the LICENSE file that accompanied this code.
   79.13 + *
   79.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   79.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   79.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   79.17 + * version 2 for more details (a copy is included in the LICENSE file that
   79.18 + * accompanied this code).
   79.19 + *
   79.20 + * You should have received a copy of the GNU General Public License version
   79.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   79.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   79.23 + *
   79.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   79.25 + * or visit www.oracle.com if you need additional information or have any
   79.26 + * questions.
   79.27 + */
   79.28 +
   79.29 +package jdk.nashorn.test.models;
   79.30 +
   79.31 +public interface A {
   79.32 +    default String a() {
   79.33 +        return "from A.a";
   79.34 +    }
   79.35 +}
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/test/src/jdk/nashorn/test/models/B.java	Tue Oct 06 11:04:55 2015 -0700
    80.3 @@ -0,0 +1,32 @@
    80.4 +/*
    80.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
    80.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    80.7 + *
    80.8 + * This code is free software; you can redistribute it and/or modify it
    80.9 + * under the terms of the GNU General Public License version 2 only, as
   80.10 + * published by the Free Software Foundation.  Oracle designates this
   80.11 + * particular file as subject to the "Classpath" exception as provided
   80.12 + * by Oracle in the LICENSE file that accompanied this code.
   80.13 + *
   80.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   80.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   80.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   80.17 + * version 2 for more details (a copy is included in the LICENSE file that
   80.18 + * accompanied this code).
   80.19 + *
   80.20 + * You should have received a copy of the GNU General Public License version
   80.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   80.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   80.23 + *
   80.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   80.25 + * or visit www.oracle.com if you need additional information or have any
   80.26 + * questions.
   80.27 + */
   80.28 +
   80.29 +package jdk.nashorn.test.models;
   80.30 +
   80.31 +public interface B extends A {
   80.32 +    default String b() {
   80.33 +        return "from B.b";
   80.34 +    }
   80.35 +}

mercurial