Fri, 30 Sep 2016 19:40:31 +0200
8166902: Nested object literal property maps not reset in optimistic recompilation
Reviewed-by: lagergren, attila
1.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Oct 10 20:28:14 2016 -0700 1.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Sep 30 19:40:31 2016 +0200 1.3 @@ -2454,11 +2454,6 @@ 1.4 } 1.5 1.6 @Override 1.7 - public boolean enterObjectNode(final ObjectNode objectNode) { 1.8 - return false; 1.9 - } 1.10 - 1.11 - @Override 1.12 public boolean enterDefault(final Node node) { 1.13 if (contains) { 1.14 return false; 1.15 @@ -2526,7 +2521,8 @@ 1.16 oc = new FieldObjectCreator<Expression>(this, tuples) { 1.17 @Override 1.18 protected void loadValue(final Expression node, final Type type) { 1.19 - loadExpressionAsType(node, type); 1.20 + // Use generic type in order to avoid conversion between object types 1.21 + loadExpressionAsType(node, Type.generic(type)); 1.22 }}; 1.23 } 1.24 1.25 @@ -2542,10 +2538,7 @@ 1.26 //handler 1.27 if (restOfProperty) { 1.28 final ContinuationInfo ci = getContinuationInfo(); 1.29 - // Can be set at most once for a single rest-of method 1.30 - assert ci.getObjectLiteralMap() == null; 1.31 - ci.setObjectLiteralMap(oc.getMap()); 1.32 - ci.setObjectLiteralStackDepth(method.getStackSize()); 1.33 + ci.setObjectLiteralMap(method.getStackSize(), oc.getMap()); 1.34 } 1.35 1.36 method.dup(); 1.37 @@ -5259,10 +5252,8 @@ 1.38 private Type[] stackTypes; 1.39 // If non-null, this node should perform the requisite type conversion 1.40 private Type returnValueType; 1.41 - // If we are in the middle of an object literal initialization, we need to update the map 1.42 - private PropertyMap objectLiteralMap; 1.43 - // Object literal stack depth for object literal - not necessarily top if property is a tree 1.44 - private int objectLiteralStackDepth = -1; 1.45 + // If we are in the middle of an object literal initialization, we need to update the property maps 1.46 + private Map<Integer, PropertyMap> objectLiteralMaps; 1.47 // The line number at the continuation point 1.48 private int lineNumber; 1.49 // The active catch label, in case the continuation point is in a try/catch block 1.50 @@ -5314,20 +5305,15 @@ 1.51 this.returnValueType = returnValueType; 1.52 } 1.53 1.54 - int getObjectLiteralStackDepth() { 1.55 - return objectLiteralStackDepth; 1.56 - } 1.57 - 1.58 - void setObjectLiteralStackDepth(final int objectLiteralStackDepth) { 1.59 - this.objectLiteralStackDepth = objectLiteralStackDepth; 1.60 - } 1.61 - 1.62 - PropertyMap getObjectLiteralMap() { 1.63 - return objectLiteralMap; 1.64 - } 1.65 - 1.66 - void setObjectLiteralMap(final PropertyMap objectLiteralMap) { 1.67 - this.objectLiteralMap = objectLiteralMap; 1.68 + void setObjectLiteralMap(final int objectLiteralStackDepth, final PropertyMap objectLiteralMap) { 1.69 + if (objectLiteralMaps == null) { 1.70 + objectLiteralMaps = new HashMap<>(); 1.71 + } 1.72 + objectLiteralMaps.put(objectLiteralStackDepth, objectLiteralMap); 1.73 + } 1.74 + 1.75 + PropertyMap getObjectLiteralMap(final int stackDepth) { 1.76 + return objectLiteralMaps == null ? null : objectLiteralMaps.get(stackDepth); 1.77 } 1.78 1.79 @Override 1.80 @@ -5417,10 +5403,9 @@ 1.81 final int[] stackStoreSpec = ci.getStackStoreSpec(); 1.82 final Type[] stackTypes = ci.getStackTypes(); 1.83 final boolean isStackEmpty = stackStoreSpec.length == 0; 1.84 - boolean replacedObjectLiteralMap = false; 1.85 + int replacedObjectLiteralMaps = 0; 1.86 if(!isStackEmpty) { 1.87 // Load arguments on the stack 1.88 - final int objectLiteralStackDepth = ci.getObjectLiteralStackDepth(); 1.89 for(int i = 0; i < stackStoreSpec.length; ++i) { 1.90 final int slot = stackStoreSpec[i]; 1.91 method.load(lvarTypes.get(slot), slot); 1.92 @@ -5428,18 +5413,18 @@ 1.93 // stack: s0=object literal being initialized 1.94 // change map of s0 so that the property we are initializing when we failed 1.95 // is now ci.returnValueType 1.96 - if (i == objectLiteralStackDepth) { 1.97 + final PropertyMap map = ci.getObjectLiteralMap(i); 1.98 + if (map != null) { 1.99 method.dup(); 1.100 - assert ci.getObjectLiteralMap() != null; 1.101 assert ScriptObject.class.isAssignableFrom(method.peekType().getTypeClass()) : method.peekType().getTypeClass() + " is not a script object"; 1.102 - loadConstant(ci.getObjectLiteralMap()); 1.103 + loadConstant(map); 1.104 method.invoke(ScriptObject.SET_MAP); 1.105 - replacedObjectLiteralMap = true; 1.106 + replacedObjectLiteralMaps++; 1.107 } 1.108 } 1.109 } 1.110 - // Must have emitted the code for replacing the map of an object literal if we have a set object literal stack depth 1.111 - assert ci.getObjectLiteralStackDepth() == -1 || replacedObjectLiteralMap; 1.112 + // Must have emitted the code for replacing all object literal maps 1.113 + assert ci.objectLiteralMaps == null || ci.objectLiteralMaps.size() == replacedObjectLiteralMaps; 1.114 // Load RewriteException back. 1.115 method.load(rewriteExceptionType, lvarCount); 1.116 // Get rid of the stored reference
2.1 --- a/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java Mon Oct 10 20:28:14 2016 -0700 2.2 +++ b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java Fri Sep 30 19:40:31 2016 +0200 2.3 @@ -188,7 +188,8 @@ 2.4 2.5 @Override 2.6 protected void loadValue(final Expression expr, final Type type) { 2.7 - codegen.loadExpressionAsType(expr, type); 2.8 + // Use generic type in order to avoid conversion between object types 2.9 + codegen.loadExpressionAsType(expr, Type.generic(type)); 2.10 } 2.11 2.12 @Override
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/script/basic/JDK-8166902.js Fri Sep 30 19:40:31 2016 +0200 3.3 @@ -0,0 +1,43 @@ 3.4 +/* 3.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/** 3.28 + * JDK-8166902: Nested object literal property maps not reset in optimistic recompilation 3.29 + * 3.30 + * @test 3.31 + * @run 3.32 + */ 3.33 + 3.34 +var o = { 3.35 + a: "A", 3.36 + b: "B" 3.37 +}; 3.38 + 3.39 +var m = { 3.40 + x: { z: o.a }, 3.41 + y: o.b 3.42 +}; 3.43 + 3.44 +Assert.assertEquals(m.x.z, "A"); 3.45 +Assert.assertEquals(m.y, "B"); 3.46 +