Tue, 06 Oct 2015 11:04:55 -0700
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 >= 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 +}