Reviewers: Jakob,

Description:
Version 4.4.63.7 (cherry-pick)

Merged 4cc4bc591cc8ffe7d458f4e89e1fbe3944d44c9f

Map::TryUpdate() must be in sync with Map::Update().

BUG=v8:4173
LOG=N
[email protected]

Please review this at https://codereview.chromium.org/1186883005/

Base URL: https://chromium.googlesource.com/v8/[email protected]

Affected files (+82, -9 lines):
  M include/v8-version.h
  M src/objects.cc
  M test/cctest/test-migrations.cc
  A test/mjsunit/regress/regress-4121.js


Index: include/v8-version.h
diff --git a/include/v8-version.h b/include/v8-version.h
index c99cc781dba5cd3eb24136847859948a35963bcd..6bfa9c931f7e9ff1945ad78418633efdbfca0a12 100644
--- a/include/v8-version.h
+++ b/include/v8-version.h
@@ -11,7 +11,7 @@
 #define V8_MAJOR_VERSION 4
 #define V8_MINOR_VERSION 4
 #define V8_BUILD_NUMBER 63
-#define V8_PATCH_LEVEL 6
+#define V8_PATCH_LEVEL 7

 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 03e6994a42b87b5e5abefd722decd437889f3cc7..67e32a63ac4bb1db49d6702eac5a2b793ab67575 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2571,7 +2571,7 @@ Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,

   ElementsKind from_kind = root_map->elements_kind();
   ElementsKind to_kind = old_map->elements_kind();
