8166902: Nested object literal property maps not reset in optimistic recompilation

Fri, 30 Sep 2016 19:40:31 +0200

author
hannesw
date
Fri, 30 Sep 2016 19:40:31 +0200
changeset 1975
64034f7f4f5e
parent 1974
ae37f23de043
child 1976
3c3b4e793e7c

8166902: Nested object literal property maps not reset in optimistic recompilation
Reviewed-by: lagergren, attila

src/jdk/nashorn/internal/codegen/CodeGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/SpillObjectCreator.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8166902.js file | annotate | diff | comparison | revisions
     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 +

mercurial