LCOV - code coverage report
Current view: top level - test/cctest - test-field-type-tracking.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1079 1106 97.6 %
Date: 2019-03-21 Functions: 103 104 99.0 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include <stdlib.h>
       6             : #include <utility>
       7             : 
       8             : #include "test/cctest/test-api.h"
       9             : 
      10             : #include "src/v8.h"
      11             : 
      12             : #include "src/compilation-cache.h"
      13             : #include "src/compiler/compilation-dependencies.h"
      14             : #include "src/compiler/js-heap-broker.h"
      15             : #include "src/execution.h"
      16             : #include "src/field-type.h"
      17             : #include "src/global-handles.h"
      18             : #include "src/heap/factory.h"
      19             : #include "src/ic/stub-cache.h"
      20             : #include "src/macro-assembler.h"
      21             : #include "src/objects-inl.h"
      22             : #include "src/objects/heap-number-inl.h"
      23             : #include "src/objects/struct-inl.h"
      24             : #include "src/optimized-compilation-info.h"
      25             : #include "src/ostreams.h"
      26             : #include "src/property.h"
      27             : #include "src/transitions.h"
      28             : 
      29             : namespace v8 {
      30             : namespace internal {
      31             : namespace compiler {
      32             : namespace test_field_type_tracking {
      33             : 
      34             : // TODO(ishell): fix this once TransitionToPrototype stops generalizing
      35             : // all field representations (similar to crbug/448711 where elements kind
      36             : // and observed transitions caused generalization of all fields).
      37             : const bool IS_PROTO_TRANS_ISSUE_FIXED = false;
      38             : 
      39             : 
      40             : // TODO(ishell): fix this once TransitionToAccessorProperty is able to always
      41             : // keep map in fast mode.
      42             : const bool IS_ACCESSOR_FIELD_SUPPORTED = false;
      43             : 
      44             : 
      45             : // Number of properties used in the tests.
      46             : const int kPropCount = 7;
      47             : 
      48             : 
      49             : //
      50             : // Helper functions.
      51             : //
      52             : 
      53             : static Handle<String> MakeString(const char* str) {
      54             :   Isolate* isolate = CcTest::i_isolate();
      55             :   Factory* factory = isolate->factory();
      56       10772 :   return factory->InternalizeUtf8String(str);
      57             : }
      58             : 
      59             : 
      60       10756 : static Handle<String> MakeName(const char* str, int suffix) {
      61             :   EmbeddedVector<char, 128> buffer;
      62       10756 :   SNPrintF(buffer, "%s%d", str, suffix);
      63       10756 :   return MakeString(buffer.start());
      64             : }
      65             : 
      66             : 
      67          32 : static Handle<AccessorPair> CreateAccessorPair(bool with_getter,
      68             :                                                bool with_setter) {
      69             :   Isolate* isolate = CcTest::i_isolate();
      70             :   Factory* factory = isolate->factory();
      71          32 :   Handle<AccessorPair> pair = factory->NewAccessorPair();
      72          32 :   Handle<String> empty_string = factory->empty_string();
      73          32 :   if (with_getter) {
      74          32 :     Handle<JSFunction> func = factory->NewFunctionForTest(empty_string);
      75          64 :     pair->set_getter(*func);
      76             :   }
      77          32 :   if (with_setter) {
      78          32 :     Handle<JSFunction> func = factory->NewFunctionForTest(empty_string);
      79          64 :     pair->set_setter(*func);
      80             :   }
      81          32 :   return pair;
      82             : }
      83             : 
      84             : // Check cached migration target map after Map::Update() and Map::TryUpdate()
      85         604 : static void CheckMigrationTarget(Isolate* isolate, Map old_map, Map new_map) {
      86             :   Map target = TransitionsAccessor(isolate, handle(old_map, isolate))
      87         604 :                    .GetMigrationTarget();
      88        1208 :   if (target.is_null()) return;
      89           0 :   CHECK_EQ(new_map, target);
      90           0 :   CHECK_EQ(Map::TryUpdateSlow(isolate, old_map), target);
      91             : }
      92             : 
      93             : class Expectations {
      94             :   static const int MAX_PROPERTIES = 10;
      95             :   Isolate* isolate_;
      96             :   ElementsKind elements_kind_;
      97             :   PropertyKind kinds_[MAX_PROPERTIES];
      98             :   PropertyLocation locations_[MAX_PROPERTIES];
      99             :   PropertyConstness constnesses_[MAX_PROPERTIES];
     100             :   PropertyAttributes attributes_[MAX_PROPERTIES];
     101             :   Representation representations_[MAX_PROPERTIES];
     102             :   // FieldType for kField, value for DATA_CONSTANT and getter for
     103             :   // ACCESSOR_CONSTANT.
     104             :   Handle<Object> values_[MAX_PROPERTIES];
     105             :   // Setter for ACCESSOR_CONSTANT.
     106             :   Handle<Object> setter_values_[MAX_PROPERTIES];
     107             :   int number_of_properties_;
     108             : 
     109             :  public:
     110             :   explicit Expectations(Isolate* isolate, ElementsKind elements_kind)
     111             :       : isolate_(isolate),
     112             :         elements_kind_(elements_kind),
     113       19840 :         number_of_properties_(0) {}
     114             : 
     115         448 :   explicit Expectations(Isolate* isolate)
     116             :       : Expectations(
     117             :             isolate,
     118         896 :             isolate->object_function()->initial_map()->elements_kind()) {}
     119             : 
     120        5740 :   void Init(int index, PropertyKind kind, PropertyAttributes attributes,
     121             :             PropertyConstness constness, PropertyLocation location,
     122             :             Representation representation, Handle<Object> value) {
     123        5740 :     CHECK(index < MAX_PROPERTIES);
     124        5740 :     kinds_[index] = kind;
     125        5740 :     locations_[index] = location;
     126       11436 :     if (kind == kData && location == kField &&
     127        5696 :         IsTransitionableFastElementsKind(elements_kind_)) {
     128             :       // Maps with transitionable elements kinds must have the most general
     129             :       // field type.
     130        1440 :       value = FieldType::Any(isolate_);
     131             :     }
     132        5740 :     constnesses_[index] = constness;
     133        5740 :     attributes_[index] = attributes;
     134        5740 :     representations_[index] = representation;
     135        5740 :     values_[index] = value;
     136        5740 :   }
     137             : 
     138           0 :   void Print() const {
     139           0 :     StdoutStream os;
     140           0 :     os << "Expectations: #" << number_of_properties_ << "\n";
     141           0 :     for (int i = 0; i < number_of_properties_; i++) {
     142           0 :       os << " " << i << ": ";
     143           0 :       os << "Descriptor @ ";
     144             : 
     145           0 :       if (kinds_[i] == kData) {
     146           0 :         os << Brief(*values_[i]);
     147             :       } else {
     148             :         // kAccessor
     149           0 :         os << "(get: " << Brief(*values_[i])
     150           0 :            << ", set: " << Brief(*setter_values_[i]) << ") ";
     151             :       }
     152             : 
     153           0 :       os << " (";
     154           0 :       if (constnesses_[i] == PropertyConstness::kConst) os << "const ";
     155           0 :       os << (kinds_[i] == kData ? "data " : "accessor ");
     156           0 :       if (locations_[i] == kField) {
     157             :         os << "field"
     158           0 :            << ": " << representations_[i].Mnemonic();
     159             :       } else {
     160           0 :         os << "descriptor";
     161             :       }
     162           0 :       os << ", attrs: " << attributes_[i] << ")\n";
     163             :     }
     164           0 :     os << "\n";
     165           0 :   }
     166             : 
     167             :   void SetElementsKind(ElementsKind elements_kind) {
     168          24 :     elements_kind_ = elements_kind;
     169             :   }
     170             : 
     171             :   Handle<FieldType> GetFieldType(int index) {
     172             :     CHECK(index < MAX_PROPERTIES);
     173             :     CHECK_EQ(kField, locations_[index]);
     174             :     return Handle<FieldType>::cast(values_[index]);
     175             :   }
     176             : 
     177             :   void SetDataField(int index, PropertyAttributes attrs,
     178             :                     PropertyConstness constness, Representation representation,
     179             :                     Handle<FieldType> field_type) {
     180        5656 :     Init(index, kData, attrs, constness, kField, representation, field_type);
     181             :   }
     182             : 
     183             :   void SetDataField(int index, PropertyConstness constness,
     184             :                     Representation representation,
     185             :                     Handle<FieldType> field_type) {
     186        1124 :     SetDataField(index, attributes_[index], constness, representation,
     187             :                  field_type);
     188             :   }
     189             : 
     190             :   void SetAccessorField(int index, PropertyAttributes attrs) {
     191             :     Init(index, kAccessor, attrs, PropertyConstness::kConst, kDescriptor,
     192             :          Representation::Tagged(), FieldType::Any(isolate_));
     193             :   }
     194             : 
     195             :   void SetAccessorField(int index) {
     196             :     SetAccessorField(index, attributes_[index]);
     197             :   }
     198             : 
     199          40 :   void SetDataConstant(int index, PropertyAttributes attrs,
     200             :                        Handle<JSFunction> value) {
     201             :     if (FLAG_track_constant_fields) {
     202          80 :       Handle<FieldType> field_type(FieldType::Class(value->map()), isolate_);
     203          40 :       Init(index, kData, attrs, PropertyConstness::kConst, kField,
     204          40 :            Representation::HeapObject(), field_type);
     205             : 
     206             :     } else {
     207             :       Init(index, kData, attrs, PropertyConstness::kConst, kDescriptor,
     208             :            Representation::HeapObject(), value);
     209             :     }
     210          40 :   }
     211             : 
     212             :   void SetDataConstant(int index, Handle<JSFunction> value) {
     213             :     SetDataConstant(index, attributes_[index], value);
     214             :   }
     215             : 
     216             :   void SetAccessorConstant(int index, PropertyAttributes attrs,
     217             :                            Handle<Object> getter, Handle<Object> setter) {
     218             :     Init(index, kAccessor, attrs, PropertyConstness::kConst, kDescriptor,
     219          44 :          Representation::Tagged(), getter);
     220          44 :     setter_values_[index] = setter;
     221             :   }
     222             : 
     223             :   void SetAccessorConstantComponent(int index, PropertyAttributes attrs,
     224             :                                     AccessorComponent component,
     225             :                                     Handle<Object> accessor) {
     226             :     CHECK_EQ(kAccessor, kinds_[index]);
     227             :     CHECK_EQ(kDescriptor, locations_[index]);
     228             :     CHECK(index < number_of_properties_);
     229             :     if (component == ACCESSOR_GETTER) {
     230             :       values_[index] = accessor;
     231             :     } else {
     232             :       setter_values_[index] = accessor;
     233             :     }
     234             :   }
     235             : 
     236          40 :   void SetAccessorConstant(int index, PropertyAttributes attrs,
     237             :                            Handle<AccessorPair> pair) {
     238          40 :     Handle<Object> getter = handle(pair->getter(), isolate_);
     239          40 :     Handle<Object> setter = handle(pair->setter(), isolate_);
     240             :     SetAccessorConstant(index, attrs, getter, setter);
     241          40 :   }
     242             : 
     243           4 :   void SetAccessorConstant(int index, Handle<Object> getter,
     244             :                            Handle<Object> setter) {
     245           4 :     SetAccessorConstant(index, attributes_[index], getter, setter);
     246           4 :   }
     247             : 
     248           4 :   void SetAccessorConstant(int index, Handle<AccessorPair> pair) {
     249           8 :     Handle<Object> getter = handle(pair->getter(), isolate_);
     250           8 :     Handle<Object> setter = handle(pair->setter(), isolate_);
     251           4 :     SetAccessorConstant(index, getter, setter);
     252           4 :   }
     253             : 
     254         476 :   void GeneralizeField(int index) {
     255         476 :     CHECK(index < number_of_properties_);
     256         476 :     representations_[index] = Representation::Tagged();
     257         476 :     if (locations_[index] == kField) {
     258         472 :       values_[index] = FieldType::Any(isolate_);
     259             :     }
     260         476 :   }
     261             : 
     262       13116 :   bool Check(DescriptorArray descriptors, int descriptor) const {
     263       13116 :     PropertyDetails details = descriptors->GetDetails(descriptor);
     264             : 
     265       13116 :     if (details.kind() != kinds_[descriptor]) return false;
     266       13116 :     if (details.location() != locations_[descriptor]) return false;
     267       13116 :     if (details.constness() != constnesses_[descriptor]) return false;
     268             : 
     269       13116 :     PropertyAttributes expected_attributes = attributes_[descriptor];
     270       13116 :     if (details.attributes() != expected_attributes) return false;
     271             : 
     272       13116 :     Representation expected_representation = representations_[descriptor];
     273             : 
     274       13116 :     if (!details.representation().Equals(expected_representation)) return false;
     275             : 
     276       13116 :     Object expected_value = *values_[descriptor];
     277       13116 :     if (details.location() == kField) {
     278       13024 :       if (details.kind() == kData) {
     279             :         FieldType type = descriptors->GetFieldType(descriptor);
     280       26048 :         return FieldType::cast(expected_value) == type;
     281             :       } else {
     282             :         // kAccessor
     283           0 :         UNREACHABLE();
     284             :       }
     285             :     } else {
     286          92 :       Object value = descriptors->GetStrongValue(descriptor);
     287             :       // kDescriptor
     288          92 :       if (details.kind() == kData) {
     289           0 :         CHECK(!FLAG_track_constant_fields);
     290             :         return value == expected_value;
     291             :       } else {
     292             :         // kAccessor
     293          92 :         if (value == expected_value) return true;
     294          92 :         if (!value->IsAccessorPair()) return false;
     295          92 :         AccessorPair pair = AccessorPair::cast(value);
     296         184 :         return pair->Equals(expected_value, *setter_values_[descriptor]);
     297             :       }
     298             :     }
     299             :     UNREACHABLE();
     300             :   }
     301             : 
     302        1932 :   bool Check(Map map, int expected_nof) const {
     303        1932 :     CHECK_EQ(elements_kind_, map->elements_kind());
     304        1932 :     CHECK(number_of_properties_ <= MAX_PROPERTIES);
     305        1932 :     CHECK_EQ(expected_nof, map->NumberOfOwnDescriptors());
     306        1932 :     CHECK(!map->is_dictionary_map());
     307             : 
     308        1932 :     DescriptorArray descriptors = map->instance_descriptors();
     309        1932 :     CHECK(expected_nof <= number_of_properties_);
     310       28164 :     for (int i = 0; i < expected_nof; i++) {
     311       13116 :       if (!Check(descriptors, i)) {
     312           0 :         Print();
     313             : #ifdef OBJECT_PRINT
     314             :         descriptors->Print();
     315             : #endif
     316           0 :         Check(descriptors, i);
     317           0 :         return false;
     318             :       }
     319             :     }
     320             :     return true;
     321             :   }
     322             : 
     323        1876 :   bool Check(Map map) const { return Check(map, number_of_properties_); }
     324             : 
     325             :   //
     326             :   // Helper methods for initializing expectations and adding properties to
     327             :   // given |map|.
     328             :   //
     329             : 
     330          96 :   Handle<Map> AsElementsKind(Handle<Map> map, ElementsKind elements_kind) {
     331          96 :     elements_kind_ = elements_kind;
     332          96 :     map = Map::AsElementsKind(isolate_, map, elements_kind);
     333          96 :     CHECK_EQ(elements_kind_, map->elements_kind());
     334          96 :     return map;
     335             :   }
     336             : 
     337             :   void ChangeAttributesForAllProperties(PropertyAttributes attributes) {
     338         360 :     for (int i = 0; i < number_of_properties_; i++) {
     339         168 :       attributes_[i] = attributes;
     340             :     }
     341             :   }
     342             : 
     343        4252 :   Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
     344             :                            PropertyConstness constness,
     345             :                            Representation representation,
     346             :                            Handle<FieldType> field_type) {
     347        4252 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     348        4252 :     int property_index = number_of_properties_++;
     349             :     SetDataField(property_index, attributes, constness, representation,
     350             :                  field_type);
     351             : 
     352        4252 :     Handle<String> name = MakeName("prop", property_index);
     353        8504 :     return Map::CopyWithField(isolate_, map, name, field_type, attributes,
     354        8504 :                               constness, representation, INSERT_TRANSITION)
     355        4252 :         .ToHandleChecked();
     356             :   }
     357             : 
     358          20 :   Handle<Map> AddDataConstant(Handle<Map> map, PropertyAttributes attributes,
     359             :                               Handle<JSFunction> value) {
     360          20 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     361          20 :     int property_index = number_of_properties_++;
     362          20 :     SetDataConstant(property_index, attributes, value);
     363             : 
     364          20 :     Handle<String> name = MakeName("prop", property_index);
     365          40 :     return Map::CopyWithConstant(isolate_, map, name, value, attributes,
     366          40 :                                  INSERT_TRANSITION)
     367          20 :         .ToHandleChecked();
     368             :   }
     369             : 
     370          12 :   Handle<Map> TransitionToDataField(Handle<Map> map,
     371             :                                     PropertyAttributes attributes,
     372             :                                     PropertyConstness constness,
     373             :                                     Representation representation,
     374             :                                     Handle<FieldType> heap_type,
     375             :                                     Handle<Object> value) {
     376          12 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     377          12 :     int property_index = number_of_properties_++;
     378             :     SetDataField(property_index, attributes, constness, representation,
     379             :                  heap_type);
     380             : 
     381          12 :     Handle<String> name = MakeName("prop", property_index);
     382             :     return Map::TransitionToDataProperty(isolate_, map, name, value, attributes,
     383          12 :                                          constness, StoreOrigin::kNamed);
     384             :   }
     385             : 
     386          20 :   Handle<Map> TransitionToDataConstant(Handle<Map> map,
     387             :                                        PropertyAttributes attributes,
     388             :                                        Handle<JSFunction> value) {
     389          20 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     390          20 :     int property_index = number_of_properties_++;
     391          20 :     SetDataConstant(property_index, attributes, value);
     392             : 
     393          20 :     Handle<String> name = MakeName("prop", property_index);
     394             :     return Map::TransitionToDataProperty(isolate_, map, name, value, attributes,
     395             :                                          PropertyConstness::kConst,
     396          20 :                                          StoreOrigin::kNamed);
     397             :   }
     398             : 
     399         252 :   Handle<Map> FollowDataTransition(Handle<Map> map,
     400             :                                    PropertyAttributes attributes,
     401             :                                    PropertyConstness constness,
     402             :                                    Representation representation,
     403             :                                    Handle<FieldType> heap_type) {
     404         252 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     405         252 :     int property_index = number_of_properties_++;
     406             :     SetDataField(property_index, attributes, constness, representation,
     407             :                  heap_type);
     408             : 
     409         252 :     Handle<String> name = MakeName("prop", property_index);
     410             :     Map target = TransitionsAccessor(isolate_, map)
     411         504 :                      .SearchTransition(*name, kData, attributes);
     412         252 :     CHECK(!target.is_null());
     413         504 :     return handle(target, isolate_);
     414             :   }
     415             : 
     416          32 :   Handle<Map> AddAccessorConstant(Handle<Map> map,
     417             :                                   PropertyAttributes attributes,
     418             :                                   Handle<AccessorPair> pair) {
     419          32 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     420          32 :     int property_index = number_of_properties_++;
     421          32 :     SetAccessorConstant(property_index, attributes, pair);
     422             : 
     423          32 :     Handle<String> name = MakeName("prop", property_index);
     424             : 
     425          32 :     Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
     426          32 :     return Map::CopyInsertDescriptor(isolate_, map, &d, INSERT_TRANSITION);
     427             :   }
     428             : 
     429             :   Handle<Map> AddAccessorConstant(Handle<Map> map,
     430             :                                   PropertyAttributes attributes,
     431             :                                   Handle<Object> getter,
     432             :                                   Handle<Object> setter) {
     433             :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     434             :     int property_index = number_of_properties_++;
     435             :     SetAccessorConstant(property_index, attributes, getter, setter);
     436             : 
     437             :     Handle<String> name = MakeName("prop", property_index);
     438             : 
     439             :     CHECK(!getter->IsNull(isolate_) || !setter->IsNull(isolate_));
     440             :     Factory* factory = isolate_->factory();
     441             : 
     442             :     if (!getter->IsNull(isolate_)) {
     443             :       Handle<AccessorPair> pair = factory->NewAccessorPair();
     444             :       pair->SetComponents(*getter, *factory->null_value());
     445             :       Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
     446             :       map = Map::CopyInsertDescriptor(isolate_, map, &d, INSERT_TRANSITION);
     447             :     }
     448             :     if (!setter->IsNull(isolate_)) {
     449             :       Handle<AccessorPair> pair = factory->NewAccessorPair();
     450             :       pair->SetComponents(*getter, *setter);
     451             :       Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
     452             :       map = Map::CopyInsertDescriptor(isolate_, map, &d, INSERT_TRANSITION);
     453             :     }
     454             :     return map;
     455             :   }
     456             : 
     457           8 :   Handle<Map> TransitionToAccessorConstant(Handle<Map> map,
     458             :                                            PropertyAttributes attributes,
     459             :                                            Handle<AccessorPair> pair) {
     460           8 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     461           8 :     int property_index = number_of_properties_++;
     462           8 :     SetAccessorConstant(property_index, attributes, pair);
     463             : 
     464           8 :     Handle<String> name = MakeName("prop", property_index);
     465             : 
     466             :     Isolate* isolate = CcTest::i_isolate();
     467             :     Handle<Object> getter(pair->getter(), isolate);
     468             :     Handle<Object> setter(pair->setter(), isolate);
     469             : 
     470             :     int descriptor =
     471          16 :         map->instance_descriptors()->SearchWithCache(isolate, *name, *map);
     472             :     map = Map::TransitionToAccessorProperty(isolate, map, name, descriptor,
     473           8 :                                             getter, setter, attributes);
     474           8 :     CHECK(!map->is_deprecated());
     475           8 :     CHECK(!map->is_dictionary_map());
     476           8 :     return map;
     477             :   }
     478             : };
     479             : 
     480             : 
     481             : ////////////////////////////////////////////////////////////////////////////////
     482             : // A set of tests for property reconfiguration that makes new transition tree
     483             : // branch.
     484             : //
     485             : 
     486       26067 : TEST(ReconfigureAccessorToNonExistingDataField) {
     487           4 :   CcTest::InitializeVM();
     488           8 :   v8::HandleScope scope(CcTest::isolate());
     489             :   Isolate* isolate = CcTest::i_isolate();
     490             : 
     491           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     492           4 :   Handle<FieldType> none_type = FieldType::None(isolate);
     493           4 :   Handle<AccessorPair> pair = CreateAccessorPair(true, true);
     494             : 
     495           4 :   Expectations expectations(isolate);
     496             : 
     497             :   // Create a map, add required properties to it and initialize expectations.
     498           4 :   Handle<Map> initial_map = Map::Create(isolate, 0);
     499           4 :   Handle<Map> map = initial_map;
     500           4 :   map = expectations.AddAccessorConstant(map, NONE, pair);
     501             : 
     502           4 :   CHECK(!map->is_deprecated());
     503           4 :   CHECK(map->is_stable());
     504           4 :   CHECK(expectations.Check(*map));
     505             : 
     506             :   Handle<Map> new_map = Map::ReconfigureProperty(
     507           4 :       isolate, map, 0, kData, NONE, Representation::None(), none_type);
     508             :   // |map| did not change except marked unstable.
     509           4 :   CHECK(!map->is_deprecated());
     510           4 :   CHECK(!map->is_stable());
     511           4 :   CHECK(expectations.Check(*map));
     512             : 
     513             :   // Property kind reconfiguration always makes the field mutable.
     514             :   expectations.SetDataField(0, NONE, PropertyConstness::kMutable,
     515             :                             Representation::None(), none_type);
     516             : 
     517           4 :   CHECK(!new_map->is_deprecated());
     518           4 :   CHECK(new_map->is_stable());
     519           4 :   CHECK(expectations.Check(*new_map));
     520             : 
     521             :   Handle<Map> new_map2 = Map::ReconfigureProperty(
     522           4 :       isolate, map, 0, kData, NONE, Representation::None(), none_type);
     523           4 :   CHECK_EQ(*new_map, *new_map2);
     524             : 
     525             :   Handle<Object> value(Smi::kZero, isolate);
     526             :   Handle<Map> prepared_map = Map::PrepareForDataProperty(
     527           4 :       isolate, new_map, 0, PropertyConstness::kConst, value);
     528             :   // None to Smi generalization is trivial, map does not change.
     529           4 :   CHECK_EQ(*new_map, *prepared_map);
     530             : 
     531             :   expectations.SetDataField(0, NONE, PropertyConstness::kMutable,
     532             :                             Representation::Smi(), any_type);
     533           4 :   CHECK(prepared_map->is_stable());
     534           4 :   CHECK(expectations.Check(*prepared_map));
     535             : 
     536             :   // Now create an object with |map|, migrate it to |prepared_map| and ensure
     537             :   // that the data property is uninitialized.
     538             :   Factory* factory = isolate->factory();
     539           4 :   Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
     540           4 :   JSObject::MigrateToMap(obj, prepared_map);
     541           4 :   FieldIndex index = FieldIndex::ForDescriptor(*prepared_map, 0);
     542           8 :   CHECK(obj->RawFastPropertyAt(index)->IsUninitialized(isolate));
     543             : #ifdef VERIFY_HEAP
     544             :   obj->ObjectVerify(isolate);
     545             : #endif
     546           4 : }
     547             : 
     548             : 
     549             : // This test checks that the LookupIterator machinery involved in
     550             : // JSObject::SetOwnPropertyIgnoreAttributes() does not try to migrate object
     551             : // to a map with a property with None representation.
     552       26067 : TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) {
     553           4 :   CcTest::InitializeVM();
     554           8 :   v8::HandleScope scope(CcTest::isolate());
     555             :   Isolate* isolate = CcTest::i_isolate();
     556             :   Factory* factory = isolate->factory();
     557             : 
     558             :   CompileRun(
     559             :       "function getter() { return 1; };"
     560             :       "function setter() {};"
     561             :       "var o = {};"
     562             :       "Object.defineProperty(o, 'foo', "
     563             :       "                      { get: getter, set: setter, "
     564             :       "                        configurable: true, enumerable: true});");
     565             : 
     566           4 :   Handle<String> foo_str = factory->InternalizeUtf8String("foo");
     567           4 :   Handle<String> obj_name = factory->InternalizeUtf8String("o");
     568             : 
     569             :   Handle<Object> obj_value =
     570          12 :       Object::GetProperty(isolate, isolate->global_object(), obj_name)
     571             :           .ToHandleChecked();
     572           4 :   CHECK(obj_value->IsJSObject());
     573             :   Handle<JSObject> obj = Handle<JSObject>::cast(obj_value);
     574             : 
     575           4 :   CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
     576           4 :   CHECK(
     577             :       obj->map()->instance_descriptors()->GetStrongValue(0)->IsAccessorPair());
     578             : 
     579             :   Handle<Object> value(Smi::FromInt(42), isolate);
     580           8 :   JSObject::SetOwnPropertyIgnoreAttributes(obj, foo_str, value, NONE).Check();
     581             : 
     582             :   // Check that the property contains |value|.
     583           4 :   CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
     584           4 :   FieldIndex index = FieldIndex::ForDescriptor(obj->map(), 0);
     585           4 :   Object the_value = obj->RawFastPropertyAt(index);
     586           4 :   CHECK(the_value->IsSmi());
     587           4 :   CHECK_EQ(42, Smi::ToInt(the_value));
     588           4 : }
     589             : 
     590             : 
     591             : ////////////////////////////////////////////////////////////////////////////////
     592             : // A set of tests for field generalization case.
     593             : //
     594             : 
     595             : // <Constness, Representation, FieldType> data.
     596             : struct CRFTData {
     597             :   PropertyConstness constness;
     598             :   Representation representation;
     599             :   Handle<FieldType> type;
     600             : };
     601             : 
     602             : // This test ensures that field generalization at |property_index| is done
     603             : // correctly independently of the fact that the |map| is detached from
     604             : // transition tree or not.
     605             : //
     606             : //  {} - p0 - p1 - p2: |detach_point_map|
     607             : //                  |
     608             : //                  X - detached at |detach_property_at_index|
     609             : //                  |
     610             : //                  + - p3 - p4: |map|
     611             : //
     612             : // Detaching does not happen if |detach_property_at_index| is -1.
     613             : //
     614         192 : static void TestGeneralizeField(int detach_property_at_index,
     615             :                                 int property_index, const CRFTData& from,
     616             :                                 const CRFTData& to, const CRFTData& expected,
     617             :                                 bool expected_deprecation,
     618             :                                 bool expected_field_type_dependency) {
     619             :   Isolate* isolate = CcTest::i_isolate();
     620         192 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     621             : 
     622         192 :   CHECK(detach_property_at_index >= -1 &&
     623             :         detach_property_at_index < kPropCount);
     624         192 :   CHECK_LT(property_index, kPropCount);
     625         192 :   CHECK_NE(detach_property_at_index, property_index);
     626             : 
     627             :   const bool is_detached_map = detach_property_at_index >= 0;
     628             : 
     629         192 :   Expectations expectations(isolate);
     630             : 
     631             :   // Create a map, add required properties to it and initialize expectations.
     632         192 :   Handle<Map> initial_map = Map::Create(isolate, 0);
     633         192 :   Handle<Map> map = initial_map;
     634             :   Handle<Map> detach_point_map;
     635        2880 :   for (int i = 0; i < kPropCount; i++) {
     636        1344 :     if (i == property_index) {
     637         192 :       map = expectations.AddDataField(map, NONE, from.constness,
     638         192 :                                       from.representation, from.type);
     639             :     } else {
     640             :       map = expectations.AddDataField(map, NONE, kDefaultFieldConstness,
     641        1152 :                                       Representation::Smi(), any_type);
     642        1152 :       if (i == detach_property_at_index) {
     643             :         detach_point_map = map;
     644             :       }
     645             :     }
     646             :   }
     647         192 :   CHECK(!map->is_deprecated());
     648         192 :   CHECK(map->is_stable());
     649         192 :   CHECK(expectations.Check(*map));
     650             : 
     651         384 :   Zone zone(isolate->allocator(), ZONE_NAME);
     652             : 
     653         192 :   if (is_detached_map) {
     654             :     detach_point_map = Map::ReconfigureProperty(
     655             :         isolate, detach_point_map, detach_property_at_index, kData, NONE,
     656          48 :         Representation::Tagged(), any_type);
     657             :     expectations.SetDataField(detach_property_at_index, kDefaultFieldConstness,
     658             :                               Representation::Tagged(), any_type);
     659          48 :     CHECK(map->is_deprecated());
     660          48 :     CHECK(expectations.Check(*detach_point_map,
     661             :                              detach_point_map->NumberOfOwnDescriptors()));
     662             :   }
     663             : 
     664             :   // Create new maps by generalizing representation of propX field.
     665         384 :   CanonicalHandleScope canonical(isolate);
     666         384 :   JSHeapBroker broker(isolate, &zone);
     667         192 :   CompilationDependencies dependencies(&broker, &zone);
     668             :   MapRef map_ref(&broker, map);
     669         192 :   map_ref.SerializeOwnDescriptors();
     670         192 :   dependencies.DependOnFieldType(map_ref, property_index);
     671             : 
     672             :   Handle<Map> field_owner(map->FindFieldOwner(isolate, property_index),
     673         384 :                           isolate);
     674             :   Handle<Map> new_map = Map::ReconfigureProperty(
     675         192 :       isolate, map, property_index, kData, NONE, to.representation, to.type);
     676             : 
     677         192 :   expectations.SetDataField(property_index, expected.constness,
     678             :                             expected.representation, expected.type);
     679             : 
     680         192 :   CHECK(!new_map->is_deprecated());
     681         192 :   CHECK(expectations.Check(*new_map));
     682             : 
     683         192 :   if (is_detached_map) {
     684          48 :     CHECK(!map->is_stable());
     685          48 :     CHECK(map->is_deprecated());
     686          48 :     CHECK_NE(*map, *new_map);
     687          56 :     CHECK_EQ(expected_field_type_dependency && !field_owner->is_deprecated(),
     688             :              !dependencies.AreValid());
     689             : 
     690         144 :   } else if (expected_deprecation) {
     691          60 :     CHECK(!map->is_stable());
     692          60 :     CHECK(map->is_deprecated());
     693          60 :     CHECK(field_owner->is_deprecated());
     694          60 :     CHECK_NE(*map, *new_map);
     695          60 :     CHECK(dependencies.AreValid());
     696             : 
     697             :   } else {
     698          84 :     CHECK(!field_owner->is_deprecated());
     699          84 :     CHECK(map->is_stable());  // Map did not change, must be left stable.
     700          84 :     CHECK_EQ(*map, *new_map);
     701             : 
     702          84 :     CHECK_EQ(expected_field_type_dependency, !dependencies.AreValid());
     703             :   }
     704             : 
     705             :   {
     706             :     // Check that all previous maps are not stable.
     707         192 :     Map tmp = *new_map;
     708        1344 :     while (true) {
     709        1536 :       Object back = tmp->GetBackPointer();
     710        1536 :       if (back->IsUndefined(isolate)) break;
     711        1344 :       tmp = Map::cast(back);
     712        1344 :       CHECK(!tmp->is_stable());
     713             :     }
     714             :   }
     715             : 
     716             :   // Update all deprecated maps and check that they are now the same.
     717         192 :   Handle<Map> updated_map = Map::Update(isolate, map);
     718         192 :   CHECK_EQ(*new_map, *updated_map);
     719         192 :   CheckMigrationTarget(isolate, *map, *updated_map);
     720         192 : }
     721             : 
     722          40 : static void TestGeneralizeField(const CRFTData& from, const CRFTData& to,
     723             :                                 const CRFTData& expected,
     724             :                                 bool expected_deprecation,
     725             :                                 bool expected_field_type_dependency) {
     726             :   // Check the cases when the map being reconfigured is a part of the
     727             :   // transition tree.
     728             :   STATIC_ASSERT(kPropCount > 4);
     729          40 :   int indices[] = {0, 2, kPropCount - 1};
     730         280 :   for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
     731         120 :     TestGeneralizeField(-1, indices[i], from, to, expected,
     732         120 :                         expected_deprecation, expected_field_type_dependency);
     733             :   }
     734             : 
     735          40 :   if (!from.representation.IsNone()) {
     736             :     // Check the cases when the map being reconfigured is NOT a part of the
     737             :     // transition tree. "None -> anything" representation changes make sense
     738             :     // only for "attached" maps.
     739          24 :     int indices[] = {0, kPropCount - 1};
     740         120 :     for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
     741          48 :       TestGeneralizeField(indices[i], 2, from, to, expected,
     742          48 :                           expected_deprecation, expected_field_type_dependency);
     743             :     }
     744             : 
     745             :     // Check that reconfiguration to the very same field works correctly.
     746          24 :     CRFTData data = from;
     747          24 :     TestGeneralizeField(-1, 2, data, data, data, false, false);
     748             :   }
     749          40 : }
     750             : 
     751             : static void TestGeneralizeField(const CRFTData& from, const CRFTData& to,
     752             :                                 const CRFTData& expected) {
     753             :   const bool expected_deprecation = true;
     754             :   const bool expected_field_type_dependency = false;
     755             : 
     756             :   TestGeneralizeField(from, to, expected, expected_deprecation,
     757          20 :                       expected_field_type_dependency);
     758             : }
     759             : 
     760             : static void TestGeneralizeFieldTrivial(
     761             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected,
     762             :     bool expected_field_type_dependency = true) {
     763             :   const bool expected_deprecation = false;
     764             : 
     765             :   TestGeneralizeField(from, to, expected, expected_deprecation,
     766          20 :                       expected_field_type_dependency);
     767             : }
     768             : 
     769       26067 : TEST(GeneralizeSmiFieldToDouble) {
     770           4 :   CcTest::InitializeVM();
     771           8 :   v8::HandleScope scope(CcTest::isolate());
     772             :   Isolate* isolate = CcTest::i_isolate();
     773             : 
     774           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     775             : 
     776           8 :   TestGeneralizeField(
     777             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
     778             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
     779             :       {PropertyConstness::kMutable, Representation::Double(), any_type});
     780           4 : }
     781             : 
     782       26067 : TEST(GeneralizeSmiFieldToTagged) {
     783           4 :   CcTest::InitializeVM();
     784           8 :   v8::HandleScope scope(CcTest::isolate());
     785             :   Isolate* isolate = CcTest::i_isolate();
     786             : 
     787           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     788             :   Handle<FieldType> value_type =
     789           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     790             : 
     791           8 :   TestGeneralizeField(
     792             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
     793             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
     794             :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
     795           4 : }
     796             : 
     797       26067 : TEST(GeneralizeDoubleFieldToTagged) {
     798           4 :   CcTest::InitializeVM();
     799           8 :   v8::HandleScope scope(CcTest::isolate());
     800             :   Isolate* isolate = CcTest::i_isolate();
     801             : 
     802           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     803             :   Handle<FieldType> value_type =
     804           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     805             : 
     806           8 :   TestGeneralizeField(
     807             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
     808             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
     809             :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
     810           4 : }
     811             : 
     812       26067 : TEST(GeneralizeHeapObjectFieldToTagged) {
     813           4 :   CcTest::InitializeVM();
     814           8 :   v8::HandleScope scope(CcTest::isolate());
     815             :   Isolate* isolate = CcTest::i_isolate();
     816             : 
     817           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     818             :   Handle<FieldType> value_type =
     819           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     820             : 
     821           8 :   TestGeneralizeField(
     822             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
     823             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
     824             :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
     825           4 : }
     826             : 
     827       26067 : TEST(GeneralizeHeapObjectFieldToHeapObject) {
     828           4 :   CcTest::InitializeVM();
     829           8 :   v8::HandleScope scope(CcTest::isolate());
     830             :   Isolate* isolate = CcTest::i_isolate();
     831             : 
     832           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     833             : 
     834             :   Handle<FieldType> current_type =
     835           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     836             : 
     837             :   Handle<FieldType> new_type =
     838           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     839             : 
     840           4 :   Handle<FieldType> expected_type = any_type;
     841             : 
     842           8 :   TestGeneralizeFieldTrivial(
     843             :       {PropertyConstness::kMutable, Representation::HeapObject(), current_type},
     844             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
     845             :       {PropertyConstness::kMutable, Representation::HeapObject(),
     846             :        expected_type});
     847             :   current_type = expected_type;
     848             : 
     849           4 :   new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
     850             : 
     851           8 :   TestGeneralizeFieldTrivial(
     852             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
     853             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
     854             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
     855             :       false);
     856           4 : }
     857             : 
     858       26067 : TEST(GeneralizeNoneFieldToSmi) {
     859           4 :   CcTest::InitializeVM();
     860           8 :   v8::HandleScope scope(CcTest::isolate());
     861             :   Isolate* isolate = CcTest::i_isolate();
     862             : 
     863           4 :   Handle<FieldType> none_type = FieldType::None(isolate);
     864           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     865             : 
     866             :   // None -> Smi representation change is trivial.
     867           8 :   TestGeneralizeFieldTrivial(
     868             :       {PropertyConstness::kMutable, Representation::None(), none_type},
     869             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
     870             :       {PropertyConstness::kMutable, Representation::Smi(), any_type});
     871           4 : }
     872             : 
     873       26067 : TEST(GeneralizeNoneFieldToDouble) {
     874           4 :   CcTest::InitializeVM();
     875           8 :   v8::HandleScope scope(CcTest::isolate());
     876             :   Isolate* isolate = CcTest::i_isolate();
     877             : 
     878           4 :   Handle<FieldType> none_type = FieldType::None(isolate);
     879           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     880             : 
     881             :   // None -> Double representation change is NOT trivial.
     882           8 :   TestGeneralizeField(
     883             :       {PropertyConstness::kMutable, Representation::None(), none_type},
     884             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
     885             :       {PropertyConstness::kMutable, Representation::Double(), any_type});
     886           4 : }
     887             : 
     888       26067 : TEST(GeneralizeNoneFieldToHeapObject) {
     889           4 :   CcTest::InitializeVM();
     890           8 :   v8::HandleScope scope(CcTest::isolate());
     891             :   Isolate* isolate = CcTest::i_isolate();
     892             : 
     893           4 :   Handle<FieldType> none_type = FieldType::None(isolate);
     894             :   Handle<FieldType> value_type =
     895           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     896             : 
     897             :   // None -> HeapObject representation change is trivial.
     898           8 :   TestGeneralizeFieldTrivial(
     899             :       {PropertyConstness::kMutable, Representation::None(), none_type},
     900             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
     901             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type});
     902           4 : }
     903             : 
     904       26067 : TEST(GeneralizeNoneFieldToTagged) {
     905           4 :   CcTest::InitializeVM();
     906           8 :   v8::HandleScope scope(CcTest::isolate());
     907             :   Isolate* isolate = CcTest::i_isolate();
     908             : 
     909           4 :   Handle<FieldType> none_type = FieldType::None(isolate);
     910           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     911             : 
     912             :   // None -> HeapObject representation change is trivial.
     913           8 :   TestGeneralizeFieldTrivial(
     914             :       {PropertyConstness::kMutable, Representation::None(), none_type},
     915             :       {PropertyConstness::kMutable, Representation::Tagged(), any_type},
     916             :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
     917           4 : }
     918             : 
     919             : 
     920             : ////////////////////////////////////////////////////////////////////////////////
     921             : // A set of tests for field generalization case with kAccessor properties.
     922             : //
     923             : 
     924       26067 : TEST(GeneralizeFieldWithAccessorProperties) {
     925           4 :   CcTest::InitializeVM();
     926           8 :   v8::HandleScope scope(CcTest::isolate());
     927             :   Isolate* isolate = CcTest::i_isolate();
     928             : 
     929           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     930           4 :   Handle<AccessorPair> pair = CreateAccessorPair(true, true);
     931             : 
     932             :   const int kAccessorProp = kPropCount / 2;
     933           4 :   Expectations expectations(isolate);
     934             : 
     935             :   // Create a map, add required properties to it and initialize expectations.
     936           4 :   Handle<Map> initial_map = Map::Create(isolate, 0);
     937           4 :   Handle<Map> map = initial_map;
     938          60 :   for (int i = 0; i < kPropCount; i++) {
     939          28 :     if (i == kAccessorProp) {
     940           4 :       map = expectations.AddAccessorConstant(map, NONE, pair);
     941             :     } else {
     942             :       map = expectations.AddDataField(map, NONE, PropertyConstness::kMutable,
     943          24 :                                       Representation::Smi(), any_type);
     944             :     }
     945             :   }
     946           4 :   CHECK(!map->is_deprecated());
     947           4 :   CHECK(map->is_stable());
     948           4 :   CHECK(expectations.Check(*map));
     949             : 
     950             :   // Create new maps by generalizing representation of propX field.
     951          60 :   Handle<Map> maps[kPropCount];
     952          60 :   for (int i = 0; i < kPropCount; i++) {
     953          28 :     if (i == kAccessorProp) {
     954             :       // Skip accessor property reconfiguration.
     955           4 :       maps[i] = maps[i - 1];
     956             :       continue;
     957             :     }
     958             :     Handle<Map> new_map = Map::ReconfigureProperty(
     959          24 :         isolate, map, i, kData, NONE, Representation::Double(), any_type);
     960          24 :     maps[i] = new_map;
     961             : 
     962             :     expectations.SetDataField(i, PropertyConstness::kMutable,
     963             :                               Representation::Double(), any_type);
     964             : 
     965          24 :     CHECK(!map->is_stable());
     966          24 :     CHECK(map->is_deprecated());
     967          24 :     CHECK_NE(*map, *new_map);
     968          44 :     CHECK(i == 0 || maps[i - 1]->is_deprecated());
     969             : 
     970          24 :     CHECK(!new_map->is_deprecated());
     971          24 :     CHECK(expectations.Check(*new_map));
     972             :   }
     973             : 
     974           4 :   Handle<Map> active_map = maps[kPropCount - 1];
     975           4 :   CHECK(!active_map->is_deprecated());
     976             : 
     977             :   // Update all deprecated maps and check that they are now the same.
     978           4 :   Handle<Map> updated_map = Map::Update(isolate, map);
     979           4 :   CHECK_EQ(*active_map, *updated_map);
     980           4 :   CheckMigrationTarget(isolate, *map, *updated_map);
     981          60 :   for (int i = 0; i < kPropCount; i++) {
     982          28 :     updated_map = Map::Update(isolate, maps[i]);
     983          28 :     CHECK_EQ(*active_map, *updated_map);
     984          56 :     CheckMigrationTarget(isolate, *maps[i], *updated_map);
     985             :   }
     986           4 : }
     987             : 
     988             : 
     989             : ////////////////////////////////////////////////////////////////////////////////
     990             : // A set of tests for attribute reconfiguration case.
     991             : //
     992             : 
     993             : // This test ensures that field generalization is correctly propagated from one
     994             : // branch of transition tree (|map2|) to another (|map|).
     995             : //
     996             : //             + - p2B - p3 - p4: |map2|
     997             : //             |
     998             : //  {} - p0 - p1 - p2A - p3 - p4: |map|
     999             : //
    1000             : // where "p2A" and "p2B" differ only in the attributes.
    1001             : //
    1002          52 : static void TestReconfigureDataFieldAttribute_GeneralizeField(
    1003             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
    1004             :   Isolate* isolate = CcTest::i_isolate();
    1005             : 
    1006          52 :   Expectations expectations(isolate);
    1007             : 
    1008             :   // Create a map, add required properties to it and initialize expectations.
    1009          52 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1010          52 :   Handle<Map> map = initial_map;
    1011         780 :   for (int i = 0; i < kPropCount; i++) {
    1012         364 :     map = expectations.AddDataField(map, NONE, from.constness,
    1013         364 :                                     from.representation, from.type);
    1014             :   }
    1015          52 :   CHECK(!map->is_deprecated());
    1016          52 :   CHECK(map->is_stable());
    1017          52 :   CHECK(expectations.Check(*map));
    1018             : 
    1019             : 
    1020             :   // Create another branch in transition tree (property at index |kSplitProp|
    1021             :   // has different attributes), initialize expectations.
    1022             :   const int kSplitProp = kPropCount / 2;
    1023          52 :   Expectations expectations2(isolate);
    1024             : 
    1025             :   Handle<Map> map2 = initial_map;
    1026         364 :   for (int i = 0; i < kSplitProp; i++) {
    1027         156 :     map2 = expectations2.FollowDataTransition(map2, NONE, from.constness,
    1028         156 :                                               from.representation, from.type);
    1029             :   }
    1030          52 :   map2 = expectations2.AddDataField(map2, READ_ONLY, to.constness,
    1031          52 :                                     to.representation, to.type);
    1032             : 
    1033         364 :   for (int i = kSplitProp + 1; i < kPropCount; i++) {
    1034         156 :     map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1035         156 :                                       to.representation, to.type);
    1036             :   }
    1037          52 :   CHECK(!map2->is_deprecated());
    1038          52 :   CHECK(map2->is_stable());
    1039          52 :   CHECK(expectations2.Check(*map2));
    1040             : 
    1041         104 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1042         104 :   CanonicalHandleScope canonical(isolate);
    1043         104 :   JSHeapBroker broker(isolate, &zone);
    1044          52 :   CompilationDependencies dependencies(&broker, &zone);
    1045             :   MapRef map_ref(&broker, map);
    1046          52 :   map_ref.SerializeOwnDescriptors();
    1047          52 :   dependencies.DependOnFieldType(map_ref, kSplitProp);
    1048             : 
    1049             :   // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
    1050             :   // should generalize representations in |map1|.
    1051             :   Handle<Map> new_map =
    1052          52 :       Map::ReconfigureExistingProperty(isolate, map2, kSplitProp, kData, NONE);
    1053             : 
    1054             :   // |map2| should be left unchanged but marked unstable.
    1055          52 :   CHECK(!map2->is_stable());
    1056          52 :   CHECK(!map2->is_deprecated());
    1057          52 :   CHECK_NE(*map2, *new_map);
    1058          52 :   CHECK(expectations2.Check(*map2));
    1059             : 
    1060             :   // |map| should be deprecated and |new_map| should match new expectations.
    1061         468 :   for (int i = kSplitProp; i < kPropCount; i++) {
    1062         208 :     expectations.SetDataField(i, expected.constness, expected.representation,
    1063             :                               expected.type);
    1064             :   }
    1065          52 :   CHECK(map->is_deprecated());
    1066          52 :   CHECK(dependencies.AreValid());
    1067          52 :   CHECK_NE(*map, *new_map);
    1068             : 
    1069          52 :   CHECK(!new_map->is_deprecated());
    1070          52 :   CHECK(expectations.Check(*new_map));
    1071             : 
    1072             :   // Update deprecated |map|, it should become |new_map|.
    1073          52 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1074          52 :   CHECK_EQ(*new_map, *updated_map);
    1075          52 :   CheckMigrationTarget(isolate, *map, *updated_map);
    1076          52 : }
    1077             : 
    1078             : // This test ensures that trivial field generalization (from HeapObject to
    1079             : // HeapObject) is correctly propagated from one branch of transition tree
    1080             : // (|map2|) to another (|map|).
    1081             : //
    1082             : //             + - p2B - p3 - p4: |map2|
    1083             : //             |
    1084             : //  {} - p0 - p1 - p2A - p3 - p4: |map|
    1085             : //
    1086             : // where "p2A" and "p2B" differ only in the attributes.
    1087             : //
    1088          32 : static void TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1089             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected,
    1090             :     bool expected_field_type_dependency = true) {
    1091             :   Isolate* isolate = CcTest::i_isolate();
    1092             : 
    1093          32 :   Expectations expectations(isolate);
    1094             : 
    1095             :   // Create a map, add required properties to it and initialize expectations.
    1096          32 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1097          32 :   Handle<Map> map = initial_map;
    1098         480 :   for (int i = 0; i < kPropCount; i++) {
    1099         224 :     map = expectations.AddDataField(map, NONE, from.constness,
    1100         224 :                                     from.representation, from.type);
    1101             :   }
    1102          32 :   CHECK(!map->is_deprecated());
    1103          32 :   CHECK(map->is_stable());
    1104          32 :   CHECK(expectations.Check(*map));
    1105             : 
    1106             : 
    1107             :   // Create another branch in transition tree (property at index |kSplitProp|
    1108             :   // has different attributes), initialize expectations.
    1109             :   const int kSplitProp = kPropCount / 2;
    1110          32 :   Expectations expectations2(isolate);
    1111             : 
    1112             :   Handle<Map> map2 = initial_map;
    1113         224 :   for (int i = 0; i < kSplitProp; i++) {
    1114          96 :     map2 = expectations2.FollowDataTransition(map2, NONE, from.constness,
    1115          96 :                                               from.representation, from.type);
    1116             :   }
    1117          32 :   map2 = expectations2.AddDataField(map2, READ_ONLY, to.constness,
    1118          32 :                                     to.representation, to.type);
    1119             : 
    1120         224 :   for (int i = kSplitProp + 1; i < kPropCount; i++) {
    1121          96 :     map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1122          96 :                                       to.representation, to.type);
    1123             :   }
    1124          32 :   CHECK(!map2->is_deprecated());
    1125          32 :   CHECK(map2->is_stable());
    1126          32 :   CHECK(expectations2.Check(*map2));
    1127             : 
    1128          64 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1129          64 :   CanonicalHandleScope canonical(isolate);
    1130          64 :   JSHeapBroker broker(isolate, &zone);
    1131          32 :   CompilationDependencies dependencies(&broker, &zone);
    1132             :   MapRef map_ref(&broker, map);
    1133          32 :   map_ref.SerializeOwnDescriptors();
    1134          32 :   dependencies.DependOnFieldType(map_ref, kSplitProp);
    1135          32 :   dependencies.DependOnFieldConstness(map_ref, kSplitProp);
    1136             : 
    1137             :   // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
    1138             :   // should generalize representations in |map1|.
    1139             :   Handle<Map> new_map =
    1140          32 :       Map::ReconfigureExistingProperty(isolate, map2, kSplitProp, kData, NONE);
    1141             : 
    1142             :   // |map2| should be left unchanged but marked unstable.
    1143          32 :   CHECK(!map2->is_stable());
    1144          32 :   CHECK(!map2->is_deprecated());
    1145          32 :   CHECK_NE(*map2, *new_map);
    1146          32 :   CHECK(expectations2.Check(*map2));
    1147             : 
    1148             :   // In trivial case |map| should be returned as a result of the property
    1149             :   // reconfiguration, respective field types should be generalized and
    1150             :   // respective code dependencies should be invalidated. |map| should be NOT
    1151             :   // deprecated and it should match new expectations.
    1152         288 :   for (int i = kSplitProp; i < kPropCount; i++) {
    1153         128 :     expectations.SetDataField(i, expected.constness, expected.representation,
    1154             :                               expected.type);
    1155             :   }
    1156          32 :   CHECK(!map->is_deprecated());
    1157          32 :   CHECK_EQ(*map, *new_map);
    1158          32 :   CHECK_EQ(expected_field_type_dependency, !dependencies.AreValid());
    1159             : 
    1160          32 :   CHECK(!new_map->is_deprecated());
    1161          32 :   CHECK(expectations.Check(*new_map));
    1162             : 
    1163          32 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1164          32 :   CHECK_EQ(*new_map, *updated_map);
    1165          32 : }
    1166             : 
    1167       26067 : TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToDouble) {
    1168           4 :   CcTest::InitializeVM();
    1169           8 :   v8::HandleScope scope(CcTest::isolate());
    1170             :   Isolate* isolate = CcTest::i_isolate();
    1171             : 
    1172           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1173             : 
    1174             :   if (FLAG_track_constant_fields) {
    1175           8 :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1176             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1177             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1178           4 :         {PropertyConstness::kConst, Representation::Double(), any_type});
    1179             : 
    1180           8 :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1181             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1182             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    1183           4 :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1184             : 
    1185           8 :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1186             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1187             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1188           4 :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1189             :   }
    1190             : 
    1191           8 :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1192             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1193             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    1194           4 :       {PropertyConstness::kMutable, Representation::Double(), any_type});
    1195           4 : }
    1196             : 
    1197       26067 : TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
    1198           4 :   CcTest::InitializeVM();
    1199           8 :   v8::HandleScope scope(CcTest::isolate());
    1200             :   Isolate* isolate = CcTest::i_isolate();
    1201             : 
    1202           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1203             :   Handle<FieldType> value_type =
    1204           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1205             : 
    1206             :   if (FLAG_track_constant_fields) {
    1207           8 :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1208             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1209             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1210           4 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    1211             : 
    1212           8 :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1213             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1214             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1215           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1216             : 
    1217           8 :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1218             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1219             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1220           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1221             :   }
    1222             : 
    1223           8 :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1224             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1225             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1226           4 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1227           4 : }
    1228             : 
    1229       26067 : TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
    1230           4 :   CcTest::InitializeVM();
    1231           8 :   v8::HandleScope scope(CcTest::isolate());
    1232             :   Isolate* isolate = CcTest::i_isolate();
    1233             : 
    1234           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1235             :   Handle<FieldType> value_type =
    1236           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1237             : 
    1238             :   if (FLAG_track_constant_fields) {
    1239           8 :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1240             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1241             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1242           4 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    1243             : 
    1244           8 :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1245             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1246             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1247           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1248             : 
    1249           8 :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1250             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    1251             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1252           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1253             :   }
    1254             : 
    1255           8 :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1256             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    1257             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1258           4 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1259           4 : }
    1260             : 
    1261       26067 : TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjFieldToHeapObj) {
    1262           4 :   CcTest::InitializeVM();
    1263           8 :   v8::HandleScope scope(CcTest::isolate());
    1264             :   Isolate* isolate = CcTest::i_isolate();
    1265             : 
    1266           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1267             : 
    1268             :   Handle<FieldType> current_type =
    1269           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1270             : 
    1271             :   Handle<FieldType> new_type =
    1272           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1273             : 
    1274           4 :   Handle<FieldType> expected_type = any_type;
    1275             : 
    1276             :   // Check generalizations that trigger deopts.
    1277             :   if (FLAG_track_constant_fields) {
    1278           8 :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1279             :         {PropertyConstness::kConst, Representation::HeapObject(), current_type},
    1280             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1281             :         {PropertyConstness::kConst, Representation::HeapObject(),
    1282           4 :          expected_type});
    1283             : 
    1284             :     if (FLAG_modify_map_inplace) {
    1285             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration does
    1286             :       // not create a new map, therefore trivial generalization.
    1287           8 :       TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1288             :           {PropertyConstness::kConst, Representation::HeapObject(),
    1289             :            current_type},
    1290             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1291             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1292           4 :            expected_type});
    1293             :     } else {
    1294             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration
    1295             :       // causes map change, therefore non-trivial generalization.
    1296             :       TestReconfigureDataFieldAttribute_GeneralizeField(
    1297             :           {PropertyConstness::kConst, Representation::HeapObject(),
    1298             :            current_type},
    1299             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1300             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1301             :            expected_type});
    1302             :     }
    1303           8 :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1304             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    1305             :          current_type},
    1306             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1307             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    1308           4 :          expected_type});
    1309             :   }
    1310           8 :   TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1311             :       {PropertyConstness::kMutable, Representation::HeapObject(), current_type},
    1312             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1313             :       {PropertyConstness::kMutable, Representation::HeapObject(),
    1314           4 :        expected_type});
    1315             :   current_type = expected_type;
    1316             : 
    1317             :   // Check generalizations that do not trigger deopts.
    1318           4 :   new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
    1319             : 
    1320             :   if (FLAG_track_constant_fields) {
    1321           8 :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1322             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1323             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1324             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1325           4 :         false);
    1326             : 
    1327             :     if (FLAG_modify_map_inplace) {
    1328             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration does
    1329             :       // not create a new map, therefore trivial generalization.
    1330           8 :       TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1331             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1332             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1333             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1334           4 :            any_type});
    1335             :     } else {
    1336             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration
    1337             :       // causes map change, therefore non-trivial generalization.
    1338             :       TestReconfigureDataFieldAttribute_GeneralizeField(
    1339             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1340             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1341             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1342             :            any_type});
    1343             :     }
    1344           8 :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1345             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1346             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1347             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1348           4 :         false);
    1349             :   }
    1350           8 :   TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1351             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1352             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1353             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1354           4 :       false);
    1355           4 : }
    1356             : 
    1357       26067 : TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjectFieldToTagged) {
    1358           4 :   CcTest::InitializeVM();
    1359           8 :   v8::HandleScope scope(CcTest::isolate());
    1360             :   Isolate* isolate = CcTest::i_isolate();
    1361             : 
    1362           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1363             :   Handle<FieldType> value_type =
    1364           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1365             : 
    1366           8 :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1367             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1368             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1369           4 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1370           4 : }
    1371             : 
    1372             : 
    1373             : // Checks that given |map| is deprecated and that it updates to given |new_map|
    1374             : // which in turn should match expectations.
    1375             : struct CheckDeprecated {
    1376             :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1377             :              const Expectations& expectations) {
    1378             :     CHECK(map->is_deprecated());
    1379             :     CHECK_NE(*map, *new_map);
    1380             : 
    1381             :     CHECK(!new_map->is_deprecated());
    1382             :     CHECK(expectations.Check(*new_map));
    1383             : 
    1384             :     // Update deprecated |map|, it should become |new_map|.
    1385             :     Handle<Map> updated_map = Map::Update(isolate, map);
    1386             :     CHECK_EQ(*new_map, *updated_map);
    1387             :     CheckMigrationTarget(isolate, *map, *updated_map);
    1388             :   }
    1389             : };
    1390             : 
    1391             : 
    1392             : // Checks that given |map| is NOT deprecated, equals to given |new_map| and
    1393             : // matches expectations.
    1394             : struct CheckSameMap {
    1395          12 :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1396             :              const Expectations& expectations) {
    1397             :     // |map| was not reconfigured, therefore it should stay stable.
    1398          12 :     CHECK(map->is_stable());
    1399          12 :     CHECK(!map->is_deprecated());
    1400          12 :     CHECK_EQ(*map, *new_map);
    1401             : 
    1402          12 :     CHECK(!new_map->is_deprecated());
    1403          12 :     CHECK(expectations.Check(*new_map));
    1404             : 
    1405             :     // Update deprecated |map|, it should become |new_map|.
    1406          12 :     Handle<Map> updated_map = Map::Update(isolate, map);
    1407          12 :     CHECK_EQ(*new_map, *updated_map);
    1408          12 :   }
    1409             : };
    1410             : 
    1411             : 
    1412             : // Checks that given |map| is NOT deprecated and matches expectations.
    1413             : // |new_map| is unrelated to |map|.
    1414             : struct CheckUnrelated {
    1415           8 :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1416             :              const Expectations& expectations) {
    1417           8 :     CHECK(!map->is_deprecated());
    1418           8 :     CHECK_NE(*map, *new_map);
    1419           8 :     CHECK(expectations.Check(*map));
    1420             : 
    1421           8 :     CHECK(new_map->is_stable());
    1422           8 :     CHECK(!new_map->is_deprecated());
    1423           8 :   }
    1424             : };
    1425             : 
    1426             : 
    1427             : // Checks that given |map| is NOT deprecated, and |new_map| is a result of
    1428             : // copy-generalize-all-representations.
    1429             : struct CheckCopyGeneralizeAllFields {
    1430           4 :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1431             :              Expectations& expectations) {
    1432           4 :     CHECK(!map->is_deprecated());
    1433           4 :     CHECK_NE(*map, *new_map);
    1434             : 
    1435           8 :     CHECK(new_map->GetBackPointer()->IsUndefined(isolate));
    1436          60 :     for (int i = 0; i < kPropCount; i++) {
    1437          28 :       expectations.GeneralizeField(i);
    1438             :     }
    1439             : 
    1440           4 :     CHECK(!new_map->is_deprecated());
    1441           4 :     CHECK(expectations.Check(*new_map));
    1442           4 :   }
    1443             : };
    1444             : 
    1445             : // This test ensures that field generalization is correctly propagated from one
    1446             : // branch of transition tree (|map2|) to another (|map1|).
    1447             : //
    1448             : //             + - p2B - p3 - p4: |map2|
    1449             : //             |
    1450             : //  {} - p0 - p1: |map|
    1451             : //             |
    1452             : //             + - p2A - p3 - p4: |map1|
    1453             : //                        |
    1454             : //                        + - the property customized by the TestConfig provided
    1455             : //
    1456             : // where "p2A" and "p2B" differ only in the attributes.
    1457             : //
    1458             : template <typename TestConfig, typename Checker>
    1459          24 : static void TestReconfigureProperty_CustomPropertyAfterTargetMap(
    1460             :     TestConfig& config, Checker& checker) {
    1461             :   Isolate* isolate = CcTest::i_isolate();
    1462          24 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1463             : 
    1464             :   const int kCustomPropIndex = kPropCount - 2;
    1465          24 :   Expectations expectations(isolate);
    1466             : 
    1467             :   const int kSplitProp = 2;
    1468             :   CHECK_LT(kSplitProp, kCustomPropIndex);
    1469             : 
    1470             :   const PropertyConstness constness = PropertyConstness::kMutable;
    1471          24 :   const Representation representation = Representation::Smi();
    1472             : 
    1473             :   // Create common part of transition tree.
    1474          24 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1475          24 :   Handle<Map> map = initial_map;
    1476         120 :   for (int i = 0; i < kSplitProp; i++) {
    1477          48 :     map = expectations.AddDataField(map, NONE, constness, representation,
    1478             :                                     any_type);
    1479             :   }
    1480          24 :   CHECK(!map->is_deprecated());
    1481          24 :   CHECK(map->is_stable());
    1482          24 :   CHECK(expectations.Check(*map));
    1483             : 
    1484             : 
    1485             :   // Create branch to |map1|.
    1486             :   Handle<Map> map1 = map;
    1487          24 :   Expectations expectations1 = expectations;
    1488         168 :   for (int i = kSplitProp; i < kCustomPropIndex; i++) {
    1489          72 :     map1 = expectations1.AddDataField(map1, NONE, constness, representation,
    1490             :                                       any_type);
    1491             :   }
    1492          24 :   map1 = config.AddPropertyAtBranch(1, expectations1, map1);
    1493          72 :   for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
    1494          24 :     map1 = expectations1.AddDataField(map1, NONE, constness, representation,
    1495             :                                       any_type);
    1496             :   }
    1497          24 :   CHECK(!map1->is_deprecated());
    1498          24 :   CHECK(map1->is_stable());
    1499          24 :   CHECK(expectations1.Check(*map1));
    1500             : 
    1501             : 
    1502             :   // Create another branch in transition tree (property at index |kSplitProp|
    1503             :   // has different attributes), initialize expectations.
    1504             :   Handle<Map> map2 = map;
    1505          24 :   Expectations expectations2 = expectations;
    1506          24 :   map2 = expectations2.AddDataField(map2, READ_ONLY, constness, representation,
    1507             :                                     any_type);
    1508         120 :   for (int i = kSplitProp + 1; i < kCustomPropIndex; i++) {
    1509          48 :     map2 = expectations2.AddDataField(map2, NONE, constness, representation,
    1510             :                                       any_type);
    1511             :   }
    1512          24 :   map2 = config.AddPropertyAtBranch(2, expectations2, map2);
    1513          72 :   for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
    1514          24 :     map2 = expectations2.AddDataField(map2, NONE, constness, representation,
    1515             :                                       any_type);
    1516             :   }
    1517          24 :   CHECK(!map2->is_deprecated());
    1518          24 :   CHECK(map2->is_stable());
    1519          24 :   CHECK(expectations2.Check(*map2));
    1520             : 
    1521             : 
    1522             :   // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
    1523             :   // should generalize representations in |map1|.
    1524             :   Handle<Map> new_map =
    1525          24 :       Map::ReconfigureExistingProperty(isolate, map2, kSplitProp, kData, NONE);
    1526             : 
    1527             :   // |map2| should be left unchanged but marked unstable.
    1528          24 :   CHECK(!map2->is_stable());
    1529          24 :   CHECK(!map2->is_deprecated());
    1530          24 :   CHECK_NE(*map2, *new_map);
    1531          24 :   CHECK(expectations2.Check(*map2));
    1532             : 
    1533           4 :   config.UpdateExpectations(kCustomPropIndex, expectations1);
    1534          24 :   checker.Check(isolate, map1, new_map, expectations1);
    1535          24 : }
    1536             : 
    1537             : 
    1538       26067 : TEST(ReconfigureDataFieldAttribute_SameDataConstantAfterTargetMap) {
    1539           4 :   CcTest::InitializeVM();
    1540           8 :   v8::HandleScope scope(CcTest::isolate());
    1541             : 
    1542             :   struct TestConfig {
    1543             :     Handle<JSFunction> js_func_;
    1544           4 :     TestConfig() {
    1545             :       Isolate* isolate = CcTest::i_isolate();
    1546             :       Factory* factory = isolate->factory();
    1547           4 :       js_func_ = factory->NewFunctionForTest(factory->empty_string());
    1548           4 :     }
    1549             : 
    1550           8 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1551             :                                     Handle<Map> map) {
    1552           8 :       CHECK(branch_id == 1 || branch_id == 2);
    1553             :       // Add the same data constant property at both transition tree branches.
    1554           8 :       return expectations.AddDataConstant(map, NONE, js_func_);
    1555             :     }
    1556             : 
    1557             :     void UpdateExpectations(int property_index, Expectations& expectations) {
    1558             :       // Expectations stay the same.
    1559             :     }
    1560             :   };
    1561             : 
    1562           4 :   TestConfig config;
    1563             :   // Two branches are "compatible" so the |map1| should NOT be deprecated.
    1564             :   CheckSameMap checker;
    1565           4 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1566           4 : }
    1567             : 
    1568             : 
    1569       26067 : TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) {
    1570           4 :   CcTest::InitializeVM();
    1571           8 :   v8::HandleScope scope(CcTest::isolate());
    1572             : 
    1573             :   struct TestConfig {
    1574             :     Handle<JSFunction> js_func1_;
    1575             :     Handle<JSFunction> js_func2_;
    1576             :     Handle<FieldType> function_type_;
    1577           4 :     TestConfig() {
    1578             :       Isolate* isolate = CcTest::i_isolate();
    1579             :       Factory* factory = isolate->factory();
    1580             :       Handle<String> name = factory->empty_string();
    1581             :       Handle<Map> sloppy_map =
    1582           4 :           Map::CopyInitialMap(isolate, isolate->sloppy_function_map());
    1583             :       Handle<SharedFunctionInfo> info =
    1584           4 :           factory->NewSharedFunctionInfoForBuiltin(name, Builtins::kIllegal);
    1585           4 :       function_type_ = FieldType::Class(sloppy_map, isolate);
    1586           4 :       CHECK(sloppy_map->is_stable());
    1587             : 
    1588             :       js_func1_ =
    1589           8 :           factory->NewFunction(sloppy_map, info, isolate->native_context());
    1590             : 
    1591             :       js_func2_ =
    1592           8 :           factory->NewFunction(sloppy_map, info, isolate->native_context());
    1593           4 :     }
    1594             : 
    1595           8 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1596             :                                     Handle<Map> map) {
    1597           8 :       CHECK(branch_id == 1 || branch_id == 2);
    1598           8 :       Handle<JSFunction> js_func = branch_id == 1 ? js_func1_ : js_func2_;
    1599           8 :       return expectations.AddDataConstant(map, NONE, js_func);
    1600             :     }
    1601             : 
    1602           4 :     void UpdateExpectations(int property_index, Expectations& expectations) {
    1603             :       PropertyConstness expected_constness = FLAG_track_constant_fields
    1604             :                                                  ? PropertyConstness::kConst
    1605             :                                                  : PropertyConstness::kMutable;
    1606             :       expectations.SetDataField(property_index, expected_constness,
    1607             :                                 Representation::HeapObject(), function_type_);
    1608           4 :     }
    1609             :   };
    1610             : 
    1611           4 :   TestConfig config;
    1612             :   if (FLAG_track_constant_fields) {
    1613             :     CheckSameMap checker;
    1614           4 :     TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1615             : 
    1616             :   } else {
    1617             :     // Two branches are "incompatible" so the |map1| should be deprecated.
    1618             :     CheckDeprecated checker;
    1619             :     TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1620             :   }
    1621           4 : }
    1622             : 
    1623             : 
    1624       26067 : TEST(ReconfigureDataFieldAttribute_DataConstantToAccConstantAfterTargetMap) {
    1625           4 :   CcTest::InitializeVM();
    1626           8 :   v8::HandleScope scope(CcTest::isolate());
    1627             : 
    1628             :   struct TestConfig {
    1629             :     Handle<JSFunction> js_func_;
    1630             :     Handle<AccessorPair> pair_;
    1631           4 :     TestConfig() {
    1632             :       Isolate* isolate = CcTest::i_isolate();
    1633             :       Factory* factory = isolate->factory();
    1634           4 :       js_func_ = factory->NewFunctionForTest(factory->empty_string());
    1635           4 :       pair_ = CreateAccessorPair(true, true);
    1636           4 :     }
    1637             : 
    1638           8 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1639             :                                     Handle<Map> map) {
    1640           8 :       CHECK(branch_id == 1 || branch_id == 2);
    1641           8 :       if (branch_id == 1) {
    1642           4 :         return expectations.AddDataConstant(map, NONE, js_func_);
    1643             :       } else {
    1644           4 :         return expectations.AddAccessorConstant(map, NONE, pair_);
    1645             :       }
    1646             :     }
    1647             : 
    1648             :     void UpdateExpectations(int property_index, Expectations& expectations) {}
    1649             :   };
    1650             : 
    1651           4 :   TestConfig config;
    1652             :   // These are completely separate branches in transition tree.
    1653             :   CheckUnrelated checker;
    1654           4 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1655           4 : }
    1656             : 
    1657             : 
    1658       26067 : TEST(ReconfigureDataFieldAttribute_SameAccessorConstantAfterTargetMap) {
    1659           4 :   CcTest::InitializeVM();
    1660           8 :   v8::HandleScope scope(CcTest::isolate());
    1661             : 
    1662             :   struct TestConfig {
    1663             :     Handle<AccessorPair> pair_;
    1664           4 :     TestConfig() { pair_ = CreateAccessorPair(true, true); }
    1665             : 
    1666           8 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1667             :                                     Handle<Map> map) {
    1668           8 :       CHECK(branch_id == 1 || branch_id == 2);
    1669             :       // Add the same accessor constant property at both transition tree
    1670             :       // branches.
    1671           8 :       return expectations.AddAccessorConstant(map, NONE, pair_);
    1672             :     }
    1673             : 
    1674             :     void UpdateExpectations(int property_index, Expectations& expectations) {
    1675             :       // Two branches are "compatible" so the |map1| should NOT be deprecated.
    1676             :     }
    1677             :   };
    1678             : 
    1679             :   TestConfig config;
    1680             :   CheckSameMap checker;
    1681           4 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1682           4 : }
    1683             : 
    1684             : 
    1685       26067 : TEST(ReconfigureDataFieldAttribute_AccConstantToAccFieldAfterTargetMap) {
    1686           4 :   CcTest::InitializeVM();
    1687           8 :   v8::HandleScope scope(CcTest::isolate());
    1688             : 
    1689             :   struct TestConfig {
    1690             :     Handle<AccessorPair> pair1_;
    1691             :     Handle<AccessorPair> pair2_;
    1692           4 :     TestConfig() {
    1693           4 :       pair1_ = CreateAccessorPair(true, true);
    1694           4 :       pair2_ = CreateAccessorPair(true, true);
    1695           4 :     }
    1696             : 
    1697           8 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1698             :                                     Handle<Map> map) {
    1699           8 :       CHECK(branch_id == 1 || branch_id == 2);
    1700           8 :       Handle<AccessorPair> pair = branch_id == 1 ? pair1_ : pair2_;
    1701           8 :       return expectations.AddAccessorConstant(map, NONE, pair);
    1702             :     }
    1703             : 
    1704             :     void UpdateExpectations(int property_index, Expectations& expectations) {
    1705             :       if (IS_ACCESSOR_FIELD_SUPPORTED) {
    1706             :         expectations.SetAccessorField(property_index);
    1707             :       } else {
    1708             :         // Currently we have a copy-generalize-all-representations case and
    1709             :         // ACCESSOR property becomes ACCESSOR_CONSTANT.
    1710           4 :         expectations.SetAccessorConstant(property_index, pair2_);
    1711             :       }
    1712             :     }
    1713             :   };
    1714             : 
    1715           4 :   TestConfig config;
    1716             :   if (IS_ACCESSOR_FIELD_SUPPORTED) {
    1717             :     CheckCopyGeneralizeAllFields checker;
    1718             :     TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1719             :   } else {
    1720             :     // Currently we have a copy-generalize-all-representations case.
    1721             :     CheckCopyGeneralizeAllFields checker;
    1722           4 :     TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1723             :   }
    1724           4 : }
    1725             : 
    1726             : 
    1727       26067 : TEST(ReconfigureDataFieldAttribute_AccConstantToDataFieldAfterTargetMap) {
    1728           4 :   CcTest::InitializeVM();
    1729           8 :   v8::HandleScope scope(CcTest::isolate());
    1730             : 
    1731             :   struct TestConfig {
    1732             :     Handle<AccessorPair> pair_;
    1733           4 :     TestConfig() { pair_ = CreateAccessorPair(true, true); }
    1734             : 
    1735           8 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1736             :                                     Handle<Map> map) {
    1737           8 :       CHECK(branch_id == 1 || branch_id == 2);
    1738           8 :       if (branch_id == 1) {
    1739           4 :         return expectations.AddAccessorConstant(map, NONE, pair_);
    1740             :       } else {
    1741             :         Isolate* isolate = CcTest::i_isolate();
    1742           4 :         Handle<FieldType> any_type = FieldType::Any(isolate);
    1743             :         return expectations.AddDataField(map, NONE, kDefaultFieldConstness,
    1744           4 :                                          Representation::Smi(), any_type);
    1745             :       }
    1746             :     }
    1747             : 
    1748             :     void UpdateExpectations(int property_index, Expectations& expectations) {}
    1749             :   };
    1750             : 
    1751             :   TestConfig config;
    1752             :   // These are completely separate branches in transition tree.
    1753             :   CheckUnrelated checker;
    1754           4 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1755           4 : }
    1756             : 
    1757             : 
    1758             : ////////////////////////////////////////////////////////////////////////////////
    1759             : // A set of tests for elements kind reconfiguration case.
    1760             : //
    1761             : 
    1762             : // This test ensures that field generalization is correctly propagated from one
    1763             : // branch of transition tree (|map2) to another (|map|).
    1764             : //
    1765             : //   + - p0 - p1 - p2A - p3 - p4: |map|
    1766             : //   |
    1767             : //  ek
    1768             : //   |
    1769             : //  {} - p0 - p1 - p2B - p3 - p4: |map2|
    1770             : //
    1771             : // where "p2A" and "p2B" differ only in the representation/field type.
    1772             : //
    1773          64 : static void TestReconfigureElementsKind_GeneralizeField(
    1774             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
    1775             :   Isolate* isolate = CcTest::i_isolate();
    1776             : 
    1777             :   Expectations expectations(isolate, PACKED_SMI_ELEMENTS);
    1778             : 
    1779             :   // Create a map, add required properties to it and initialize expectations.
    1780          64 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1781             :   initial_map->set_instance_type(JS_ARRAY_TYPE);
    1782          64 :   initial_map->set_elements_kind(PACKED_SMI_ELEMENTS);
    1783             : 
    1784             :   Handle<Map> map = initial_map;
    1785          64 :   map = expectations.AsElementsKind(map, PACKED_ELEMENTS);
    1786         960 :   for (int i = 0; i < kPropCount; i++) {
    1787         448 :     map = expectations.AddDataField(map, NONE, from.constness,
    1788         448 :                                     from.representation, from.type);
    1789             :   }
    1790          64 :   CHECK(!map->is_deprecated());
    1791          64 :   CHECK(map->is_stable());
    1792          64 :   CHECK(expectations.Check(*map));
    1793             : 
    1794             :   // Create another branch in transition tree (property at index |kDiffProp|
    1795             :   // has different representatio/field type), initialize expectations.
    1796             :   const int kDiffProp = kPropCount / 2;
    1797             :   Expectations expectations2(isolate, PACKED_SMI_ELEMENTS);
    1798             : 
    1799             :   Handle<Map> map2 = initial_map;
    1800         960 :   for (int i = 0; i < kPropCount; i++) {
    1801         448 :     if (i == kDiffProp) {
    1802          64 :       map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1803          64 :                                         to.representation, to.type);
    1804             :     } else {
    1805         384 :       map2 = expectations2.AddDataField(map2, NONE, from.constness,
    1806         384 :                                         from.representation, from.type);
    1807             :     }
    1808             :   }
    1809          64 :   CHECK(!map2->is_deprecated());
    1810          64 :   CHECK(map2->is_stable());
    1811          64 :   CHECK(expectations2.Check(*map2));
    1812             : 
    1813         128 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1814         128 :   CanonicalHandleScope canonical(isolate);
    1815         128 :   JSHeapBroker broker(isolate, &zone);
    1816          64 :   CompilationDependencies dependencies(&broker, &zone);
    1817             :   MapRef map_ref(&broker, map);
    1818          64 :   map_ref.SerializeOwnDescriptors();
    1819          64 :   dependencies.DependOnFieldType(map_ref, kDiffProp);
    1820             : 
    1821             :   // Reconfigure elements kinds of |map2|, which should generalize
    1822             :   // representations in |map|.
    1823             :   Handle<Map> new_map =
    1824          64 :       Map::ReconfigureElementsKind(isolate, map2, PACKED_ELEMENTS);
    1825             : 
    1826             :   // |map2| should be left unchanged but marked unstable.
    1827          64 :   CHECK(!map2->is_stable());
    1828          64 :   CHECK(!map2->is_deprecated());
    1829          64 :   CHECK_NE(*map2, *new_map);
    1830          64 :   CHECK(expectations2.Check(*map2));
    1831             : 
    1832             :   // |map| should be deprecated and |new_map| should match new expectations.
    1833          64 :   expectations.SetDataField(kDiffProp, expected.constness,
    1834             :                             expected.representation, expected.type);
    1835             : 
    1836          64 :   CHECK(map->is_deprecated());
    1837          64 :   CHECK(dependencies.AreValid());
    1838          64 :   CHECK_NE(*map, *new_map);
    1839             : 
    1840          64 :   CHECK(!new_map->is_deprecated());
    1841          64 :   CHECK(expectations.Check(*new_map));
    1842             : 
    1843             :   // Update deprecated |map|, it should become |new_map|.
    1844          64 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1845          64 :   CHECK_EQ(*new_map, *updated_map);
    1846          64 :   CheckMigrationTarget(isolate, *map, *updated_map);
    1847             : 
    1848             :   // Ensure Map::FindElementsKindTransitionedMap() is able to find the
    1849             :   // transitioned map.
    1850             :   {
    1851             :     MapHandles map_list;
    1852          64 :     map_list.push_back(updated_map);
    1853             :     Map transitioned_map =
    1854          64 :         map2->FindElementsKindTransitionedMap(isolate, map_list);
    1855          64 :     CHECK_EQ(*updated_map, transitioned_map);
    1856             :   }
    1857          64 : }
    1858             : 
    1859             : // This test ensures that trivial field generalization (from HeapObject to
    1860             : // HeapObject) is correctly propagated from one branch of transition tree
    1861             : // (|map2|) to another (|map|).
    1862             : //
    1863             : //   + - p0 - p1 - p2A - p3 - p4: |map|
    1864             : //   |
    1865             : //  ek
    1866             : //   |
    1867             : //  {} - p0 - p1 - p2B - p3 - p4: |map2|
    1868             : //
    1869             : // where "p2A" and "p2B" differ only in the representation/field type.
    1870             : //
    1871          32 : static void TestReconfigureElementsKind_GeneralizeFieldTrivial(
    1872             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
    1873             :   Isolate* isolate = CcTest::i_isolate();
    1874             : 
    1875             :   Expectations expectations(isolate, PACKED_SMI_ELEMENTS);
    1876             : 
    1877             :   // Create a map, add required properties to it and initialize expectations.
    1878          32 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1879             :   initial_map->set_instance_type(JS_ARRAY_TYPE);
    1880          32 :   initial_map->set_elements_kind(PACKED_SMI_ELEMENTS);
    1881             : 
    1882             :   Handle<Map> map = initial_map;
    1883          32 :   map = expectations.AsElementsKind(map, PACKED_ELEMENTS);
    1884         480 :   for (int i = 0; i < kPropCount; i++) {
    1885         224 :     map = expectations.AddDataField(map, NONE, from.constness,
    1886         224 :                                     from.representation, from.type);
    1887             :   }
    1888          32 :   CHECK(!map->is_deprecated());
    1889          32 :   CHECK(map->is_stable());
    1890          32 :   CHECK(expectations.Check(*map));
    1891             : 
    1892             :   // Create another branch in transition tree (property at index |kDiffProp|
    1893             :   // has different attributes), initialize expectations.
    1894             :   const int kDiffProp = kPropCount / 2;
    1895             :   Expectations expectations2(isolate, PACKED_SMI_ELEMENTS);
    1896             : 
    1897             :   Handle<Map> map2 = initial_map;
    1898         480 :   for (int i = 0; i < kPropCount; i++) {
    1899         224 :     if (i == kDiffProp) {
    1900          32 :       map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1901          32 :                                         to.representation, to.type);
    1902             :     } else {
    1903         192 :       map2 = expectations2.AddDataField(map2, NONE, from.constness,
    1904         192 :                                         from.representation, from.type);
    1905             :     }
    1906             :   }
    1907          32 :   CHECK(!map2->is_deprecated());
    1908          32 :   CHECK(map2->is_stable());
    1909          32 :   CHECK(expectations2.Check(*map2));
    1910             : 
    1911          64 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1912          64 :   CanonicalHandleScope canonical(isolate);
    1913          64 :   JSHeapBroker broker(isolate, &zone);
    1914          32 :   CompilationDependencies dependencies(&broker, &zone);
    1915             :   MapRef map_ref(&broker, map);
    1916          32 :   map_ref.SerializeOwnDescriptors();
    1917             : 
    1918          32 :   dependencies.DependOnFieldType(map_ref, kDiffProp);
    1919          32 :   dependencies.DependOnFieldConstness(map_ref, kDiffProp);
    1920             : 
    1921             :   // Reconfigure elements kinds of |map2|, which should generalize
    1922             :   // representations in |map|.
    1923             :   Handle<Map> new_map =
    1924          32 :       Map::ReconfigureElementsKind(isolate, map2, PACKED_ELEMENTS);
    1925             : 
    1926             :   // |map2| should be left unchanged but marked unstable.
    1927          32 :   CHECK(!map2->is_stable());
    1928          32 :   CHECK(!map2->is_deprecated());
    1929          32 :   CHECK_NE(*map2, *new_map);
    1930          32 :   CHECK(expectations2.Check(*map2));
    1931             : 
    1932             :   // In trivial case |map| should be returned as a result of the elements
    1933             :   // kind reconfiguration, respective field types should be generalized and
    1934             :   // respective code dependencies should be invalidated. |map| should be NOT
    1935             :   // deprecated and it should match new expectations.
    1936          32 :   expectations.SetDataField(kDiffProp, expected.constness,
    1937             :                             expected.representation, expected.type);
    1938          32 :   CHECK(!map->is_deprecated());
    1939          32 :   CHECK_EQ(*map, *new_map);
    1940          64 :   CHECK_EQ(IsGeneralizableTo(to.constness, from.constness),
    1941             :            dependencies.AreValid());
    1942             : 
    1943          32 :   CHECK(!new_map->is_deprecated());
    1944          32 :   CHECK(expectations.Check(*new_map));
    1945             : 
    1946          32 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1947          32 :   CHECK_EQ(*new_map, *updated_map);
    1948             : 
    1949             :   // Ensure Map::FindElementsKindTransitionedMap() is able to find the
    1950             :   // transitioned map.
    1951             :   {
    1952             :     MapHandles map_list;
    1953          32 :     map_list.push_back(updated_map);
    1954             :     Map transitioned_map =
    1955          32 :         map2->FindElementsKindTransitionedMap(isolate, map_list);
    1956          32 :     CHECK_EQ(*updated_map, transitioned_map);
    1957             :   }
    1958          32 : }
    1959             : 
    1960       26067 : TEST(ReconfigureElementsKind_GeneralizeSmiFieldToDouble) {
    1961           4 :   CcTest::InitializeVM();
    1962           8 :   v8::HandleScope scope(CcTest::isolate());
    1963             :   Isolate* isolate = CcTest::i_isolate();
    1964             : 
    1965           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1966             : 
    1967             :   if (FLAG_track_constant_fields) {
    1968           8 :     TestReconfigureElementsKind_GeneralizeField(
    1969             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1970             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1971           4 :         {PropertyConstness::kConst, Representation::Double(), any_type});
    1972             : 
    1973           8 :     TestReconfigureElementsKind_GeneralizeField(
    1974             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1975             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    1976           4 :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1977             : 
    1978           8 :     TestReconfigureElementsKind_GeneralizeField(
    1979             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1980             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1981           4 :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1982             :   }
    1983           8 :   TestReconfigureElementsKind_GeneralizeField(
    1984             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1985             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    1986           4 :       {PropertyConstness::kMutable, Representation::Double(), any_type});
    1987           4 : }
    1988             : 
    1989       26067 : TEST(ReconfigureElementsKind_GeneralizeSmiFieldToTagged) {
    1990           4 :   CcTest::InitializeVM();
    1991           8 :   v8::HandleScope scope(CcTest::isolate());
    1992             :   Isolate* isolate = CcTest::i_isolate();
    1993             : 
    1994           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1995             :   Handle<FieldType> value_type =
    1996           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1997             : 
    1998             :   if (FLAG_track_constant_fields) {
    1999           8 :     TestReconfigureElementsKind_GeneralizeField(
    2000             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2001             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2002           4 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    2003             : 
    2004           8 :     TestReconfigureElementsKind_GeneralizeField(
    2005             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2006             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2007           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2008             : 
    2009           8 :     TestReconfigureElementsKind_GeneralizeField(
    2010             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2011             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2012           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2013             :   }
    2014           8 :   TestReconfigureElementsKind_GeneralizeField(
    2015             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2016             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2017           4 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2018           4 : }
    2019             : 
    2020       26067 : TEST(ReconfigureElementsKind_GeneralizeDoubleFieldToTagged) {
    2021           4 :   CcTest::InitializeVM();
    2022           8 :   v8::HandleScope scope(CcTest::isolate());
    2023             :   Isolate* isolate = CcTest::i_isolate();
    2024             : 
    2025           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2026             :   Handle<FieldType> value_type =
    2027           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2028             : 
    2029             :   if (FLAG_track_constant_fields) {
    2030           8 :     TestReconfigureElementsKind_GeneralizeField(
    2031             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    2032             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2033           4 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    2034             : 
    2035           8 :     TestReconfigureElementsKind_GeneralizeField(
    2036             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    2037             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2038           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2039             : 
    2040           8 :     TestReconfigureElementsKind_GeneralizeField(
    2041             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    2042             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2043           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2044             :   }
    2045           8 :   TestReconfigureElementsKind_GeneralizeField(
    2046             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    2047             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2048           4 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2049           4 : }
    2050             : 
    2051       26067 : TEST(ReconfigureElementsKind_GeneralizeHeapObjFieldToHeapObj) {
    2052           4 :   CcTest::InitializeVM();
    2053           8 :   v8::HandleScope scope(CcTest::isolate());
    2054             :   Isolate* isolate = CcTest::i_isolate();
    2055             : 
    2056           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2057             : 
    2058             :   Handle<FieldType> current_type =
    2059           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2060             : 
    2061             :   Handle<FieldType> new_type =
    2062           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2063             : 
    2064           4 :   Handle<FieldType> expected_type = any_type;
    2065             : 
    2066             :   // Check generalizations that trigger deopts.
    2067             :   if (FLAG_track_constant_fields) {
    2068           8 :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2069             :         {PropertyConstness::kConst, Representation::HeapObject(), current_type},
    2070             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2071             :         {PropertyConstness::kConst, Representation::HeapObject(),
    2072           4 :          expected_type});
    2073             :     if (FLAG_modify_map_inplace) {
    2074             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration does
    2075             :       // not create a new map, therefore trivial generalization.
    2076           8 :       TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2077             :           {PropertyConstness::kConst, Representation::HeapObject(),
    2078             :            current_type},
    2079             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2080             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2081           4 :            expected_type});
    2082             :     } else {
    2083             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration
    2084             :       // causes map change, therefore non-trivial generalization.
    2085             :       TestReconfigureElementsKind_GeneralizeField(
    2086             :           {PropertyConstness::kConst, Representation::HeapObject(),
    2087             :            current_type},
    2088             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2089             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2090             :            expected_type});
    2091             :     }
    2092           8 :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2093             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    2094             :          current_type},
    2095             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2096             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    2097           4 :          expected_type});
    2098             :   }
    2099           8 :   TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2100             :       {PropertyConstness::kMutable, Representation::HeapObject(), current_type},
    2101             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2102             :       {PropertyConstness::kMutable, Representation::HeapObject(),
    2103           4 :        expected_type});
    2104             :   current_type = expected_type;
    2105             : 
    2106             :   // Check generalizations that do not trigger deopts.
    2107           4 :   new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
    2108             : 
    2109             :   if (FLAG_track_constant_fields) {
    2110           8 :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2111             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    2112             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2113           4 :         {PropertyConstness::kConst, Representation::HeapObject(), any_type});
    2114             : 
    2115             :     if (FLAG_modify_map_inplace) {
    2116             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration does
    2117             :       // not create a new map, therefore trivial generalization.
    2118           8 :       TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2119             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    2120             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2121             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2122           4 :            any_type});
    2123             :     } else {
    2124             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration
    2125             :       // causes map change, therefore non-trivial generalization.
    2126             :       TestReconfigureElementsKind_GeneralizeField(
    2127             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    2128             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2129             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2130             :            any_type});
    2131             :     }
    2132             : 
    2133           8 :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2134             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    2135             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2136           4 :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type});
    2137             :   }
    2138           8 :   TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2139             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    2140             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2141           4 :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type});
    2142           4 : }
    2143             : 
    2144       26067 : TEST(ReconfigureElementsKind_GeneralizeHeapObjectFieldToTagged) {
    2145           4 :   CcTest::InitializeVM();
    2146           8 :   v8::HandleScope scope(CcTest::isolate());
    2147             :   Isolate* isolate = CcTest::i_isolate();
    2148             : 
    2149           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2150             :   Handle<FieldType> value_type =
    2151           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2152             : 
    2153             :   if (FLAG_track_constant_fields) {
    2154           8 :     TestReconfigureElementsKind_GeneralizeField(
    2155             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2156             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2157           4 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    2158             : 
    2159           8 :     TestReconfigureElementsKind_GeneralizeField(
    2160             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2161             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2162           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2163             : 
    2164           8 :     TestReconfigureElementsKind_GeneralizeField(
    2165             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2166             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2167           4 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2168             :   }
    2169           8 :   TestReconfigureElementsKind_GeneralizeField(
    2170             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2171             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2172           4 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2173           4 : }
    2174             : 
    2175             : ////////////////////////////////////////////////////////////////////////////////
    2176             : // A set of tests checking split map deprecation.
    2177             : //
    2178             : 
    2179       26067 : TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
    2180           4 :   CcTest::InitializeVM();
    2181           8 :   v8::HandleScope scope(CcTest::isolate());
    2182             :   Isolate* isolate = CcTest::i_isolate();
    2183             : 
    2184           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2185             : 
    2186           4 :   Expectations expectations(isolate);
    2187             : 
    2188             :   // Create a map, add required properties to it and initialize expectations.
    2189           4 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    2190           4 :   Handle<Map> map = initial_map;
    2191          60 :   for (int i = 0; i < kPropCount; i++) {
    2192             :     map = expectations.AddDataField(map, NONE, PropertyConstness::kMutable,
    2193          28 :                                     Representation::Smi(), any_type);
    2194             :   }
    2195           4 :   CHECK(!map->is_deprecated());
    2196           4 :   CHECK(map->is_stable());
    2197             : 
    2198             :   // Generalize representation of property at index |kSplitProp|.
    2199             :   const int kSplitProp = kPropCount / 2;
    2200             :   Handle<Map> split_map;
    2201             :   Handle<Map> map2 = initial_map;
    2202             :   {
    2203          36 :     for (int i = 0; i < kSplitProp + 1; i++) {
    2204          16 :       if (i == kSplitProp) {
    2205             :         split_map = map2;
    2206             :       }
    2207             : 
    2208          16 :       Handle<String> name = MakeName("prop", i);
    2209             :       Map target = TransitionsAccessor(isolate, map2)
    2210          32 :                        .SearchTransition(*name, kData, NONE);
    2211          16 :       CHECK(!target.is_null());
    2212             :       map2 = handle(target, isolate);
    2213             :     }
    2214             : 
    2215             :     map2 = Map::ReconfigureProperty(isolate, map2, kSplitProp, kData, NONE,
    2216           4 :                                     Representation::Double(), any_type);
    2217             :     expectations.SetDataField(kSplitProp, PropertyConstness::kMutable,
    2218             :                               Representation::Double(), any_type);
    2219             : 
    2220           4 :     CHECK(expectations.Check(*split_map, kSplitProp));
    2221           4 :     CHECK(expectations.Check(*map2, kSplitProp + 1));
    2222             :   }
    2223             : 
    2224             :   // At this point |map| should be deprecated and disconnected from the
    2225             :   // transition tree.
    2226           4 :   CHECK(map->is_deprecated());
    2227           4 :   CHECK(!split_map->is_deprecated());
    2228           4 :   CHECK(map2->is_stable());
    2229           4 :   CHECK(!map2->is_deprecated());
    2230             : 
    2231             :   // Fill in transition tree of |map2| so that it can't have more transitions.
    2232       12292 :   for (int i = 0; i < TransitionsAccessor::kMaxNumberOfTransitions; i++) {
    2233        6144 :     CHECK(TransitionsAccessor(isolate, map2).CanHaveMoreTransitions());
    2234        6144 :     Handle<String> name = MakeName("foo", i);
    2235       12288 :     Map::CopyWithField(isolate, map2, name, any_type, NONE,
    2236             :                        PropertyConstness::kMutable, Representation::Smi(),
    2237        6144 :                        INSERT_TRANSITION)
    2238             :         .ToHandleChecked();
    2239             :   }
    2240           4 :   CHECK(!TransitionsAccessor(isolate, map2).CanHaveMoreTransitions());
    2241             : 
    2242             :   // Try to update |map|, since there is no place for propX transition at |map2|
    2243             :   // |map| should become "copy-generalized".
    2244           4 :   Handle<Map> updated_map = Map::Update(isolate, map);
    2245           8 :   CHECK(updated_map->GetBackPointer()->IsUndefined(isolate));
    2246             : 
    2247          60 :   for (int i = 0; i < kPropCount; i++) {
    2248             :     expectations.SetDataField(i, PropertyConstness::kMutable,
    2249             :                               Representation::Tagged(), any_type);
    2250             :   }
    2251           4 :   CHECK(expectations.Check(*updated_map));
    2252           4 : }
    2253             : 
    2254             : 
    2255             : ////////////////////////////////////////////////////////////////////////////////
    2256             : // A set of tests involving special transitions (such as elements kind
    2257             : // transition, observed transition or prototype transition).
    2258             : //
    2259             : 
    2260             : // This test ensures that field generalization is correctly propagated from one
    2261             : // branch of transition tree (|map2|) to another (|map|).
    2262             : //
    2263             : //                            p4B: |map2|
    2264             : //                             |
    2265             : //                             * - special transition
    2266             : //                             |
    2267             : //  {} - p0 - p1 - p2A - p3 - p4A: |map|
    2268             : //
    2269             : // where "p4A" and "p4B" are exactly the same properties.
    2270             : //
    2271             : // TODO(ishell): unify this test template with
    2272             : // TestReconfigureDataFieldAttribute_GeneralizeField once
    2273             : // IS_PROTO_TRANS_ISSUE_FIXED and IS_NON_EQUIVALENT_TRANSITION_SUPPORTED are
    2274             : // fixed.
    2275             : template <typename TestConfig>
    2276          32 : static void TestGeneralizeFieldWithSpecialTransition(TestConfig& config,
    2277             :                                                      const CRFTData& from,
    2278             :                                                      const CRFTData& to,
    2279             :                                                      const CRFTData& expected) {
    2280             :   Isolate* isolate = CcTest::i_isolate();
    2281             : 
    2282          32 :   Expectations expectations(isolate);
    2283             : 
    2284             :   // Create a map, add required properties to it and initialize expectations.
    2285          32 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    2286          32 :   Handle<Map> map = initial_map;
    2287         480 :   for (int i = 0; i < kPropCount; i++) {
    2288         224 :     map = expectations.AddDataField(map, NONE, from.constness,
    2289             :                                     from.representation, from.type);
    2290             :   }
    2291          32 :   CHECK(!map->is_deprecated());
    2292          32 :   CHECK(map->is_stable());
    2293          32 :   CHECK(expectations.Check(*map));
    2294             : 
    2295          32 :   Expectations expectations2 = expectations;
    2296             : 
    2297             :   // Apply some special transition to |map|.
    2298          32 :   CHECK(map->owns_descriptors());
    2299          32 :   Handle<Map> map2 = config.Transition(map, expectations2);
    2300             : 
    2301             :   // |map| should still match expectations.
    2302          32 :   CHECK(!map->is_deprecated());
    2303          32 :   CHECK(expectations.Check(*map));
    2304             : 
    2305             :   if (config.generalizes_representations()) {
    2306         120 :     for (int i = 0; i < kPropCount; i++) {
    2307          56 :       expectations2.GeneralizeField(i);
    2308             :     }
    2309             :   }
    2310             : 
    2311          32 :   CHECK(!map2->is_deprecated());
    2312          32 :   CHECK(map2->is_stable());
    2313          32 :   CHECK(expectations2.Check(*map2));
    2314             : 
    2315             :   // Create new maps by generalizing representation of propX field.
    2316         480 :   Handle<Map> maps[kPropCount];
    2317         480 :   for (int i = 0; i < kPropCount; i++) {
    2318             :     Handle<Map> new_map = Map::ReconfigureProperty(isolate, map, i, kData, NONE,
    2319         224 :                                                    to.representation, to.type);
    2320         224 :     maps[i] = new_map;
    2321             : 
    2322         224 :     expectations.SetDataField(i, expected.constness, expected.representation,
    2323             :                               expected.type);
    2324             : 
    2325         224 :     CHECK(map->is_deprecated());
    2326         224 :     CHECK_NE(*map, *new_map);
    2327         416 :     CHECK(i == 0 || maps[i - 1]->is_deprecated());
    2328         224 :     CHECK(expectations.Check(*new_map));
    2329             : 
    2330         224 :     Handle<Map> new_map2 = Map::Update(isolate, map2);
    2331         224 :     CHECK(!new_map2->is_deprecated());
    2332         224 :     CHECK(!new_map2->is_dictionary_map());
    2333             : 
    2334             :     Handle<Map> tmp_map;
    2335         448 :     if (Map::TryUpdate(isolate, map2).ToHandle(&tmp_map)) {
    2336             :       // If Map::TryUpdate() manages to succeed the result must match the result
    2337             :       // of Map::Update().
    2338         224 :       CHECK_EQ(*new_map2, *tmp_map);
    2339             :     } else {
    2340             :       // Equivalent transitions should always find the updated map.
    2341           0 :       CHECK(config.is_non_equivalent_transition());
    2342             :     }
    2343             : 
    2344             :     if (config.is_non_equivalent_transition()) {
    2345             :       // In case of non-equivalent transition currently we generalize all
    2346             :       // representations.
    2347         840 :       for (int i = 0; i < kPropCount; i++) {
    2348         392 :         expectations2.GeneralizeField(i);
    2349             :       }
    2350         112 :       CHECK(new_map2->GetBackPointer()->IsUndefined(isolate));
    2351          56 :       CHECK(expectations2.Check(*new_map2));
    2352             :     } else {
    2353         168 :       expectations2.SetDataField(i, expected.constness, expected.representation,
    2354             :                                  expected.type);
    2355             : 
    2356         336 :       CHECK(!new_map2->GetBackPointer()->IsUndefined(isolate));
    2357         168 :       CHECK(expectations2.Check(*new_map2));
    2358             :     }
    2359             :   }
    2360             : 
    2361          32 :   Handle<Map> active_map = maps[kPropCount - 1];
    2362          32 :   CHECK(!active_map->is_deprecated());
    2363             : 
    2364             :   // Update all deprecated maps and check that they are now the same.
    2365          32 :   Handle<Map> updated_map = Map::Update(isolate, map);
    2366          32 :   CHECK_EQ(*active_map, *updated_map);
    2367          32 :   CheckMigrationTarget(isolate, *map, *updated_map);
    2368         480 :   for (int i = 0; i < kPropCount; i++) {
    2369         224 :     updated_map = Map::Update(isolate, maps[i]);
    2370         224 :     CHECK_EQ(*active_map, *updated_map);
    2371         448 :     CheckMigrationTarget(isolate, *maps[i], *updated_map);
    2372             :   }
    2373          32 : }
    2374             : 
    2375             : 
    2376       26067 : TEST(ElementsKindTransitionFromMapOwningDescriptor) {
    2377           4 :   CcTest::InitializeVM();
    2378           8 :   v8::HandleScope scope(CcTest::isolate());
    2379             :   Isolate* isolate = CcTest::i_isolate();
    2380             : 
    2381           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2382             :   Handle<FieldType> value_type =
    2383           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2384             : 
    2385             :   struct TestConfig {
    2386             :     TestConfig(PropertyAttributes attributes, Handle<Symbol> symbol)
    2387          12 :         : attributes(attributes), symbol(symbol) {}
    2388             : 
    2389          12 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2390             :       expectations.SetElementsKind(DICTIONARY_ELEMENTS);
    2391          12 :       expectations.ChangeAttributesForAllProperties(attributes);
    2392             :       return Map::CopyForPreventExtensions(CcTest::i_isolate(), map, attributes,
    2393          24 :                                            symbol, "CopyForPreventExtensions");
    2394             :     }
    2395             :     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
    2396             :     bool generalizes_representations() const { return false; }
    2397             :     bool is_non_equivalent_transition() const { return false; }
    2398             : 
    2399             :     PropertyAttributes attributes;
    2400             :     Handle<Symbol> symbol;
    2401             :   };
    2402             :   Factory* factory = isolate->factory();
    2403             :   TestConfig configs[] = {{FROZEN, factory->frozen_symbol()},
    2404             :                           {SEALED, factory->sealed_symbol()},
    2405             :                           {NONE, factory->nonextensible_symbol()}};
    2406          28 :   for (size_t i = 0; i < arraysize(configs); i++) {
    2407          24 :     TestGeneralizeFieldWithSpecialTransition(
    2408             :         configs[i],
    2409             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2410             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2411          12 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2412             :   }
    2413           4 : }
    2414             : 
    2415             : 
    2416       26067 : TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
    2417           4 :   CcTest::InitializeVM();
    2418           8 :   v8::HandleScope scope(CcTest::isolate());
    2419             :   Isolate* isolate = CcTest::i_isolate();
    2420             : 
    2421           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2422             :   Handle<FieldType> value_type =
    2423           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2424             : 
    2425             :   struct TestConfig {
    2426             :     TestConfig(PropertyAttributes attributes, Handle<Symbol> symbol)
    2427          12 :         : attributes(attributes), symbol(symbol) {}
    2428             : 
    2429          12 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2430             :       Isolate* isolate = CcTest::i_isolate();
    2431          12 :       Handle<FieldType> any_type = FieldType::Any(isolate);
    2432             : 
    2433             :       // Add one more transition to |map| in order to prevent descriptors
    2434             :       // ownership.
    2435          12 :       CHECK(map->owns_descriptors());
    2436          24 :       Map::CopyWithField(isolate, map, MakeString("foo"), any_type, NONE,
    2437             :                          PropertyConstness::kMutable, Representation::Smi(),
    2438          12 :                          INSERT_TRANSITION)
    2439             :           .ToHandleChecked();
    2440          12 :       CHECK(!map->owns_descriptors());
    2441             : 
    2442             :       expectations.SetElementsKind(DICTIONARY_ELEMENTS);
    2443          12 :       expectations.ChangeAttributesForAllProperties(attributes);
    2444             :       return Map::CopyForPreventExtensions(isolate, map, attributes, symbol,
    2445          12 :                                            "CopyForPreventExtensions");
    2446             :     }
    2447             :     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
    2448             :     bool generalizes_representations() const { return false; }
    2449             :     bool is_non_equivalent_transition() const { return false; }
    2450             : 
    2451             :     PropertyAttributes attributes;
    2452             :     Handle<Symbol> symbol;
    2453             :   };
    2454             :   Factory* factory = isolate->factory();
    2455             :   TestConfig configs[] = {{FROZEN, factory->frozen_symbol()},
    2456             :                           {SEALED, factory->sealed_symbol()},
    2457             :                           {NONE, factory->nonextensible_symbol()}};
    2458          28 :   for (size_t i = 0; i < arraysize(configs); i++) {
    2459          24 :     TestGeneralizeFieldWithSpecialTransition(
    2460             :         configs[i],
    2461             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2462             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2463          12 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2464             :   }
    2465           4 : }
    2466             : 
    2467             : 
    2468       26067 : TEST(PrototypeTransitionFromMapOwningDescriptor) {
    2469           4 :   CcTest::InitializeVM();
    2470           8 :   v8::HandleScope scope(CcTest::isolate());
    2471             :   Isolate* isolate = CcTest::i_isolate();
    2472             : 
    2473           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2474             :   Handle<FieldType> value_type =
    2475           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2476             : 
    2477             :   struct TestConfig {
    2478             :     Handle<JSObject> prototype_;
    2479             : 
    2480           4 :     TestConfig() {
    2481             :       Isolate* isolate = CcTest::i_isolate();
    2482             :       Factory* factory = isolate->factory();
    2483           4 :       prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
    2484           4 :     }
    2485             : 
    2486           4 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2487           4 :       return Map::TransitionToPrototype(CcTest::i_isolate(), map, prototype_);
    2488             :     }
    2489             :     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
    2490             :     bool generalizes_representations() const {
    2491             :       return !IS_PROTO_TRANS_ISSUE_FIXED;
    2492             :     }
    2493             :     bool is_non_equivalent_transition() const { return true; }
    2494             :   };
    2495           4 :   TestConfig config;
    2496           8 :   TestGeneralizeFieldWithSpecialTransition(
    2497             :       config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2498             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2499           4 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2500           4 : }
    2501             : 
    2502             : 
    2503       26067 : TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
    2504           4 :   CcTest::InitializeVM();
    2505           8 :   v8::HandleScope scope(CcTest::isolate());
    2506             :   Isolate* isolate = CcTest::i_isolate();
    2507             : 
    2508           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2509             :   Handle<FieldType> value_type =
    2510           4 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2511             : 
    2512             :   struct TestConfig {
    2513             :     Handle<JSObject> prototype_;
    2514             : 
    2515           4 :     TestConfig() {
    2516             :       Isolate* isolate = CcTest::i_isolate();
    2517             :       Factory* factory = isolate->factory();
    2518           4 :       prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
    2519           4 :     }
    2520             : 
    2521           4 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2522             :       Isolate* isolate = CcTest::i_isolate();
    2523           4 :       Handle<FieldType> any_type = FieldType::Any(isolate);
    2524             : 
    2525             :       // Add one more transition to |map| in order to prevent descriptors
    2526             :       // ownership.
    2527           4 :       CHECK(map->owns_descriptors());
    2528           8 :       Map::CopyWithField(isolate, map, MakeString("foo"), any_type, NONE,
    2529             :                          PropertyConstness::kMutable, Representation::Smi(),
    2530           4 :                          INSERT_TRANSITION)
    2531             :           .ToHandleChecked();
    2532           4 :       CHECK(!map->owns_descriptors());
    2533             : 
    2534           4 :       return Map::TransitionToPrototype(isolate, map, prototype_);
    2535             :     }
    2536             :     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
    2537             :     bool generalizes_representations() const {
    2538             :       return !IS_PROTO_TRANS_ISSUE_FIXED;
    2539             :     }
    2540             :     bool is_non_equivalent_transition() const { return true; }
    2541             :   };
    2542           4 :   TestConfig config;
    2543           8 :   TestGeneralizeFieldWithSpecialTransition(
    2544             :       config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2545             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2546           4 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2547           4 : }
    2548             : 
    2549             : 
    2550             : ////////////////////////////////////////////////////////////////////////////////
    2551             : // A set of tests for higher level transitioning mechanics.
    2552             : //
    2553             : 
    2554             : struct TransitionToDataFieldOperator {
    2555             :   PropertyConstness constness_;
    2556             :   Representation representation_;
    2557             :   PropertyAttributes attributes_;
    2558             :   Handle<FieldType> heap_type_;
    2559             :   Handle<Object> value_;
    2560             : 
    2561             :   TransitionToDataFieldOperator(PropertyConstness constness,
    2562             :                                 Representation representation,
    2563             :                                 Handle<FieldType> heap_type,
    2564             :                                 Handle<Object> value,
    2565             :                                 PropertyAttributes attributes = NONE)
    2566             :       : constness_(constness),
    2567             :         representation_(representation),
    2568             :         attributes_(attributes),
    2569             :         heap_type_(heap_type),
    2570          12 :         value_(value) {}
    2571             : 
    2572             :   Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
    2573             :     return expectations.TransitionToDataField(
    2574          12 :         map, attributes_, constness_, representation_, heap_type_, value_);
    2575             :   }
    2576             : };
    2577             : 
    2578             : 
    2579             : struct TransitionToDataConstantOperator {
    2580             :   PropertyAttributes attributes_;
    2581             :   Handle<JSFunction> value_;
    2582             : 
    2583             :   TransitionToDataConstantOperator(Handle<JSFunction> value,
    2584             :                                    PropertyAttributes attributes = NONE)
    2585          16 :       : attributes_(attributes), value_(value) {}
    2586             : 
    2587             :   Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
    2588          20 :     return expectations.TransitionToDataConstant(map, attributes_, value_);
    2589             :   }
    2590             : };
    2591             : 
    2592             : 
    2593             : struct TransitionToAccessorConstantOperator {
    2594             :   PropertyAttributes attributes_;
    2595             :   Handle<AccessorPair> pair_;
    2596             : 
    2597             :   TransitionToAccessorConstantOperator(Handle<AccessorPair> pair,
    2598             :                                        PropertyAttributes attributes = NONE)
    2599           4 :       : attributes_(attributes), pair_(pair) {}
    2600             : 
    2601             :   Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
    2602           8 :     return expectations.TransitionToAccessorConstant(map, attributes_, pair_);
    2603             :   }
    2604             : };
    2605             : 
    2606             : 
    2607             : struct ReconfigureAsDataPropertyOperator {
    2608             :   int descriptor_;
    2609             :   Representation representation_;
    2610             :   PropertyAttributes attributes_;
    2611             :   Handle<FieldType> heap_type_;
    2612             : 
    2613             :   ReconfigureAsDataPropertyOperator(int descriptor,
    2614             :                                     Representation representation,
    2615             :                                     Handle<FieldType> heap_type,
    2616             :                                     PropertyAttributes attributes = NONE)
    2617             :       : descriptor_(descriptor),
    2618             :         representation_(representation),
    2619             :         attributes_(attributes),
    2620             :         heap_type_(heap_type) {}
    2621             : 
    2622             :   Handle<Map> DoTransition(Isolate* isolate, Expectations& expectations,
    2623             :                            Handle<Map> map) {
    2624             :     expectations.SetDataField(descriptor_, PropertyConstness::kMutable,
    2625             :                               representation_, heap_type_);
    2626             :     return Map::ReconfigureExistingProperty(isolate, map, descriptor_, kData,
    2627             :                                             attributes_);
    2628             :   }
    2629             : };
    2630             : 
    2631             : 
    2632             : struct ReconfigureAsAccessorPropertyOperator {
    2633             :   int descriptor_;
    2634             :   PropertyAttributes attributes_;
    2635             : 
    2636             :   ReconfigureAsAccessorPropertyOperator(int descriptor,
    2637             :                                         PropertyAttributes attributes = NONE)
    2638             :       : descriptor_(descriptor), attributes_(attributes) {}
    2639             : 
    2640             :   Handle<Map> DoTransition(Isolate* isolate, Expectations& expectations,
    2641             :                            Handle<Map> map) {
    2642             :     expectations.SetAccessorField(descriptor_);
    2643             :     return Map::ReconfigureExistingProperty(isolate, map, descriptor_,
    2644             :                                             kAccessor, attributes_);
    2645             :   }
    2646             : };
    2647             : 
    2648             : // Checks that field generalization happened.
    2649             : struct FieldGeneralizationChecker {
    2650             :   int descriptor_;
    2651             :   PropertyConstness constness_;
    2652             :   Representation representation_;
    2653             :   PropertyAttributes attributes_;
    2654             :   Handle<FieldType> heap_type_;
    2655             : 
    2656             :   FieldGeneralizationChecker(int descriptor, PropertyConstness constness,
    2657             :                              Representation representation,
    2658             :                              Handle<FieldType> heap_type,
    2659             :                              PropertyAttributes attributes = NONE)
    2660             :       : descriptor_(descriptor),
    2661             :         constness_(constness),
    2662             :         representation_(representation),
    2663             :         attributes_(attributes),
    2664           8 :         heap_type_(heap_type) {}
    2665             : 
    2666           8 :   void Check(Isolate* isolate, Expectations& expectations2, Handle<Map> map1,
    2667             :              Handle<Map> map2) {
    2668           8 :     CHECK(!map2->is_deprecated());
    2669             : 
    2670           8 :     CHECK(map1->is_deprecated());
    2671           8 :     CHECK_NE(*map1, *map2);
    2672           8 :     Handle<Map> updated_map = Map::Update(isolate, map1);
    2673           8 :     CHECK_EQ(*map2, *updated_map);
    2674           8 :     CheckMigrationTarget(isolate, *map1, *updated_map);
    2675             : 
    2676           8 :     expectations2.SetDataField(descriptor_, attributes_, constness_,
    2677             :                                representation_, heap_type_);
    2678           8 :     CHECK(expectations2.Check(*map2));
    2679           8 :   }
    2680             : };
    2681             : 
    2682             : 
    2683             : // Checks that existing transition was taken as is.
    2684             : struct SameMapChecker {
    2685          12 :   void Check(Isolate* isolate, Expectations& expectations, Handle<Map> map1,
    2686             :              Handle<Map> map2) {
    2687          12 :     CHECK(!map2->is_deprecated());
    2688          12 :     CHECK_EQ(*map1, *map2);
    2689          12 :     CHECK(expectations.Check(*map2));
    2690          12 :   }
    2691             : };
    2692             : 
    2693             : 
    2694             : // Checks that both |map1| and |map2| should stays non-deprecated, this is
    2695             : // the case when property kind is change.
    2696             : struct PropertyKindReconfigurationChecker {
    2697             :   void Check(Expectations& expectations, Handle<Map> map1, Handle<Map> map2) {
    2698             :     CHECK(!map1->is_deprecated());
    2699             :     CHECK(!map2->is_deprecated());
    2700             :     CHECK_NE(*map1, *map2);
    2701             :     CHECK(expectations.Check(*map2));
    2702             :   }
    2703             : };
    2704             : 
    2705             : 
    2706             : // This test transitions to various property types under different
    2707             : // circumstances.
    2708             : // Plan:
    2709             : // 1) create a |map| with p0..p3 properties.
    2710             : // 2) create |map1| by adding "p4" to |map0|.
    2711             : // 3) create |map2| by transition to "p4" from |map0|.
    2712             : //
    2713             : //                       + - p4B: |map2|
    2714             : //                       |
    2715             : //  {} - p0 - p1 - pA - p3: |map|
    2716             : //                       |
    2717             : //                       + - p4A: |map1|
    2718             : //
    2719             : // where "p4A" and "p4B" differ only in the attributes.
    2720             : //
    2721             : template <typename TransitionOp1, typename TransitionOp2, typename Checker>
    2722          20 : static void TestTransitionTo(TransitionOp1& transition_op1,
    2723             :                              TransitionOp2& transition_op2, Checker& checker) {
    2724             :   Isolate* isolate = CcTest::i_isolate();
    2725          20 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2726             : 
    2727          20 :   Expectations expectations(isolate);
    2728             : 
    2729             :   // Create a map, add required properties to it and initialize expectations.
    2730          20 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    2731          20 :   Handle<Map> map = initial_map;
    2732         260 :   for (int i = 0; i < kPropCount - 1; i++) {
    2733         120 :     map = expectations.AddDataField(map, NONE, PropertyConstness::kMutable,
    2734             :                                     Representation::Smi(), any_type);
    2735             :   }
    2736          20 :   CHECK(expectations.Check(*map));
    2737             : 
    2738          20 :   Expectations expectations1 = expectations;
    2739             :   Handle<Map> map1 = transition_op1.DoTransition(expectations1, map);
    2740          20 :   CHECK(expectations1.Check(*map1));
    2741             : 
    2742          20 :   Expectations expectations2 = expectations;
    2743          20 :   Handle<Map> map2 = transition_op2.DoTransition(expectations2, map);
    2744             : 
    2745             :   // Let the test customization do the check.
    2746          20 :   checker.Check(isolate, expectations2, map1, map2);
    2747          20 : }
    2748             : 
    2749             : 
    2750       26067 : TEST(TransitionDataFieldToDataField) {
    2751           4 :   CcTest::InitializeVM();
    2752           8 :   v8::HandleScope scope(CcTest::isolate());
    2753             :   Isolate* isolate = CcTest::i_isolate();
    2754             : 
    2755           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2756             : 
    2757             :   Handle<Object> value1 = handle(Smi::kZero, isolate);
    2758             :   TransitionToDataFieldOperator transition_op1(
    2759             :       PropertyConstness::kMutable, Representation::Smi(), any_type, value1);
    2760             : 
    2761           4 :   Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
    2762             :   TransitionToDataFieldOperator transition_op2(
    2763             :       PropertyConstness::kMutable, Representation::Double(), any_type, value2);
    2764             : 
    2765             :   FieldGeneralizationChecker checker(kPropCount - 1,
    2766             :                                      PropertyConstness::kMutable,
    2767             :                                      Representation::Double(), any_type);
    2768           4 :   TestTransitionTo(transition_op1, transition_op2, checker);
    2769           4 : }
    2770             : 
    2771       26067 : TEST(TransitionDataConstantToSameDataConstant) {
    2772           4 :   CcTest::InitializeVM();
    2773           8 :   v8::HandleScope scope(CcTest::isolate());
    2774             :   Isolate* isolate = CcTest::i_isolate();
    2775             :   Factory* factory = isolate->factory();
    2776             : 
    2777             :   Handle<JSFunction> js_func =
    2778           4 :       factory->NewFunctionForTest(factory->empty_string());
    2779             :   TransitionToDataConstantOperator transition_op(js_func);
    2780             : 
    2781             :   SameMapChecker checker;
    2782           4 :   TestTransitionTo(transition_op, transition_op, checker);
    2783           4 : }
    2784             : 
    2785             : 
    2786       26067 : TEST(TransitionDataConstantToAnotherDataConstant) {
    2787           4 :   CcTest::InitializeVM();
    2788           8 :   v8::HandleScope scope(CcTest::isolate());
    2789             :   Isolate* isolate = CcTest::i_isolate();
    2790             :   Factory* factory = isolate->factory();
    2791             : 
    2792             :   Handle<String> name = factory->empty_string();
    2793             :   Handle<Map> sloppy_map =
    2794           4 :       Map::CopyInitialMap(isolate, isolate->sloppy_function_map());
    2795             :   Handle<SharedFunctionInfo> info =
    2796           4 :       factory->NewSharedFunctionInfoForBuiltin(name, Builtins::kIllegal);
    2797           4 :   Handle<FieldType> function_type = FieldType::Class(sloppy_map, isolate);
    2798           4 :   CHECK(sloppy_map->is_stable());
    2799             : 
    2800             :   Handle<JSFunction> js_func1 =
    2801           8 :       factory->NewFunction(sloppy_map, info, isolate->native_context());
    2802             :   TransitionToDataConstantOperator transition_op1(js_func1);
    2803             : 
    2804             :   Handle<JSFunction> js_func2 =
    2805           8 :       factory->NewFunction(sloppy_map, info, isolate->native_context());
    2806             :   TransitionToDataConstantOperator transition_op2(js_func2);
    2807             : 
    2808             :   if (FLAG_track_constant_fields) {
    2809             :     SameMapChecker checker;
    2810           4 :     TestTransitionTo(transition_op1, transition_op2, checker);
    2811             : 
    2812             :   } else {
    2813             :     FieldGeneralizationChecker checker(
    2814             :         kPropCount - 1, PropertyConstness::kMutable,
    2815             :         Representation::HeapObject(), function_type);
    2816             :     TestTransitionTo(transition_op1, transition_op2, checker);
    2817             :   }
    2818           4 : }
    2819             : 
    2820             : 
    2821       26067 : TEST(TransitionDataConstantToDataField) {
    2822           4 :   CcTest::InitializeVM();
    2823           8 :   v8::HandleScope scope(CcTest::isolate());
    2824             :   Isolate* isolate = CcTest::i_isolate();
    2825             :   Factory* factory = isolate->factory();
    2826             : 
    2827           4 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2828             : 
    2829             :   Handle<JSFunction> js_func1 =
    2830           4 :       factory->NewFunctionForTest(factory->empty_string());
    2831             :   TransitionToDataConstantOperator transition_op1(js_func1);
    2832             : 
    2833           4 :   Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
    2834             :   TransitionToDataFieldOperator transition_op2(
    2835             :       PropertyConstness::kMutable, Representation::Double(), any_type, value2);
    2836             : 
    2837             :   FieldGeneralizationChecker checker(kPropCount - 1,
    2838             :                                      PropertyConstness::kMutable,
    2839             :                                      Representation::Tagged(), any_type);
    2840           4 :   TestTransitionTo(transition_op1, transition_op2, checker);
    2841           4 : }
    2842             : 
    2843             : 
    2844       26067 : TEST(TransitionAccessorConstantToSameAccessorConstant) {
    2845           4 :   CcTest::InitializeVM();
    2846           8 :   v8::HandleScope scope(CcTest::isolate());
    2847             : 
    2848           4 :   Handle<AccessorPair> pair = CreateAccessorPair(true, true);
    2849             :   TransitionToAccessorConstantOperator transition_op(pair);
    2850             : 
    2851             :   SameMapChecker checker;
    2852           4 :   TestTransitionTo(transition_op, transition_op, checker);
    2853           4 : }
    2854             : 
    2855             : // TODO(ishell): add this test once IS_ACCESSOR_FIELD_SUPPORTED is supported.
    2856             : // TEST(TransitionAccessorConstantToAnotherAccessorConstant)
    2857             : 
    2858       26067 : TEST(HoleyMutableHeapNumber) {
    2859           4 :   CcTest::InitializeVM();
    2860           8 :   v8::HandleScope scope(CcTest::isolate());
    2861             :   Isolate* isolate = CcTest::i_isolate();
    2862             : 
    2863             :   auto mhn = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
    2864           4 :   CHECK_EQ(kHoleNanInt64, mhn->value_as_bits());
    2865             : 
    2866           4 :   mhn = isolate->factory()->NewMutableHeapNumber(0.0);
    2867           4 :   CHECK_EQ(uint64_t{0}, mhn->value_as_bits());
    2868             : 
    2869             :   mhn->set_value_as_bits(kHoleNanInt64);
    2870           4 :   CHECK_EQ(kHoleNanInt64, mhn->value_as_bits());
    2871             : 
    2872             :   // Ensure that new storage for uninitialized value or mutable heap number
    2873             :   // with uninitialized sentinel (kHoleNanInt64) is a mutable heap number
    2874             :   // with uninitialized sentinel.
    2875             :   Handle<Object> obj =
    2876             :       Object::NewStorageFor(isolate, isolate->factory()->uninitialized_value(),
    2877           4 :                             Representation::Double());
    2878           4 :   CHECK(obj->IsMutableHeapNumber());
    2879           4 :   CHECK_EQ(kHoleNanInt64, MutableHeapNumber::cast(*obj)->value_as_bits());
    2880             : 
    2881           4 :   obj = Object::NewStorageFor(isolate, mhn, Representation::Double());
    2882           4 :   CHECK(obj->IsMutableHeapNumber());
    2883           4 :   CHECK_EQ(kHoleNanInt64, MutableHeapNumber::cast(*obj)->value_as_bits());
    2884           4 : }
    2885             : 
    2886             : }  // namespace test_field_type_tracking
    2887             : }  // namespace compiler
    2888             : }  // namespace internal
    2889       78189 : }  // namespace v8

Generated by: LCOV version 1.10