# HG changeset patch # User hannesw # Date 1475257231 -7200 # Node ID a3c1a712c67ed703072a8850f109380e3c6459d3 # Parent 0c17b3fdc0430b8b7aad31a3c59d2dd8596e1e50 8166902: Nested object literal property maps not reset in optimistic recompilation Reviewed-by: lagergren, attila diff -r 0c17b3fdc043 -r a3c1a712c67e nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Sep 29 16:45:12 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Sep 30 19:40:31 2016 +0200 @@ -2486,11 +2486,6 @@ } @Override - public boolean enterObjectNode(final ObjectNode objectNode) { - return false; - } - - @Override public boolean enterDefault(final Node node) { if (contains) { return false; @@ -2562,7 +2557,8 @@ oc = new FieldObjectCreator(this, tuples) { @Override protected void loadValue(final Expression node, final Type type) { - loadExpressionAsType(node, type); + // Use generic type in order to avoid conversion between object types + loadExpressionAsType(node, Type.generic(type)); }}; } @@ -2578,10 +2574,7 @@ //handler if (restOfProperty) { final ContinuationInfo ci = getContinuationInfo(); - // Can be set at most once for a single rest-of method - assert ci.getObjectLiteralMap() == null; - ci.setObjectLiteralMap(oc.getMap()); - ci.setObjectLiteralStackDepth(method.getStackSize()); + ci.setObjectLiteralMap(method.getStackSize(), oc.getMap()); } method.dup(); @@ -5309,10 +5302,8 @@ private Type[] stackTypes; // If non-null, this node should perform the requisite type conversion private Type returnValueType; - // If we are in the middle of an object literal initialization, we need to update the map - private PropertyMap objectLiteralMap; - // Object literal stack depth for object literal - not necessarily top if property is a tree - private int objectLiteralStackDepth = -1; + // If we are in the middle of an object literal initialization, we need to update the property maps + private Map objectLiteralMaps; // The line number at the continuation point private int lineNumber; // The active catch label, in case the continuation point is in a try/catch block @@ -5364,20 +5355,15 @@ this.returnValueType = returnValueType; } - int getObjectLiteralStackDepth() { - return objectLiteralStackDepth; - } - - void setObjectLiteralStackDepth(final int objectLiteralStackDepth) { - this.objectLiteralStackDepth = objectLiteralStackDepth; - } - - PropertyMap getObjectLiteralMap() { - return objectLiteralMap; - } - - void setObjectLiteralMap(final PropertyMap objectLiteralMap) { - this.objectLiteralMap = objectLiteralMap; + void setObjectLiteralMap(final int objectLiteralStackDepth, final PropertyMap objectLiteralMap) { + if (objectLiteralMaps == null) { + objectLiteralMaps = new HashMap<>(); + } + objectLiteralMaps.put(objectLiteralStackDepth, objectLiteralMap); + } + + PropertyMap getObjectLiteralMap(final int stackDepth) { + return objectLiteralMaps == null ? null : objectLiteralMaps.get(stackDepth); } @Override @@ -5467,10 +5453,9 @@ final int[] stackStoreSpec = ci.getStackStoreSpec(); final Type[] stackTypes = ci.getStackTypes(); final boolean isStackEmpty = stackStoreSpec.length == 0; - boolean replacedObjectLiteralMap = false; + int replacedObjectLiteralMaps = 0; if(!isStackEmpty) { // Load arguments on the stack - final int objectLiteralStackDepth = ci.getObjectLiteralStackDepth(); for(int i = 0; i < stackStoreSpec.length; ++i) { final int slot = stackStoreSpec[i]; method.load(lvarTypes.get(slot), slot); @@ -5478,18 +5463,18 @@ // stack: s0=object literal being initialized // change map of s0 so that the property we are initializing when we failed // is now ci.returnValueType - if (i == objectLiteralStackDepth) { + final PropertyMap map = ci.getObjectLiteralMap(i); + if (map != null) { method.dup(); - assert ci.getObjectLiteralMap() != null; assert ScriptObject.class.isAssignableFrom(method.peekType().getTypeClass()) : method.peekType().getTypeClass() + " is not a script object"; - loadConstant(ci.getObjectLiteralMap()); + loadConstant(map); method.invoke(ScriptObject.SET_MAP); - replacedObjectLiteralMap = true; + replacedObjectLiteralMaps++; } } } - // Must have emitted the code for replacing the map of an object literal if we have a set object literal stack depth - assert ci.getObjectLiteralStackDepth() == -1 || replacedObjectLiteralMap; + // Must have emitted the code for replacing all object literal maps + assert ci.objectLiteralMaps == null || ci.objectLiteralMaps.size() == replacedObjectLiteralMaps; // Load RewriteException back. method.load(rewriteExceptionType, lvarCount); // Get rid of the stored reference diff -r 0c17b3fdc043 -r a3c1a712c67e nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SpillObjectCreator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SpillObjectCreator.java Thu Sep 29 16:45:12 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SpillObjectCreator.java Fri Sep 30 19:40:31 2016 +0200 @@ -189,7 +189,8 @@ @Override protected void loadValue(final Expression expr, final Type type) { - codegen.loadExpressionAsType(expr, type); + // Use generic type in order to avoid conversion between object types + codegen.loadExpressionAsType(expr, Type.generic(type)); } @Override diff -r 0c17b3fdc043 -r a3c1a712c67e nashorn/test/script/basic/JDK-8166902.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8166902.js Fri Sep 30 19:40:31 2016 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8166902: Nested object literal property maps not reset in optimistic recompilation + * + * @test + * @run + */ + +var o = { + a: "A", + b: "B" +}; + +var m = { + x: { z: o.a }, + y: o.b +}; + +Assert.assertEquals(m.x.z, "A"); +Assert.assertEquals(m.y, "B"); +