Map::ReconfigureProperty() should mark map as unstable when there is an element kind...
authorishell <ishell@chromium.org>
Fri, 15 May 2015 10:40:04 +0000 (03:40 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 15 May 2015 10:39:51 +0000 (10:39 +0000)
BUG=chromium:485548
LOG=N

Review URL: https://codereview.chromium.org/1128043005

Cr-Commit-Position: refs/heads/master@{#28418}

src/objects.cc
test/mjsunit/regress/regress-crbug-485548-1.js [new file with mode: 0644]
test/mjsunit/regress/regress-crbug-485548-2.js [new file with mode: 0644]

index 6dc5de2..5bd67af 100644 (file)
@@ -1419,7 +1419,8 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
   }
   switch (map()->instance_type()) {
     case MAP_TYPE:
-      os << "<Map(elements=" << Map::cast(this)->elements_kind() << ")>";
+      os << "<Map(" << ElementsKindToString(Map::cast(this)->elements_kind())
+         << ")>";
       break;
     case FIXED_ARRAY_TYPE:
       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
@@ -2971,6 +2972,13 @@ Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
       split_kind, old_descriptors->GetKey(split_nof), split_attributes,
       *new_descriptors, *new_layout_descriptor);
 
+  if (from_kind != to_kind) {
+    // There was an elements kind change in the middle of transition tree and
+    // we reconstructed the tree so that all elements kind transitions are
+    // done at the beginning, therefore the |old_map| is no longer stable.
+    old_map->NotifyLeafMapLayoutChange();
+  }
+
   // If |transition_target_deprecated| is true then the transition array
   // already contains entry for given descriptor. This means that the transition
   // could be inserted regardless of whether transitions array is full or not.
diff --git a/test/mjsunit/regress/regress-crbug-485548-1.js b/test/mjsunit/regress/regress-crbug-485548-1.js
new file mode 100644 (file)
index 0000000..bbd0f7d
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --expose-gc
+
+var inner = new Array();
+inner.a = {x:1};
+inner[0] = 1.5;
+inner.b = {x:2};
+assertTrue(%HasFastDoubleElements(inner));
+
+function foo(o) {
+  return o.field.a.x;
+}
+
+var outer = {};
+outer.field = inner;
+foo(outer);
+foo(outer);
+foo(outer);
+%OptimizeFunctionOnNextCall(foo);
+foo(outer);
+
+// Generalize representation of field "a" of inner object.
+var v = { get x() { return 0x7fffffff; } };
+inner.a = v;
+
+gc();
+
+var boom = foo(outer);
+print(boom);
+assertEquals(0x7fffffff, boom);
diff --git a/test/mjsunit/regress/regress-crbug-485548-2.js b/test/mjsunit/regress/regress-crbug-485548-2.js
new file mode 100644 (file)
index 0000000..7e449a6
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --expose-gc
+
+var inner = new Array();
+inner.a = {x:1};
+inner[0] = 1.5;
+inner.b = {x:2};
+assertTrue(%HasFastDoubleElements(inner));
+
+function foo(o) {
+  return o.field.b.x;
+}
+
+var outer = {};
+outer.field = inner;
+foo(outer);
+foo(outer);
+foo(outer);
+%OptimizeFunctionOnNextCall(foo);
+foo(outer);
+
+// Generalize representation of field "b" of inner object.
+var v = { get x() { return 0x7fffffff; } };
+inner.b = v;
+
+gc();
+
+var boom = foo(outer);
+print(boom);
+assertEquals(0x7fffffff, boom);