-  if (from_kind != to_kind &&
+  if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
       !(IsTransitionableFastElementsKind(from_kind) &&
         IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, @@ -3035,6 +3035,15 @@ MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
   // Check the state of the root map.
   Map* root_map = old_map->FindRootMap();
if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
+
+  ElementsKind from_kind = root_map->elements_kind();
+  ElementsKind to_kind = old_map->elements_kind();
+  if (from_kind != to_kind) {
+    // Try to follow existing elements kind transitions.
+    root_map = root_map->LookupElementsTransitionMap(to_kind);
+    if (root_map == NULL) return MaybeHandle<Map>();
+    // From here on, use the map with correct elements kind as root map.
+  }
   int root_nof = root_map->NumberOfOwnDescriptors();

   int old_nof = old_map->NumberOfOwnDescriptors();
Index: test/cctest/test-migrations.cc
diff --git a/test/cctest/test-migrations.cc b/test/cctest/test-migrations.cc
index 544278575ce1e189bbe00a71abbf60e28f5d6328..340e81d27ea521d2578640eda1faf308d684a6b6 100644
--- a/test/cctest/test-migrations.cc
+++ b/test/cctest/test-migrations.cc
@@ -20,11 +20,6 @@
 using namespace v8::internal;


-// TODO(ishell): fix this once ReconfigureProperty supports "non equivalent"
-// transitions.
-const bool IS_NON_EQUIVALENT_TRANSITION_SUPPORTED = false;
-
-
 // TODO(ishell): fix this once TransitionToPrototype stops generalizing
 // all field representations (similar to crbug/448711 where elements kind
// and observed transitions caused generalization of all field representations). @@ -1592,7 +1587,14 @@ static void TestGeneralizeRepresentationWithSpecialTransition(
     CHECK(!new_map2->is_deprecated());
     CHECK(!new_map2->is_dictionary_map());

-    if (!IS_NON_EQUIVALENT_TRANSITION_SUPPORTED) {
+    Handle<Map> tmp_map;
+    if (Map::TryUpdate(map2).ToHandle(&tmp_map)) {
+ // If Map::TryUpdate() manages to succeed the result must match the result
+      // of Map::Update().
+      CHECK_EQ(*new_map2, *tmp_map);
+    }
+
+    if (config.is_non_equevalent_transition()) {
       // In case of non-equivalent transition currently we generalize all
       // representations.
       for (int i = 0; i < kPropCount; i++) {
@@ -1601,7 +1603,8 @@ static void TestGeneralizeRepresentationWithSpecialTransition(
       CHECK(new_map2->GetBackPointer()->IsUndefined());
       CHECK(expectations2.Check(*new_map2));
     } else {
-      CHECK(expectations.Check(*new_map2));
+      CHECK(!new_map2->GetBackPointer()->IsUndefined());
+      CHECK(expectations2.Check(*new_map2));
     }
   }

@@ -1633,6 +1636,7 @@ TEST(ElementsKindTransitionFromMapOwningDescriptor) {
     }
     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
     bool generalizes_representations() const { return false; }
+    bool is_non_equevalent_transition() const { return false; }
   };
   TestConfig config;
   TestGeneralizeRepresentationWithSpecialTransition(
@@ -1667,6 +1671,7 @@ TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
     }
     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
     bool generalizes_representations() const { return false; }
+    bool is_non_equevalent_transition() const { return false; }
   };
   TestConfig config;
   TestGeneralizeRepresentationWithSpecialTransition(
@@ -1689,6 +1694,7 @@ TEST(ForObservedTransitionFromMapOwningDescriptor) {
     }
     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
     bool generalizes_representations() const { return false; }
+    bool is_non_equevalent_transition() const { return true; }
   };
   TestConfig config;
   TestGeneralizeRepresentationWithSpecialTransition(
@@ -1722,6 +1728,7 @@ TEST(ForObservedTransitionFromMapNotOwningDescriptor) {
     }
     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
     bool generalizes_representations() const { return false; }
+    bool is_non_equevalent_transition() const { return true; }
   };
   TestConfig config;
   TestGeneralizeRepresentationWithSpecialTransition(
@@ -1755,6 +1762,7 @@ TEST(PrototypeTransitionFromMapOwningDescriptor) {
     bool generalizes_representations() const {
       return !IS_PROTO_TRANS_ISSUE_FIXED;
     }
+    bool is_non_equevalent_transition() const { return true; }
   };
   TestConfig config;
   TestGeneralizeRepresentationWithSpecialTransition(
@@ -1799,6 +1807,7 @@ TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
     bool generalizes_representations() const {
       return !IS_PROTO_TRANS_ISSUE_FIXED;
     }
+    bool is_non_equevalent_transition() const { return true; }
   };
   TestConfig config;
   TestGeneralizeRepresentationWithSpecialTransition(
Index: test/mjsunit/regress/regress-4121.js
diff --git a/test/mjsunit/regress/regress-4121.js b/test/mjsunit/regress/regress-4121.js
new file mode 100644
index 0000000000000000000000000000000000000000..3d777c26b355054d71cd0f0efea6a5e203af4b8a
--- /dev/null
+++ b/test/mjsunit/regress/regress-4121.js
@@ -0,0 +1,55 @@
+// 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
+
+function Migrator(o) {
+  return o.foo;
+}
+function Loader(o) {
+  return o[0];
+}
+
+var first_smi_array = [1];
+var second_smi_array = [2];
+var first_object_array = ["first"];
+var second_object_array = ["string"];
+
+assertTrue(%HasFastSmiElements(first_smi_array));
+assertTrue(%HasFastSmiElements(second_smi_array));
+assertTrue(%HasFastObjectElements(first_object_array));
+assertTrue(%HasFastObjectElements(second_object_array));
+
+// Prepare identical transition chains for smi and object arrays.
+first_smi_array.foo = 0;
+second_smi_array.foo = 0;
+first_object_array.foo = 0;
+second_object_array.foo = 0;
+
+// Collect type feedback for not-yet-deprecated original object array map.
+for (var i = 0; i < 3; i++) Migrator(second_object_array);
+
+// Blaze a migration trail for smi array maps.
+// This marks the migrated smi array map as a migration target.
+first_smi_array.foo = 0.5;
+print(second_smi_array.foo);
+
+// Deprecate original object array map.
+// Use TryMigrate from deferred optimized code to migrate second object array.
+first_object_array.foo = 0.5;
+%OptimizeFunctionOnNextCall(Migrator);
+Migrator(second_object_array);
+
+// |second_object_array| now erroneously has a smi map.
+// Optimized code assuming smi elements will expose this.
+
+for (var i = 0; i < 3; i++) Loader(second_smi_array);
+%OptimizeFunctionOnNextCall(Loader);
+assertEquals("string", Loader(second_object_array));
+
+// Any of the following checks will also fail:
+assertTrue(%HasFastObjectElements(second_object_array));
+assertFalse(%HasFastSmiElements(second_object_array));
+assertTrue(%HaveSameMap(first_object_array, second_object_array));
+assertFalse(%HaveSameMap(first_smi_array, second_object_array));


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to