LCOV - code coverage report
Current view: top level - test/cctest - test-field-type-tracking.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1039 1067 97.4 %
Date: 2019-02-19 Functions: 104 105 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       13465 :   return factory->InternalizeUtf8String(str);
      57             : }
      58             : 
      59             : 
      60       13445 : static Handle<String> MakeName(const char* str, int suffix) {
      61             :   EmbeddedVector<char, 128> buffer;
      62       13445 :   SNPrintF(buffer, "%s%d", str, suffix);
      63       26890 :   return MakeString(buffer.start());
      64             : }
      65             : 
      66             : 
      67          40 : static Handle<AccessorPair> CreateAccessorPair(bool with_getter,
      68             :                                                bool with_setter) {
      69             :   Isolate* isolate = CcTest::i_isolate();
      70             :   Factory* factory = isolate->factory();
      71          40 :   Handle<AccessorPair> pair = factory->NewAccessorPair();
      72          40 :   Handle<String> empty_string = factory->empty_string();
      73          40 :   if (with_getter) {
      74          40 :     Handle<JSFunction> func = factory->NewFunctionForTest(empty_string);
      75          80 :     pair->set_getter(*func);
      76             :   }
      77          40 :   if (with_setter) {
      78          40 :     Handle<JSFunction> func = factory->NewFunctionForTest(empty_string);
      79          80 :     pair->set_setter(*func);
      80             :   }
      81          40 :   return pair;
      82             : }
      83             : 
      84             : // Check cached migration target map after Map::Update() and Map::TryUpdate()
      85         755 : static void CheckMigrationTarget(Isolate* isolate, Map old_map, Map new_map) {
      86             :   Map target = TransitionsAccessor(isolate, handle(old_map, isolate))
      87         755 :                    .GetMigrationTarget();
      88        1510 :   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         800 :   explicit Expectations(Isolate* isolate, ElementsKind elements_kind)
     111             :       : isolate_(isolate),
     112             :         elements_kind_(elements_kind),
     113       24800 :         number_of_properties_(0) {}
     114             : 
     115         560 :   explicit Expectations(Isolate* isolate)
     116             :       : Expectations(
     117             :             isolate,
     118        1680 :             isolate->object_function()->initial_map()->elements_kind()) {}
     119             : 
     120        7175 :   void Init(int index, PropertyKind kind, PropertyAttributes attributes,
     121             :             PropertyConstness constness, PropertyLocation location,
     122             :             Representation representation, Handle<Object> value) {
     123        7175 :     CHECK(index < MAX_PROPERTIES);
     124        7175 :     kinds_[index] = kind;
     125        7175 :     locations_[index] = location;
     126       14295 :     if (kind == kData && location == kField &&
     127        7120 :         IsTransitionableFastElementsKind(elements_kind_)) {
     128             :       // Maps with transitionable elements kinds must have the most general
     129             :       // field type.
     130        1800 :       value = FieldType::Any(isolate_);
     131             :     }
     132        7175 :     constnesses_[index] = constness;
     133        7175 :     attributes_[index] = attributes;
     134        7175 :     representations_[index] = representation;
     135        7175 :     values_[index] = value;
     136        7175 :   }
     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           0 :         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          30 :     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        7070 :     Init(index, kData, attrs, constness, kField, representation, field_type);
     181             :   }
     182             : 
     183        1405 :   void SetDataField(int index, PropertyConstness constness,
     184             :                     Representation representation,
     185             :                     Handle<FieldType> field_type) {
     186             :     SetDataField(index, attributes_[index], constness, representation,
     187        1405 :                  field_type);
     188        1405 :   }
     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          50 :   void SetDataConstant(int index, PropertyAttributes attrs,
     200             :                        Handle<JSFunction> value) {
     201             :     if (FLAG_track_constant_fields) {
     202         100 :       Handle<FieldType> field_type(FieldType::Class(value->map()), isolate_);
     203             :       Init(index, kData, attrs, PropertyConstness::kConst, kField,
     204          50 :            Representation::HeapObject(), field_type);
     205             : 
     206             :     } else {
     207             :       Init(index, kData, attrs, PropertyConstness::kConst, kDescriptor,
     208             :            Representation::HeapObject(), value);
     209             :     }
     210          50 :   }
     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          55 :          Representation::Tagged(), getter);
     220          55 :     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          50 :   void SetAccessorConstant(int index, PropertyAttributes attrs,
     237             :                            Handle<AccessorPair> pair) {
     238          50 :     Handle<Object> getter = handle(pair->getter(), isolate_);
     239          50 :     Handle<Object> setter = handle(pair->setter(), isolate_);
     240             :     SetAccessorConstant(index, attrs, getter, setter);
     241          50 :   }
     242             : 
     243           5 :   void SetAccessorConstant(int index, Handle<Object> getter,
     244             :                            Handle<Object> setter) {
     245           5 :     SetAccessorConstant(index, attributes_[index], getter, setter);
     246           5 :   }
     247             : 
     248           5 :   void SetAccessorConstant(int index, Handle<AccessorPair> pair) {
     249          10 :     Handle<Object> getter = handle(pair->getter(), isolate_);
     250          10 :     Handle<Object> setter = handle(pair->setter(), isolate_);
     251           5 :     SetAccessorConstant(index, getter, setter);
     252           5 :   }
     253             : 
     254         595 :   void GeneralizeField(int index) {
     255         595 :     CHECK(index < number_of_properties_);
     256         595 :     representations_[index] = Representation::Tagged();
     257         595 :     if (locations_[index] == kField) {
     258         590 :       values_[index] = FieldType::Any(isolate_);
     259             :     }
     260         595 :   }
     261             : 
     262       16395 :   bool Check(DescriptorArray descriptors, int descriptor) const {
     263       16395 :     PropertyDetails details = descriptors->GetDetails(descriptor);
     264             : 
     265       16395 :     if (details.kind() != kinds_[descriptor]) return false;
     266       16395 :     if (details.location() != locations_[descriptor]) return false;
     267       16395 :     if (details.constness() != constnesses_[descriptor]) return false;
     268             : 
     269       16395 :     PropertyAttributes expected_attributes = attributes_[descriptor];
     270       16395 :     if (details.attributes() != expected_attributes) return false;
     271             : 
     272       16395 :     Representation expected_representation = representations_[descriptor];
     273             : 
     274       16395 :     if (!details.representation().Equals(expected_representation)) return false;
     275             : 
     276       16395 :     Object expected_value = *values_[descriptor];
     277       16395 :     if (details.location() == kField) {
     278       16280 :       if (details.kind() == kData) {
     279       16280 :         FieldType type = descriptors->GetFieldType(descriptor);
     280       32560 :         return FieldType::cast(expected_value) == type;
     281             :       } else {
     282             :         // kAccessor
     283           0 :         UNREACHABLE();
     284             :       }
     285             :     } else {
     286         115 :       Object value = descriptors->GetStrongValue(descriptor);
     287             :       // kDescriptor
     288         115 :       if (details.kind() == kData) {
     289           0 :         CHECK(!FLAG_track_constant_fields);
     290             :         return value == expected_value;
     291             :       } else {
     292             :         // kAccessor
     293         115 :         if (value == expected_value) return true;
     294         115 :         if (!value->IsAccessorPair()) return false;
     295             :         AccessorPair pair = AccessorPair::cast(value);
     296         230 :         return pair->Equals(expected_value, *setter_values_[descriptor]);
     297             :       }
     298             :     }
     299             :     UNREACHABLE();
     300             :   }
     301             : 
     302        2415 :   bool Check(Map map, int expected_nof) const {
     303        2415 :     CHECK_EQ(elements_kind_, map->elements_kind());
     304        2415 :     CHECK(number_of_properties_ <= MAX_PROPERTIES);
     305        2415 :     CHECK_EQ(expected_nof, map->NumberOfOwnDescriptors());
     306        2415 :     CHECK(!map->is_dictionary_map());
     307             : 
     308        2415 :     DescriptorArray descriptors = map->instance_descriptors();
     309        2415 :     CHECK(expected_nof <= number_of_properties_);
     310       16395 :     for (int i = 0; i < expected_nof; i++) {
     311       16395 :       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        2345 :   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         120 :   Handle<Map> AsElementsKind(Handle<Map> map, ElementsKind elements_kind) {
     331         120 :     elements_kind_ = elements_kind;
     332         120 :     map = Map::AsElementsKind(isolate_, map, elements_kind);
     333         120 :     CHECK_EQ(elements_kind_, map->elements_kind());
     334         120 :     return map;
     335             :   }
     336             : 
     337             :   void ChangeAttributesForAllProperties(PropertyAttributes attributes) {
     338         210 :     for (int i = 0; i < number_of_properties_; i++) {
     339         210 :       attributes_[i] = attributes;
     340             :     }
     341             :   }
     342             : 
     343        5315 :   Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
     344             :                            PropertyConstness constness,
     345             :                            Representation representation,
     346             :                            Handle<FieldType> field_type) {
     347        5315 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     348        5315 :     int property_index = number_of_properties_++;
     349             :     SetDataField(property_index, attributes, constness, representation,
     350             :                  field_type);
     351             : 
     352        5315 :     Handle<String> name = MakeName("prop", property_index);
     353             :     return Map::CopyWithField(isolate_, map, name, field_type, attributes,
     354       10630 :                               constness, representation, INSERT_TRANSITION)
     355       15945 :         .ToHandleChecked();
     356             :   }
     357             : 
     358          25 :   Handle<Map> AddDataConstant(Handle<Map> map, PropertyAttributes attributes,
     359             :                               Handle<JSFunction> value) {
     360          25 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     361          25 :     int property_index = number_of_properties_++;
     362          25 :     SetDataConstant(property_index, attributes, value);
     363             : 
     364          25 :     Handle<String> name = MakeName("prop", property_index);
     365             :     return Map::CopyWithConstant(isolate_, map, name, value, attributes,
     366          50 :                                  INSERT_TRANSITION)
     367          75 :         .ToHandleChecked();
     368             :   }
     369             : 
     370          15 :   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          15 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     377          15 :     int property_index = number_of_properties_++;
     378             :     SetDataField(property_index, attributes, constness, representation,
     379             :                  heap_type);
     380             : 
     381          15 :     Handle<String> name = MakeName("prop", property_index);
     382             :     return Map::TransitionToDataProperty(isolate_, map, name, value, attributes,
     383          15 :                                          constness, StoreOrigin::kNamed);
     384             :   }
     385             : 
     386          25 :   Handle<Map> TransitionToDataConstant(Handle<Map> map,
     387             :                                        PropertyAttributes attributes,
     388             :                                        Handle<JSFunction> value) {
     389          25 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     390          25 :     int property_index = number_of_properties_++;
     391          25 :     SetDataConstant(property_index, attributes, value);
     392             : 
     393          25 :     Handle<String> name = MakeName("prop", property_index);
     394             :     return Map::TransitionToDataProperty(isolate_, map, name, value, attributes,
     395             :                                          PropertyConstness::kConst,
     396          25 :                                          StoreOrigin::kNamed);
     397             :   }
     398             : 
     399         315 :   Handle<Map> FollowDataTransition(Handle<Map> map,
     400             :                                    PropertyAttributes attributes,
     401             :                                    PropertyConstness constness,
     402             :                                    Representation representation,
     403             :                                    Handle<FieldType> heap_type) {
     404         315 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     405         315 :     int property_index = number_of_properties_++;
     406             :     SetDataField(property_index, attributes, constness, representation,
     407             :                  heap_type);
     408             : 
     409         315 :     Handle<String> name = MakeName("prop", property_index);
     410             :     Map target = TransitionsAccessor(isolate_, map)
     411         315 :                      .SearchTransition(*name, kData, attributes);
     412         315 :     CHECK(!target.is_null());
     413         630 :     return handle(target, isolate_);
     414             :   }
     415             : 
     416          40 :   Handle<Map> AddAccessorConstant(Handle<Map> map,
     417             :                                   PropertyAttributes attributes,
     418             :                                   Handle<AccessorPair> pair) {
     419          40 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     420          40 :     int property_index = number_of_properties_++;
     421          40 :     SetAccessorConstant(property_index, attributes, pair);
     422             : 
     423          40 :     Handle<String> name = MakeName("prop", property_index);
     424             : 
     425          40 :     Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
     426          40 :     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          10 :   Handle<Map> TransitionToAccessorConstant(Handle<Map> map,
     458             :                                            PropertyAttributes attributes,
     459             :                                            Handle<AccessorPair> pair) {
     460          10 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     461          10 :     int property_index = number_of_properties_++;
     462          10 :     SetAccessorConstant(property_index, attributes, pair);
     463             : 
     464          10 :     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          20 :         map->instance_descriptors()->SearchWithCache(isolate, *name, *map);
     472             :     map = Map::TransitionToAccessorProperty(isolate, map, name, descriptor,
     473          10 :                                             getter, setter, attributes);
     474          10 :     CHECK(!map->is_deprecated());
     475          10 :     CHECK(!map->is_dictionary_map());
     476          10 :     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       25880 : TEST(ReconfigureAccessorToNonExistingDataField) {
     487           5 :   CcTest::InitializeVM();
     488           5 :   v8::HandleScope scope(CcTest::isolate());
     489             :   Isolate* isolate = CcTest::i_isolate();
     490             : 
     491           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     492           5 :   Handle<FieldType> none_type = FieldType::None(isolate);
     493           5 :   Handle<AccessorPair> pair = CreateAccessorPair(true, true);
     494             : 
     495           5 :   Expectations expectations(isolate);
     496             : 
     497             :   // Create a map, add required properties to it and initialize expectations.
     498           5 :   Handle<Map> initial_map = Map::Create(isolate, 0);
     499           5 :   Handle<Map> map = initial_map;
     500           5 :   map = expectations.AddAccessorConstant(map, NONE, pair);
     501             : 
     502           5 :   CHECK(!map->is_deprecated());
     503           5 :   CHECK(map->is_stable());
     504           5 :   CHECK(expectations.Check(*map));
     505             : 
     506             :   Handle<Map> new_map = Map::ReconfigureProperty(
     507           5 :       isolate, map, 0, kData, NONE, Representation::None(), none_type);
     508             :   // |map| did not change except marked unstable.
     509           5 :   CHECK(!map->is_deprecated());
     510           5 :   CHECK(!map->is_stable());
     511           5 :   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           5 :   CHECK(!new_map->is_deprecated());
     518           5 :   CHECK(new_map->is_stable());
     519           5 :   CHECK(expectations.Check(*new_map));
     520             : 
     521             :   Handle<Map> new_map2 = Map::ReconfigureProperty(
     522           5 :       isolate, map, 0, kData, NONE, Representation::None(), none_type);
     523          15 :   CHECK_EQ(*new_map, *new_map2);
     524             : 
     525             :   Handle<Object> value(Smi::kZero, isolate);
     526             :   Handle<Map> prepared_map = Map::PrepareForDataProperty(
     527           5 :       isolate, new_map, 0, PropertyConstness::kConst, value);
     528             :   // None to Smi generalization is trivial, map does not change.
     529          15 :   CHECK_EQ(*new_map, *prepared_map);
     530             : 
     531             :   expectations.SetDataField(0, NONE, PropertyConstness::kMutable,
     532             :                             Representation::Smi(), any_type);
     533           5 :   CHECK(prepared_map->is_stable());
     534           5 :   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           5 :   Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
     540           5 :   JSObject::MigrateToMap(obj, prepared_map);
     541           5 :   FieldIndex index = FieldIndex::ForDescriptor(*prepared_map, 0);
     542          10 :   CHECK(obj->RawFastPropertyAt(index)->IsUninitialized(isolate));
     543             : #ifdef VERIFY_HEAP
     544             :   obj->ObjectVerify(isolate);
     545             : #endif
     546           5 : }
     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       25880 : TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) {
     553           5 :   CcTest::InitializeVM();
     554           5 :   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           5 :   Handle<String> foo_str = factory->InternalizeUtf8String("foo");
     567           5 :   Handle<String> obj_name = factory->InternalizeUtf8String("o");
     568             : 
     569             :   Handle<Object> obj_value =
     570          10 :       Object::GetProperty(isolate, isolate->global_object(), obj_name)
     571          10 :           .ToHandleChecked();
     572          10 :   CHECK(obj_value->IsJSObject());
     573           5 :   Handle<JSObject> obj = Handle<JSObject>::cast(obj_value);
     574             : 
     575           5 :   CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
     576          15 :   CHECK(
     577             :       obj->map()->instance_descriptors()->GetStrongValue(0)->IsAccessorPair());
     578             : 
     579             :   Handle<Object> value(Smi::FromInt(42), isolate);
     580          10 :   JSObject::SetOwnPropertyIgnoreAttributes(obj, foo_str, value, NONE).Check();
     581             : 
     582             :   // Check that the property contains |value|.
     583           5 :   CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());
     584           5 :   FieldIndex index = FieldIndex::ForDescriptor(obj->map(), 0);
     585           5 :   Object the_value = obj->RawFastPropertyAt(index);
     586           5 :   CHECK(the_value->IsSmi());
     587           5 :   CHECK_EQ(42, Smi::ToInt(the_value));
     588           5 : }
     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         240 : 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         240 :   Isolate* isolate = CcTest::i_isolate();
     620         240 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     621             : 
     622         240 :   CHECK(detach_property_at_index >= -1 &&
     623             :         detach_property_at_index < kPropCount);
     624         240 :   CHECK_LT(property_index, kPropCount);
     625         240 :   CHECK_NE(detach_property_at_index, property_index);
     626             : 
     627         240 :   const bool is_detached_map = detach_property_at_index >= 0;
     628             : 
     629         240 :   Expectations expectations(isolate);
     630             : 
     631             :   // Create a map, add required properties to it and initialize expectations.
     632         240 :   Handle<Map> initial_map = Map::Create(isolate, 0);
     633         240 :   Handle<Map> map = initial_map;
     634             :   Handle<Map> detach_point_map;
     635        1920 :   for (int i = 0; i < kPropCount; i++) {
     636        1680 :     if (i == property_index) {
     637             :       map = expectations.AddDataField(map, NONE, from.constness,
     638         240 :                                       from.representation, from.type);
     639             :     } else {
     640             :       map = expectations.AddDataField(map, NONE, kDefaultFieldConstness,
     641        1440 :                                       Representation::Smi(), any_type);
     642        1440 :       if (i == detach_property_at_index) {
     643             :         detach_point_map = map;
     644             :       }
     645             :     }
     646             :   }
     647         240 :   CHECK(!map->is_deprecated());
     648         240 :   CHECK(map->is_stable());
     649         240 :   CHECK(expectations.Check(*map));
     650             : 
     651         240 :   Zone zone(isolate->allocator(), ZONE_NAME);
     652             : 
     653         240 :   if (is_detached_map) {
     654             :     detach_point_map = Map::ReconfigureProperty(
     655             :         isolate, detach_point_map, detach_property_at_index, kData, NONE,
     656          60 :         Representation::Tagged(), any_type);
     657             :     expectations.SetDataField(detach_property_at_index, kDefaultFieldConstness,
     658          60 :                               Representation::Tagged(), any_type);
     659          60 :     CHECK(map->is_deprecated());
     660          60 :     CHECK(expectations.Check(*detach_point_map,
     661             :                              detach_point_map->NumberOfOwnDescriptors()));
     662             :   }
     663             : 
     664             :   // Create new maps by generalizing representation of propX field.
     665         480 :   CanonicalHandleScope canonical(isolate);
     666         240 :   JSHeapBroker broker(isolate, &zone);
     667         240 :   CompilationDependencies dependencies(isolate, &zone);
     668             :   MapRef map_ref(&broker, map);
     669         240 :   map_ref.SerializeOwnDescriptors();
     670         240 :   dependencies.DependOnFieldType(map_ref, property_index);
     671             : 
     672             :   Handle<Map> field_owner(map->FindFieldOwner(isolate, property_index),
     673         480 :                           isolate);
     674             :   Handle<Map> new_map = Map::ReconfigureProperty(
     675         240 :       isolate, map, property_index, kData, NONE, to.representation, to.type);
     676             : 
     677             :   expectations.SetDataField(property_index, expected.constness,
     678         240 :                             expected.representation, expected.type);
     679             : 
     680         240 :   CHECK(!new_map->is_deprecated());
     681         240 :   CHECK(expectations.Check(*new_map));
     682             : 
     683         240 :   if (is_detached_map) {
     684          60 :     CHECK(!map->is_stable());
     685          60 :     CHECK(map->is_deprecated());
     686         180 :     CHECK_NE(*map, *new_map);
     687          70 :     CHECK_EQ(expected_field_type_dependency && !field_owner->is_deprecated(),
     688             :              !dependencies.AreValid());
     689             : 
     690         180 :   } else if (expected_deprecation) {
     691          75 :     CHECK(!map->is_stable());
     692          75 :     CHECK(map->is_deprecated());
     693          75 :     CHECK(field_owner->is_deprecated());
     694         225 :     CHECK_NE(*map, *new_map);
     695          75 :     CHECK(dependencies.AreValid());
     696             : 
     697             :   } else {
     698         105 :     CHECK(!field_owner->is_deprecated());
     699         105 :     CHECK(map->is_stable());  // Map did not change, must be left stable.
     700         315 :     CHECK_EQ(*map, *new_map);
     701             : 
     702         105 :     CHECK_EQ(expected_field_type_dependency, !dependencies.AreValid());
     703             :   }
     704             : 
     705             :   {
     706             :     // Check that all previous maps are not stable.
     707         240 :     Map tmp = *new_map;
     708             :     while (true) {
     709        1920 :       Object back = tmp->GetBackPointer();
     710        1920 :       if (back->IsUndefined(isolate)) break;
     711        1680 :       tmp = Map::cast(back);
     712        1680 :       CHECK(!tmp->is_stable());
     713        1680 :     }
     714             :   }
     715             : 
     716             :   // Update all deprecated maps and check that they are now the same.
     717         240 :   Handle<Map> updated_map = Map::Update(isolate, map);
     718         720 :   CHECK_EQ(*new_map, *updated_map);
     719         480 :   CheckMigrationTarget(isolate, *map, *updated_map);
     720         240 : }
     721             : 
     722          50 : 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          50 :   int indices[] = {0, 2, kPropCount - 1};
     730         200 :   for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
     731             :     TestGeneralizeField(-1, indices[i], from, to, expected,
     732         150 :                         expected_deprecation, expected_field_type_dependency);
     733             :   }
     734             : 
     735          50 :   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          30 :     int indices[] = {0, kPropCount - 1};
     740          90 :     for (int i = 0; i < static_cast<int>(arraysize(indices)); i++) {
     741             :       TestGeneralizeField(indices[i], 2, from, to, expected,
     742          60 :                           expected_deprecation, expected_field_type_dependency);
     743             :     }
     744             : 
     745             :     // Check that reconfiguration to the very same field works correctly.
     746          30 :     CRFTData data = from;
     747          30 :     TestGeneralizeField(-1, 2, data, data, data, false, false);
     748             :   }
     749          50 : }
     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          25 :                       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          25 :                       expected_field_type_dependency);
     767             : }
     768             : 
     769       25880 : TEST(GeneralizeSmiFieldToDouble) {
     770           5 :   CcTest::InitializeVM();
     771           5 :   v8::HandleScope scope(CcTest::isolate());
     772             :   Isolate* isolate = CcTest::i_isolate();
     773             : 
     774           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     775             : 
     776             :   TestGeneralizeField(
     777             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
     778             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
     779          10 :       {PropertyConstness::kMutable, Representation::Double(), any_type});
     780           5 : }
     781             : 
     782       25880 : TEST(GeneralizeSmiFieldToTagged) {
     783           5 :   CcTest::InitializeVM();
     784           5 :   v8::HandleScope scope(CcTest::isolate());
     785             :   Isolate* isolate = CcTest::i_isolate();
     786             : 
     787           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     788             :   Handle<FieldType> value_type =
     789           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     790             : 
     791             :   TestGeneralizeField(
     792             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
     793             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
     794          10 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
     795           5 : }
     796             : 
     797       25880 : TEST(GeneralizeDoubleFieldToTagged) {
     798           5 :   CcTest::InitializeVM();
     799           5 :   v8::HandleScope scope(CcTest::isolate());
     800             :   Isolate* isolate = CcTest::i_isolate();
     801             : 
     802           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     803             :   Handle<FieldType> value_type =
     804           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     805             : 
     806             :   TestGeneralizeField(
     807             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
     808             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
     809          10 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
     810           5 : }
     811             : 
     812       25880 : TEST(GeneralizeHeapObjectFieldToTagged) {
     813           5 :   CcTest::InitializeVM();
     814           5 :   v8::HandleScope scope(CcTest::isolate());
     815             :   Isolate* isolate = CcTest::i_isolate();
     816             : 
     817           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     818             :   Handle<FieldType> value_type =
     819           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     820             : 
     821             :   TestGeneralizeField(
     822             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
     823             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
     824          10 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
     825           5 : }
     826             : 
     827       25880 : TEST(GeneralizeHeapObjectFieldToHeapObject) {
     828           5 :   CcTest::InitializeVM();
     829           5 :   v8::HandleScope scope(CcTest::isolate());
     830             :   Isolate* isolate = CcTest::i_isolate();
     831             : 
     832           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     833             : 
     834             :   Handle<FieldType> current_type =
     835           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     836             : 
     837             :   Handle<FieldType> new_type =
     838           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     839             : 
     840           5 :   Handle<FieldType> expected_type = any_type;
     841             : 
     842             :   TestGeneralizeFieldTrivial(
     843             :       {PropertyConstness::kMutable, Representation::HeapObject(), current_type},
     844             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
     845             :       {PropertyConstness::kMutable, Representation::HeapObject(),
     846          10 :        expected_type});
     847             :   current_type = expected_type;
     848             : 
     849           5 :   new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
     850             : 
     851             :   TestGeneralizeFieldTrivial(
     852             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
     853             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
     854             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
     855          10 :       false);
     856           5 : }
     857             : 
     858       25880 : TEST(GeneralizeNoneFieldToSmi) {
     859           5 :   CcTest::InitializeVM();
     860           5 :   v8::HandleScope scope(CcTest::isolate());
     861             :   Isolate* isolate = CcTest::i_isolate();
     862             : 
     863           5 :   Handle<FieldType> none_type = FieldType::None(isolate);
     864           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     865             : 
     866             :   // None -> Smi representation change is trivial.
     867             :   TestGeneralizeFieldTrivial(
     868             :       {PropertyConstness::kMutable, Representation::None(), none_type},
     869             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
     870          10 :       {PropertyConstness::kMutable, Representation::Smi(), any_type});
     871           5 : }
     872             : 
     873       25880 : TEST(GeneralizeNoneFieldToDouble) {
     874           5 :   CcTest::InitializeVM();
     875           5 :   v8::HandleScope scope(CcTest::isolate());
     876             :   Isolate* isolate = CcTest::i_isolate();
     877             : 
     878           5 :   Handle<FieldType> none_type = FieldType::None(isolate);
     879           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     880             : 
     881             :   // None -> Double representation change is NOT trivial.
     882             :   TestGeneralizeField(
     883             :       {PropertyConstness::kMutable, Representation::None(), none_type},
     884             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
     885          10 :       {PropertyConstness::kMutable, Representation::Double(), any_type});
     886           5 : }
     887             : 
     888       25880 : TEST(GeneralizeNoneFieldToHeapObject) {
     889           5 :   CcTest::InitializeVM();
     890           5 :   v8::HandleScope scope(CcTest::isolate());
     891             :   Isolate* isolate = CcTest::i_isolate();
     892             : 
     893           5 :   Handle<FieldType> none_type = FieldType::None(isolate);
     894             :   Handle<FieldType> value_type =
     895           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
     896             : 
     897             :   // None -> HeapObject representation change is trivial.
     898             :   TestGeneralizeFieldTrivial(
     899             :       {PropertyConstness::kMutable, Representation::None(), none_type},
     900             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
     901          10 :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type});
     902           5 : }
     903             : 
     904       25880 : TEST(GeneralizeNoneFieldToTagged) {
     905           5 :   CcTest::InitializeVM();
     906           5 :   v8::HandleScope scope(CcTest::isolate());
     907             :   Isolate* isolate = CcTest::i_isolate();
     908             : 
     909           5 :   Handle<FieldType> none_type = FieldType::None(isolate);
     910           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     911             : 
     912             :   // None -> HeapObject representation change is trivial.
     913             :   TestGeneralizeFieldTrivial(
     914             :       {PropertyConstness::kMutable, Representation::None(), none_type},
     915             :       {PropertyConstness::kMutable, Representation::Tagged(), any_type},
     916          10 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
     917           5 : }
     918             : 
     919             : 
     920             : ////////////////////////////////////////////////////////////////////////////////
     921             : // A set of tests for field generalization case with kAccessor properties.
     922             : //
     923             : 
     924       25880 : TEST(GeneralizeFieldWithAccessorProperties) {
     925           5 :   CcTest::InitializeVM();
     926           5 :   v8::HandleScope scope(CcTest::isolate());
     927             :   Isolate* isolate = CcTest::i_isolate();
     928             : 
     929           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
     930           5 :   Handle<AccessorPair> pair = CreateAccessorPair(true, true);
     931             : 
     932             :   const int kAccessorProp = kPropCount / 2;
     933           5 :   Expectations expectations(isolate);
     934             : 
     935             :   // Create a map, add required properties to it and initialize expectations.
     936           5 :   Handle<Map> initial_map = Map::Create(isolate, 0);
     937           5 :   Handle<Map> map = initial_map;
     938          40 :   for (int i = 0; i < kPropCount; i++) {
     939          35 :     if (i == kAccessorProp) {
     940           5 :       map = expectations.AddAccessorConstant(map, NONE, pair);
     941             :     } else {
     942             :       map = expectations.AddDataField(map, NONE, PropertyConstness::kMutable,
     943          30 :                                       Representation::Smi(), any_type);
     944             :     }
     945             :   }
     946           5 :   CHECK(!map->is_deprecated());
     947           5 :   CHECK(map->is_stable());
     948           5 :   CHECK(expectations.Check(*map));
     949             : 
     950             :   // Create new maps by generalizing representation of propX field.
     951          35 :   Handle<Map> maps[kPropCount];
     952          35 :   for (int i = 0; i < kPropCount; i++) {
     953          35 :     if (i == kAccessorProp) {
     954             :       // Skip accessor property reconfiguration.
     955           5 :       maps[i] = maps[i - 1];
     956             :       continue;
     957             :     }
     958             :     Handle<Map> new_map = Map::ReconfigureProperty(
     959          30 :         isolate, map, i, kData, NONE, Representation::Double(), any_type);
     960          30 :     maps[i] = new_map;
     961             : 
     962             :     expectations.SetDataField(i, PropertyConstness::kMutable,
     963          30 :                               Representation::Double(), any_type);
     964             : 
     965          30 :     CHECK(!map->is_stable());
     966          30 :     CHECK(map->is_deprecated());
     967          90 :     CHECK_NE(*map, *new_map);
     968          55 :     CHECK(i == 0 || maps[i - 1]->is_deprecated());
     969             : 
     970          30 :     CHECK(!new_map->is_deprecated());
     971          30 :     CHECK(expectations.Check(*new_map));
     972             :   }
     973             : 
     974           5 :   Handle<Map> active_map = maps[kPropCount - 1];
     975           5 :   CHECK(!active_map->is_deprecated());
     976             : 
     977             :   // Update all deprecated maps and check that they are now the same.
     978           5 :   Handle<Map> updated_map = Map::Update(isolate, map);
     979          15 :   CHECK_EQ(*active_map, *updated_map);
     980           5 :   CheckMigrationTarget(isolate, *map, *updated_map);
     981          40 :   for (int i = 0; i < kPropCount; i++) {
     982          35 :     updated_map = Map::Update(isolate, maps[i]);
     983         105 :     CHECK_EQ(*active_map, *updated_map);
     984          70 :     CheckMigrationTarget(isolate, *maps[i], *updated_map);
     985           5 :   }
     986           5 : }
     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          65 : static void TestReconfigureDataFieldAttribute_GeneralizeField(
    1003             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
    1004          65 :   Isolate* isolate = CcTest::i_isolate();
    1005             : 
    1006          65 :   Expectations expectations(isolate);
    1007             : 
    1008             :   // Create a map, add required properties to it and initialize expectations.
    1009          65 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1010          65 :   Handle<Map> map = initial_map;
    1011         520 :   for (int i = 0; i < kPropCount; i++) {
    1012             :     map = expectations.AddDataField(map, NONE, from.constness,
    1013         455 :                                     from.representation, from.type);
    1014             :   }
    1015          65 :   CHECK(!map->is_deprecated());
    1016          65 :   CHECK(map->is_stable());
    1017          65 :   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          65 :   Expectations expectations2(isolate);
    1024             : 
    1025             :   Handle<Map> map2 = initial_map;
    1026         260 :   for (int i = 0; i < kSplitProp; i++) {
    1027             :     map2 = expectations2.FollowDataTransition(map2, NONE, from.constness,
    1028         195 :                                               from.representation, from.type);
    1029             :   }
    1030             :   map2 = expectations2.AddDataField(map2, READ_ONLY, to.constness,
    1031          65 :                                     to.representation, to.type);
    1032             : 
    1033         260 :   for (int i = kSplitProp + 1; i < kPropCount; i++) {
    1034             :     map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1035         195 :                                       to.representation, to.type);
    1036             :   }
    1037          65 :   CHECK(!map2->is_deprecated());
    1038          65 :   CHECK(map2->is_stable());
    1039          65 :   CHECK(expectations2.Check(*map2));
    1040             : 
    1041          65 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1042         130 :   CanonicalHandleScope canonical(isolate);
    1043          65 :   JSHeapBroker broker(isolate, &zone);
    1044          65 :   CompilationDependencies dependencies(isolate, &zone);
    1045             :   MapRef map_ref(&broker, map);
    1046          65 :   map_ref.SerializeOwnDescriptors();
    1047          65 :   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          65 :       Map::ReconfigureExistingProperty(isolate, map2, kSplitProp, kData, NONE);
    1053             : 
    1054             :   // |map2| should be left unchanged but marked unstable.
    1055          65 :   CHECK(!map2->is_stable());
    1056          65 :   CHECK(!map2->is_deprecated());
    1057         195 :   CHECK_NE(*map2, *new_map);
    1058          65 :   CHECK(expectations2.Check(*map2));
    1059             : 
    1060             :   // |map| should be deprecated and |new_map| should match new expectations.
    1061         260 :   for (int i = kSplitProp; i < kPropCount; i++) {
    1062             :     expectations.SetDataField(i, expected.constness, expected.representation,
    1063         260 :                               expected.type);
    1064             :   }
    1065          65 :   CHECK(map->is_deprecated());
    1066          65 :   CHECK(dependencies.AreValid());
    1067         195 :   CHECK_NE(*map, *new_map);
    1068             : 
    1069          65 :   CHECK(!new_map->is_deprecated());
    1070          65 :   CHECK(expectations.Check(*new_map));
    1071             : 
    1072             :   // Update deprecated |map|, it should become |new_map|.
    1073          65 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1074         195 :   CHECK_EQ(*new_map, *updated_map);
    1075         130 :   CheckMigrationTarget(isolate, *map, *updated_map);
    1076          65 : }
    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          40 : static void TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1089             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected,
    1090             :     bool expected_field_type_dependency = true) {
    1091          40 :   Isolate* isolate = CcTest::i_isolate();
    1092             : 
    1093          40 :   Expectations expectations(isolate);
    1094             : 
    1095             :   // Create a map, add required properties to it and initialize expectations.
    1096          40 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1097          40 :   Handle<Map> map = initial_map;
    1098         320 :   for (int i = 0; i < kPropCount; i++) {
    1099             :     map = expectations.AddDataField(map, NONE, from.constness,
    1100         280 :                                     from.representation, from.type);
    1101             :   }
    1102          40 :   CHECK(!map->is_deprecated());
    1103          40 :   CHECK(map->is_stable());
    1104          40 :   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          40 :   Expectations expectations2(isolate);
    1111             : 
    1112             :   Handle<Map> map2 = initial_map;
    1113         160 :   for (int i = 0; i < kSplitProp; i++) {
    1114             :     map2 = expectations2.FollowDataTransition(map2, NONE, from.constness,
    1115         120 :                                               from.representation, from.type);
    1116             :   }
    1117             :   map2 = expectations2.AddDataField(map2, READ_ONLY, to.constness,
    1118          40 :                                     to.representation, to.type);
    1119             : 
    1120         160 :   for (int i = kSplitProp + 1; i < kPropCount; i++) {
    1121             :     map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1122         120 :                                       to.representation, to.type);
    1123             :   }
    1124          40 :   CHECK(!map2->is_deprecated());
    1125          40 :   CHECK(map2->is_stable());
    1126          40 :   CHECK(expectations2.Check(*map2));
    1127             : 
    1128          40 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1129          80 :   CanonicalHandleScope canonical(isolate);
    1130          40 :   JSHeapBroker broker(isolate, &zone);
    1131          40 :   CompilationDependencies dependencies(isolate, &zone);
    1132             :   MapRef map_ref(&broker, map);
    1133          40 :   map_ref.SerializeOwnDescriptors();
    1134          40 :   dependencies.DependOnFieldType(map_ref, kSplitProp);
    1135          40 :   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          40 :       Map::ReconfigureExistingProperty(isolate, map2, kSplitProp, kData, NONE);
    1141             : 
    1142             :   // |map2| should be left unchanged but marked unstable.
    1143          40 :   CHECK(!map2->is_stable());
    1144          40 :   CHECK(!map2->is_deprecated());
    1145         120 :   CHECK_NE(*map2, *new_map);
    1146          40 :   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         160 :   for (int i = kSplitProp; i < kPropCount; i++) {
    1153             :     expectations.SetDataField(i, expected.constness, expected.representation,
    1154         160 :                               expected.type);
    1155             :   }
    1156          40 :   CHECK(!map->is_deprecated());
    1157         120 :   CHECK_EQ(*map, *new_map);
    1158          40 :   CHECK_EQ(expected_field_type_dependency, !dependencies.AreValid());
    1159             : 
    1160          40 :   CHECK(!new_map->is_deprecated());
    1161          40 :   CHECK(expectations.Check(*new_map));
    1162             : 
    1163          40 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1164         160 :   CHECK_EQ(*new_map, *updated_map);
    1165          40 : }
    1166             : 
    1167       25880 : TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToDouble) {
    1168           5 :   CcTest::InitializeVM();
    1169           5 :   v8::HandleScope scope(CcTest::isolate());
    1170             :   Isolate* isolate = CcTest::i_isolate();
    1171             : 
    1172           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1173             : 
    1174             :   if (FLAG_track_constant_fields) {
    1175             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1176             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1177             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1178           5 :         {PropertyConstness::kConst, Representation::Double(), any_type});
    1179             : 
    1180             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1181             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1182             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    1183           5 :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1184             : 
    1185             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1186             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1187             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1188           5 :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1189             :   }
    1190             : 
    1191             :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1192             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1193             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    1194           5 :       {PropertyConstness::kMutable, Representation::Double(), any_type});
    1195           5 : }
    1196             : 
    1197       25880 : TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
    1198           5 :   CcTest::InitializeVM();
    1199           5 :   v8::HandleScope scope(CcTest::isolate());
    1200             :   Isolate* isolate = CcTest::i_isolate();
    1201             : 
    1202           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1203             :   Handle<FieldType> value_type =
    1204           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1205             : 
    1206             :   if (FLAG_track_constant_fields) {
    1207             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1208             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1209             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1210           5 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    1211             : 
    1212             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1213             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1214             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1215           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1216             : 
    1217             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1218             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1219             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1220           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1221             :   }
    1222             : 
    1223             :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1224             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1225             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1226           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1227           5 : }
    1228             : 
    1229       25880 : TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
    1230           5 :   CcTest::InitializeVM();
    1231           5 :   v8::HandleScope scope(CcTest::isolate());
    1232             :   Isolate* isolate = CcTest::i_isolate();
    1233             : 
    1234           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1235             :   Handle<FieldType> value_type =
    1236           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1237             : 
    1238             :   if (FLAG_track_constant_fields) {
    1239             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1240             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1241             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1242           5 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    1243             : 
    1244             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1245             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1246             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1247           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1248             : 
    1249             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1250             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    1251             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1252           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1253             :   }
    1254             : 
    1255             :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1256             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    1257             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1258           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1259           5 : }
    1260             : 
    1261       25880 : TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjFieldToHeapObj) {
    1262           5 :   CcTest::InitializeVM();
    1263           5 :   v8::HandleScope scope(CcTest::isolate());
    1264             :   Isolate* isolate = CcTest::i_isolate();
    1265             : 
    1266           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1267             : 
    1268             :   Handle<FieldType> current_type =
    1269           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1270             : 
    1271             :   Handle<FieldType> new_type =
    1272           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1273             : 
    1274           5 :   Handle<FieldType> expected_type = any_type;
    1275             : 
    1276             :   // Check generalizations that trigger deopts.
    1277             :   if (FLAG_track_constant_fields) {
    1278             :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1279             :         {PropertyConstness::kConst, Representation::HeapObject(), current_type},
    1280             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1281             :         {PropertyConstness::kConst, Representation::HeapObject(),
    1282           5 :          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             :       TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1288             :           {PropertyConstness::kConst, Representation::HeapObject(),
    1289             :            current_type},
    1290             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1291             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1292           5 :            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             :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1304             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    1305             :          current_type},
    1306             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1307             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    1308           5 :          expected_type});
    1309             :   }
    1310             :   TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1311             :       {PropertyConstness::kMutable, Representation::HeapObject(), current_type},
    1312             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1313             :       {PropertyConstness::kMutable, Representation::HeapObject(),
    1314           5 :        expected_type});
    1315             :   current_type = expected_type;
    1316             : 
    1317             :   // Check generalizations that do not trigger deopts.
    1318           5 :   new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
    1319             : 
    1320             :   if (FLAG_track_constant_fields) {
    1321             :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1322             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1323             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1324             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1325           5 :         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             :       TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1331             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1332             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1333             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1334           5 :            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             :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1345             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1346             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1347             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1348           5 :         false);
    1349             :   }
    1350             :   TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1351             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1352             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1353             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1354           5 :       false);
    1355           5 : }
    1356             : 
    1357       25880 : TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjectFieldToTagged) {
    1358           5 :   CcTest::InitializeVM();
    1359           5 :   v8::HandleScope scope(CcTest::isolate());
    1360             :   Isolate* isolate = CcTest::i_isolate();
    1361             : 
    1362           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1363             :   Handle<FieldType> value_type =
    1364           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1365             : 
    1366             :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1367             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1368             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1369           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1370           5 : }
    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          15 :   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          15 :     CHECK(map->is_stable());
    1399          15 :     CHECK(!map->is_deprecated());
    1400          45 :     CHECK_EQ(*map, *new_map);
    1401             : 
    1402          15 :     CHECK(!new_map->is_deprecated());
    1403          15 :     CHECK(expectations.Check(*new_map));
    1404             : 
    1405             :     // Update deprecated |map|, it should become |new_map|.
    1406          15 :     Handle<Map> updated_map = Map::Update(isolate, map);
    1407          45 :     CHECK_EQ(*new_map, *updated_map);
    1408          15 :   }
    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          10 :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1416             :              const Expectations& expectations) {
    1417          10 :     CHECK(!map->is_deprecated());
    1418          30 :     CHECK_NE(*map, *new_map);
    1419          10 :     CHECK(expectations.Check(*map));
    1420             : 
    1421          10 :     CHECK(new_map->is_stable());
    1422          10 :     CHECK(!new_map->is_deprecated());
    1423          10 :   }
    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           5 :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1431             :              Expectations& expectations) {
    1432           5 :     CHECK(!map->is_deprecated());
    1433          15 :     CHECK_NE(*map, *new_map);
    1434             : 
    1435          10 :     CHECK(new_map->GetBackPointer()->IsUndefined(isolate));
    1436          35 :     for (int i = 0; i < kPropCount; i++) {
    1437          35 :       expectations.GeneralizeField(i);
    1438             :     }
    1439             : 
    1440           5 :     CHECK(!new_map->is_deprecated());
    1441           5 :     CHECK(expectations.Check(*new_map));
    1442           5 :   }
    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          30 : static void TestReconfigureProperty_CustomPropertyAfterTargetMap(
    1460             :     TestConfig& config, Checker& checker) {
    1461             :   Isolate* isolate = CcTest::i_isolate();
    1462          30 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1463             : 
    1464             :   const int kCustomPropIndex = kPropCount - 2;
    1465          30 :   Expectations expectations(isolate);
    1466             : 
    1467             :   const int kSplitProp = 2;
    1468             :   CHECK_LT(kSplitProp, kCustomPropIndex);
    1469             : 
    1470             :   const PropertyConstness constness = PropertyConstness::kMutable;
    1471          30 :   const Representation representation = Representation::Smi();
    1472             : 
    1473             :   // Create common part of transition tree.
    1474          30 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1475          30 :   Handle<Map> map = initial_map;
    1476          90 :   for (int i = 0; i < kSplitProp; i++) {
    1477          60 :     map = expectations.AddDataField(map, NONE, constness, representation,
    1478             :                                     any_type);
    1479             :   }
    1480          30 :   CHECK(!map->is_deprecated());
    1481          30 :   CHECK(map->is_stable());
    1482          30 :   CHECK(expectations.Check(*map));
    1483             : 
    1484             : 
    1485             :   // Create branch to |map1|.
    1486             :   Handle<Map> map1 = map;
    1487          30 :   Expectations expectations1 = expectations;
    1488         120 :   for (int i = kSplitProp; i < kCustomPropIndex; i++) {
    1489          90 :     map1 = expectations1.AddDataField(map1, NONE, constness, representation,
    1490             :                                       any_type);
    1491             :   }
    1492          30 :   map1 = config.AddPropertyAtBranch(1, expectations1, map1);
    1493          60 :   for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
    1494          30 :     map1 = expectations1.AddDataField(map1, NONE, constness, representation,
    1495             :                                       any_type);
    1496             :   }
    1497          30 :   CHECK(!map1->is_deprecated());
    1498          30 :   CHECK(map1->is_stable());
    1499          30 :   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          30 :   Expectations expectations2 = expectations;
    1506          30 :   map2 = expectations2.AddDataField(map2, READ_ONLY, constness, representation,
    1507             :                                     any_type);
    1508          90 :   for (int i = kSplitProp + 1; i < kCustomPropIndex; i++) {
    1509          60 :     map2 = expectations2.AddDataField(map2, NONE, constness, representation,
    1510             :                                       any_type);
    1511             :   }
    1512          30 :   map2 = config.AddPropertyAtBranch(2, expectations2, map2);
    1513          60 :   for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
    1514          30 :     map2 = expectations2.AddDataField(map2, NONE, constness, representation,
    1515             :                                       any_type);
    1516             :   }
    1517          30 :   CHECK(!map2->is_deprecated());
    1518          30 :   CHECK(map2->is_stable());
    1519          30 :   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          30 :       Map::ReconfigureExistingProperty(isolate, map2, kSplitProp, kData, NONE);
    1526             : 
    1527             :   // |map2| should be left unchanged but marked unstable.
    1528          30 :   CHECK(!map2->is_stable());
    1529          30 :   CHECK(!map2->is_deprecated());
    1530          90 :   CHECK_NE(*map2, *new_map);
    1531          30 :   CHECK(expectations2.Check(*map2));
    1532             : 
    1533             :   config.UpdateExpectations(kCustomPropIndex, expectations1);
    1534          30 :   checker.Check(isolate, map1, new_map, expectations1);
    1535          30 : }
    1536             : 
    1537             : 
    1538       25880 : TEST(ReconfigureDataFieldAttribute_SameDataConstantAfterTargetMap) {
    1539           5 :   CcTest::InitializeVM();
    1540           5 :   v8::HandleScope scope(CcTest::isolate());
    1541             : 
    1542             :   struct TestConfig {
    1543             :     Handle<JSFunction> js_func_;
    1544           5 :     TestConfig() {
    1545             :       Isolate* isolate = CcTest::i_isolate();
    1546             :       Factory* factory = isolate->factory();
    1547           5 :       js_func_ = factory->NewFunctionForTest(factory->empty_string());
    1548           5 :     }
    1549             : 
    1550          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1551             :                                     Handle<Map> map) {
    1552          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1553             :       // Add the same data constant property at both transition tree branches.
    1554          10 :       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           5 :   TestConfig config;
    1563             :   // Two branches are "compatible" so the |map1| should NOT be deprecated.
    1564             :   CheckSameMap checker;
    1565           5 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1566           5 : }
    1567             : 
    1568             : 
    1569       25880 : TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) {
    1570           5 :   CcTest::InitializeVM();
    1571           5 :   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           5 :     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           5 :           Map::CopyInitialMap(isolate, isolate->sloppy_function_map());
    1583             :       Handle<SharedFunctionInfo> info =
    1584           5 :           factory->NewSharedFunctionInfoForBuiltin(name, Builtins::kIllegal);
    1585           5 :       function_type_ = FieldType::Class(sloppy_map, isolate);
    1586           5 :       CHECK(sloppy_map->is_stable());
    1587             : 
    1588             :       js_func1_ =
    1589          10 :           factory->NewFunction(sloppy_map, info, isolate->native_context());
    1590             : 
    1591             :       js_func2_ =
    1592          10 :           factory->NewFunction(sloppy_map, info, isolate->native_context());
    1593           5 :     }
    1594             : 
    1595          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1596             :                                     Handle<Map> map) {
    1597          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1598          10 :       Handle<JSFunction> js_func = branch_id == 1 ? js_func1_ : js_func2_;
    1599          10 :       return expectations.AddDataConstant(map, NONE, js_func);
    1600             :     }
    1601             : 
    1602             :     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           5 :                                 Representation::HeapObject(), function_type_);
    1608             :     }
    1609             :   };
    1610             : 
    1611           5 :   TestConfig config;
    1612             :   if (FLAG_track_constant_fields) {
    1613             :     CheckSameMap checker;
    1614           5 :     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           5 :   }
    1621           5 : }
    1622             : 
    1623             : 
    1624       25880 : TEST(ReconfigureDataFieldAttribute_DataConstantToAccConstantAfterTargetMap) {
    1625           5 :   CcTest::InitializeVM();
    1626           5 :   v8::HandleScope scope(CcTest::isolate());
    1627             : 
    1628             :   struct TestConfig {
    1629             :     Handle<JSFunction> js_func_;
    1630             :     Handle<AccessorPair> pair_;
    1631           5 :     TestConfig() {
    1632             :       Isolate* isolate = CcTest::i_isolate();
    1633             :       Factory* factory = isolate->factory();
    1634           5 :       js_func_ = factory->NewFunctionForTest(factory->empty_string());
    1635           5 :       pair_ = CreateAccessorPair(true, true);
    1636           5 :     }
    1637             : 
    1638          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1639             :                                     Handle<Map> map) {
    1640          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1641          10 :       if (branch_id == 1) {
    1642           5 :         return expectations.AddDataConstant(map, NONE, js_func_);
    1643             :       } else {
    1644           5 :         return expectations.AddAccessorConstant(map, NONE, pair_);
    1645             :       }
    1646             :     }
    1647             : 
    1648             :     void UpdateExpectations(int property_index, Expectations& expectations) {}
    1649             :   };
    1650             : 
    1651           5 :   TestConfig config;
    1652             :   // These are completely separate branches in transition tree.
    1653             :   CheckUnrelated checker;
    1654           5 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1655           5 : }
    1656             : 
    1657             : 
    1658       25880 : TEST(ReconfigureDataFieldAttribute_SameAccessorConstantAfterTargetMap) {
    1659           5 :   CcTest::InitializeVM();
    1660           5 :   v8::HandleScope scope(CcTest::isolate());
    1661             : 
    1662             :   struct TestConfig {
    1663             :     Handle<AccessorPair> pair_;
    1664           5 :     TestConfig() { pair_ = CreateAccessorPair(true, true); }
    1665             : 
    1666          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1667             :                                     Handle<Map> map) {
    1668          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1669             :       // Add the same accessor constant property at both transition tree
    1670             :       // branches.
    1671          10 :       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           5 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1682           5 : }
    1683             : 
    1684             : 
    1685       25880 : TEST(ReconfigureDataFieldAttribute_AccConstantToAccFieldAfterTargetMap) {
    1686           5 :   CcTest::InitializeVM();
    1687           5 :   v8::HandleScope scope(CcTest::isolate());
    1688             : 
    1689             :   struct TestConfig {
    1690             :     Handle<AccessorPair> pair1_;
    1691             :     Handle<AccessorPair> pair2_;
    1692           5 :     TestConfig() {
    1693           5 :       pair1_ = CreateAccessorPair(true, true);
    1694           5 :       pair2_ = CreateAccessorPair(true, true);
    1695           5 :     }
    1696             : 
    1697          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1698             :                                     Handle<Map> map) {
    1699          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1700          10 :       Handle<AccessorPair> pair = branch_id == 1 ? pair1_ : pair2_;
    1701          10 :       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           5 :         expectations.SetAccessorConstant(property_index, pair2_);
    1711             :       }
    1712             :     }
    1713             :   };
    1714             : 
    1715           5 :   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           5 :     TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1723           5 :   }
    1724           5 : }
    1725             : 
    1726             : 
    1727       25880 : TEST(ReconfigureDataFieldAttribute_AccConstantToDataFieldAfterTargetMap) {
    1728           5 :   CcTest::InitializeVM();
    1729           5 :   v8::HandleScope scope(CcTest::isolate());
    1730             : 
    1731             :   struct TestConfig {
    1732             :     Handle<AccessorPair> pair_;
    1733           5 :     TestConfig() { pair_ = CreateAccessorPair(true, true); }
    1734             : 
    1735          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1736             :                                     Handle<Map> map) {
    1737          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1738          10 :       if (branch_id == 1) {
    1739           5 :         return expectations.AddAccessorConstant(map, NONE, pair_);
    1740             :       } else {
    1741             :         Isolate* isolate = CcTest::i_isolate();
    1742           5 :         Handle<FieldType> any_type = FieldType::Any(isolate);
    1743             :         return expectations.AddDataField(map, NONE, kDefaultFieldConstness,
    1744           5 :                                          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           5 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1755           5 : }
    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          80 : static void TestReconfigureElementsKind_GeneralizeField(
    1774             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
    1775          80 :   Isolate* isolate = CcTest::i_isolate();
    1776             : 
    1777          80 :   Expectations expectations(isolate, PACKED_SMI_ELEMENTS);
    1778             : 
    1779             :   // Create a map, add required properties to it and initialize expectations.
    1780          80 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1781             :   initial_map->set_instance_type(JS_ARRAY_TYPE);
    1782          80 :   initial_map->set_elements_kind(PACKED_SMI_ELEMENTS);
    1783             : 
    1784             :   Handle<Map> map = initial_map;
    1785          80 :   map = expectations.AsElementsKind(map, PACKED_ELEMENTS);
    1786         640 :   for (int i = 0; i < kPropCount; i++) {
    1787             :     map = expectations.AddDataField(map, NONE, from.constness,
    1788         560 :                                     from.representation, from.type);
    1789             :   }
    1790          80 :   CHECK(!map->is_deprecated());
    1791          80 :   CHECK(map->is_stable());
    1792          80 :   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          80 :   Expectations expectations2(isolate, PACKED_SMI_ELEMENTS);
    1798             : 
    1799             :   Handle<Map> map2 = initial_map;
    1800         640 :   for (int i = 0; i < kPropCount; i++) {
    1801         560 :     if (i == kDiffProp) {
    1802             :       map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1803          80 :                                         to.representation, to.type);
    1804             :     } else {
    1805             :       map2 = expectations2.AddDataField(map2, NONE, from.constness,
    1806         480 :                                         from.representation, from.type);
    1807             :     }
    1808             :   }
    1809          80 :   CHECK(!map2->is_deprecated());
    1810          80 :   CHECK(map2->is_stable());
    1811          80 :   CHECK(expectations2.Check(*map2));
    1812             : 
    1813          80 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1814         160 :   CanonicalHandleScope canonical(isolate);
    1815          80 :   JSHeapBroker broker(isolate, &zone);
    1816          80 :   CompilationDependencies dependencies(isolate, &zone);
    1817             :   MapRef map_ref(&broker, map);
    1818          80 :   map_ref.SerializeOwnDescriptors();
    1819          80 :   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          80 :       Map::ReconfigureElementsKind(isolate, map2, PACKED_ELEMENTS);
    1825             : 
    1826             :   // |map2| should be left unchanged but marked unstable.
    1827          80 :   CHECK(!map2->is_stable());
    1828          80 :   CHECK(!map2->is_deprecated());
    1829         240 :   CHECK_NE(*map2, *new_map);
    1830          80 :   CHECK(expectations2.Check(*map2));
    1831             : 
    1832             :   // |map| should be deprecated and |new_map| should match new expectations.
    1833             :   expectations.SetDataField(kDiffProp, expected.constness,
    1834          80 :                             expected.representation, expected.type);
    1835             : 
    1836          80 :   CHECK(map->is_deprecated());
    1837          80 :   CHECK(dependencies.AreValid());
    1838         240 :   CHECK_NE(*map, *new_map);
    1839             : 
    1840          80 :   CHECK(!new_map->is_deprecated());
    1841          80 :   CHECK(expectations.Check(*new_map));
    1842             : 
    1843             :   // Update deprecated |map|, it should become |new_map|.
    1844          80 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1845         240 :   CHECK_EQ(*new_map, *updated_map);
    1846          80 :   CheckMigrationTarget(isolate, *map, *updated_map);
    1847             : 
    1848             :   // Ensure Map::FindElementsKindTransitionedMap() is able to find the
    1849             :   // transitioned map.
    1850             :   {
    1851             :     MapHandles map_list;
    1852          80 :     map_list.push_back(updated_map);
    1853             :     Map transitioned_map =
    1854          80 :         map2->FindElementsKindTransitionedMap(isolate, map_list);
    1855         160 :     CHECK_EQ(*updated_map, transitioned_map);
    1856          80 :   }
    1857          80 : }
    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          40 : static void TestReconfigureElementsKind_GeneralizeFieldTrivial(
    1872             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
    1873          40 :   Isolate* isolate = CcTest::i_isolate();
    1874             : 
    1875          40 :   Expectations expectations(isolate, PACKED_SMI_ELEMENTS);
    1876             : 
    1877             :   // Create a map, add required properties to it and initialize expectations.
    1878          40 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1879             :   initial_map->set_instance_type(JS_ARRAY_TYPE);
    1880          40 :   initial_map->set_elements_kind(PACKED_SMI_ELEMENTS);
    1881             : 
    1882             :   Handle<Map> map = initial_map;
    1883          40 :   map = expectations.AsElementsKind(map, PACKED_ELEMENTS);
    1884         320 :   for (int i = 0; i < kPropCount; i++) {
    1885             :     map = expectations.AddDataField(map, NONE, from.constness,
    1886         280 :                                     from.representation, from.type);
    1887             :   }
    1888          40 :   CHECK(!map->is_deprecated());
    1889          40 :   CHECK(map->is_stable());
    1890          40 :   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          40 :   Expectations expectations2(isolate, PACKED_SMI_ELEMENTS);
    1896             : 
    1897             :   Handle<Map> map2 = initial_map;
    1898         320 :   for (int i = 0; i < kPropCount; i++) {
    1899         280 :     if (i == kDiffProp) {
    1900             :       map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1901          40 :                                         to.representation, to.type);
    1902             :     } else {
    1903             :       map2 = expectations2.AddDataField(map2, NONE, from.constness,
    1904         240 :                                         from.representation, from.type);
    1905             :     }
    1906             :   }
    1907          40 :   CHECK(!map2->is_deprecated());
    1908          40 :   CHECK(map2->is_stable());
    1909          40 :   CHECK(expectations2.Check(*map2));
    1910             : 
    1911          40 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1912          80 :   CanonicalHandleScope canonical(isolate);
    1913          40 :   JSHeapBroker broker(isolate, &zone);
    1914          40 :   CompilationDependencies dependencies(isolate, &zone);
    1915             :   MapRef map_ref(&broker, map);
    1916          40 :   map_ref.SerializeOwnDescriptors();
    1917             : 
    1918          40 :   dependencies.DependOnFieldType(map_ref, kDiffProp);
    1919          40 :   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          40 :       Map::ReconfigureElementsKind(isolate, map2, PACKED_ELEMENTS);
    1925             : 
    1926             :   // |map2| should be left unchanged but marked unstable.
    1927          40 :   CHECK(!map2->is_stable());
    1928          40 :   CHECK(!map2->is_deprecated());
    1929         120 :   CHECK_NE(*map2, *new_map);
    1930          40 :   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             :   expectations.SetDataField(kDiffProp, expected.constness,
    1937          40 :                             expected.representation, expected.type);
    1938          40 :   CHECK(!map->is_deprecated());
    1939         120 :   CHECK_EQ(*map, *new_map);
    1940          80 :   CHECK_EQ(IsGeneralizableTo(to.constness, from.constness),
    1941             :            dependencies.AreValid());
    1942             : 
    1943          40 :   CHECK(!new_map->is_deprecated());
    1944          40 :   CHECK(expectations.Check(*new_map));
    1945             : 
    1946          40 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1947         120 :   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          40 :     map_list.push_back(updated_map);
    1954             :     Map transitioned_map =
    1955          40 :         map2->FindElementsKindTransitionedMap(isolate, map_list);
    1956          80 :     CHECK_EQ(*updated_map, transitioned_map);
    1957          40 :   }
    1958          40 : }
    1959             : 
    1960       25880 : TEST(ReconfigureElementsKind_GeneralizeSmiFieldToDouble) {
    1961           5 :   CcTest::InitializeVM();
    1962           5 :   v8::HandleScope scope(CcTest::isolate());
    1963             :   Isolate* isolate = CcTest::i_isolate();
    1964             : 
    1965           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1966             : 
    1967             :   if (FLAG_track_constant_fields) {
    1968             :     TestReconfigureElementsKind_GeneralizeField(
    1969             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1970             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1971           5 :         {PropertyConstness::kConst, Representation::Double(), any_type});
    1972             : 
    1973             :     TestReconfigureElementsKind_GeneralizeField(
    1974             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1975             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    1976           5 :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1977             : 
    1978             :     TestReconfigureElementsKind_GeneralizeField(
    1979             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1980             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1981           5 :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1982             :   }
    1983             :   TestReconfigureElementsKind_GeneralizeField(
    1984             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1985             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    1986           5 :       {PropertyConstness::kMutable, Representation::Double(), any_type});
    1987           5 : }
    1988             : 
    1989       25880 : TEST(ReconfigureElementsKind_GeneralizeSmiFieldToTagged) {
    1990           5 :   CcTest::InitializeVM();
    1991           5 :   v8::HandleScope scope(CcTest::isolate());
    1992             :   Isolate* isolate = CcTest::i_isolate();
    1993             : 
    1994           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1995             :   Handle<FieldType> value_type =
    1996           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1997             : 
    1998             :   if (FLAG_track_constant_fields) {
    1999             :     TestReconfigureElementsKind_GeneralizeField(
    2000             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2001             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2002           5 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    2003             : 
    2004             :     TestReconfigureElementsKind_GeneralizeField(
    2005             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2006             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2007           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2008             : 
    2009             :     TestReconfigureElementsKind_GeneralizeField(
    2010             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2011             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2012           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2013             :   }
    2014             :   TestReconfigureElementsKind_GeneralizeField(
    2015             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2016             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2017           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2018           5 : }
    2019             : 
    2020       25880 : TEST(ReconfigureElementsKind_GeneralizeDoubleFieldToTagged) {
    2021           5 :   CcTest::InitializeVM();
    2022           5 :   v8::HandleScope scope(CcTest::isolate());
    2023             :   Isolate* isolate = CcTest::i_isolate();
    2024             : 
    2025           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2026             :   Handle<FieldType> value_type =
    2027           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2028             : 
    2029             :   if (FLAG_track_constant_fields) {
    2030             :     TestReconfigureElementsKind_GeneralizeField(
    2031             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    2032             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2033           5 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    2034             : 
    2035             :     TestReconfigureElementsKind_GeneralizeField(
    2036             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    2037             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2038           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2039             : 
    2040             :     TestReconfigureElementsKind_GeneralizeField(
    2041             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    2042             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2043           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2044             :   }
    2045             :   TestReconfigureElementsKind_GeneralizeField(
    2046             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    2047             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2048           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2049           5 : }
    2050             : 
    2051       25880 : TEST(ReconfigureElementsKind_GeneralizeHeapObjFieldToHeapObj) {
    2052           5 :   CcTest::InitializeVM();
    2053           5 :   v8::HandleScope scope(CcTest::isolate());
    2054             :   Isolate* isolate = CcTest::i_isolate();
    2055             : 
    2056           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2057             : 
    2058             :   Handle<FieldType> current_type =
    2059           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2060             : 
    2061             :   Handle<FieldType> new_type =
    2062           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2063             : 
    2064           5 :   Handle<FieldType> expected_type = any_type;
    2065             : 
    2066             :   // Check generalizations that trigger deopts.
    2067             :   if (FLAG_track_constant_fields) {
    2068             :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2069             :         {PropertyConstness::kConst, Representation::HeapObject(), current_type},
    2070             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2071             :         {PropertyConstness::kConst, Representation::HeapObject(),
    2072           5 :          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             :       TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2077             :           {PropertyConstness::kConst, Representation::HeapObject(),
    2078             :            current_type},
    2079             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2080             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2081           5 :            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             :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2093             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    2094             :          current_type},
    2095             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2096             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    2097           5 :          expected_type});
    2098             :   }
    2099             :   TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2100             :       {PropertyConstness::kMutable, Representation::HeapObject(), current_type},
    2101             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2102             :       {PropertyConstness::kMutable, Representation::HeapObject(),
    2103           5 :        expected_type});
    2104             :   current_type = expected_type;
    2105             : 
    2106             :   // Check generalizations that do not trigger deopts.
    2107           5 :   new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
    2108             : 
    2109             :   if (FLAG_track_constant_fields) {
    2110             :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2111             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    2112             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2113           5 :         {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             :       TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2119             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    2120             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2121             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2122           5 :            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             :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2134             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    2135             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2136           5 :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type});
    2137             :   }
    2138             :   TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2139             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    2140             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2141           5 :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type});
    2142           5 : }
    2143             : 
    2144       25880 : TEST(ReconfigureElementsKind_GeneralizeHeapObjectFieldToTagged) {
    2145           5 :   CcTest::InitializeVM();
    2146           5 :   v8::HandleScope scope(CcTest::isolate());
    2147             :   Isolate* isolate = CcTest::i_isolate();
    2148             : 
    2149           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2150             :   Handle<FieldType> value_type =
    2151           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2152             : 
    2153             :   if (FLAG_track_constant_fields) {
    2154             :     TestReconfigureElementsKind_GeneralizeField(
    2155             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2156             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2157           5 :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    2158             : 
    2159             :     TestReconfigureElementsKind_GeneralizeField(
    2160             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2161             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2162           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2163             : 
    2164             :     TestReconfigureElementsKind_GeneralizeField(
    2165             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2166             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2167           5 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2168             :   }
    2169             :   TestReconfigureElementsKind_GeneralizeField(
    2170             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2171             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2172           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2173           5 : }
    2174             : 
    2175             : ////////////////////////////////////////////////////////////////////////////////
    2176             : // A set of tests checking split map deprecation.
    2177             : //
    2178             : 
    2179       25880 : TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
    2180           5 :   CcTest::InitializeVM();
    2181           5 :   v8::HandleScope scope(CcTest::isolate());
    2182             :   Isolate* isolate = CcTest::i_isolate();
    2183             : 
    2184           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2185             : 
    2186           5 :   Expectations expectations(isolate);
    2187             : 
    2188             :   // Create a map, add required properties to it and initialize expectations.
    2189           5 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    2190           5 :   Handle<Map> map = initial_map;
    2191          40 :   for (int i = 0; i < kPropCount; i++) {
    2192             :     map = expectations.AddDataField(map, NONE, PropertyConstness::kMutable,
    2193          35 :                                     Representation::Smi(), any_type);
    2194             :   }
    2195           5 :   CHECK(!map->is_deprecated());
    2196           5 :   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          20 :     for (int i = 0; i < kSplitProp + 1; i++) {
    2204          20 :       if (i == kSplitProp) {
    2205             :         split_map = map2;
    2206             :       }
    2207             : 
    2208          20 :       Handle<String> name = MakeName("prop", i);
    2209             :       Map target = TransitionsAccessor(isolate, map2)
    2210          20 :                        .SearchTransition(*name, kData, NONE);
    2211          20 :       CHECK(!target.is_null());
    2212             :       map2 = handle(target, isolate);
    2213             :     }
    2214             : 
    2215             :     map2 = Map::ReconfigureProperty(isolate, map2, kSplitProp, kData, NONE,
    2216           5 :                                     Representation::Double(), any_type);
    2217             :     expectations.SetDataField(kSplitProp, PropertyConstness::kMutable,
    2218           5 :                               Representation::Double(), any_type);
    2219             : 
    2220           5 :     CHECK(expectations.Check(*split_map, kSplitProp));
    2221           5 :     CHECK(expectations.Check(*map2, kSplitProp + 1));
    2222             :   }
    2223             : 
    2224             :   // At this point |map| should be deprecated and disconnected from the
    2225             :   // transition tree.
    2226           5 :   CHECK(map->is_deprecated());
    2227           5 :   CHECK(!split_map->is_deprecated());
    2228           5 :   CHECK(map2->is_stable());
    2229           5 :   CHECK(!map2->is_deprecated());
    2230             : 
    2231             :   // Fill in transition tree of |map2| so that it can't have more transitions.
    2232        7680 :   for (int i = 0; i < TransitionsAccessor::kMaxNumberOfTransitions; i++) {
    2233        7680 :     CHECK(TransitionsAccessor(isolate, map2).CanHaveMoreTransitions());
    2234        7680 :     Handle<String> name = MakeName("foo", i);
    2235             :     Map::CopyWithField(isolate, map2, name, any_type, NONE,
    2236             :                        PropertyConstness::kMutable, Representation::Smi(),
    2237        7680 :                        INSERT_TRANSITION)
    2238       15360 :         .ToHandleChecked();
    2239             :   }
    2240           5 :   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           5 :   Handle<Map> updated_map = Map::Update(isolate, map);
    2245          10 :   CHECK(updated_map->GetBackPointer()->IsUndefined(isolate));
    2246             : 
    2247          35 :   for (int i = 0; i < kPropCount; i++) {
    2248             :     expectations.SetDataField(i, PropertyConstness::kMutable,
    2249          35 :                               Representation::Tagged(), any_type);
    2250             :   }
    2251           5 :   CHECK(expectations.Check(*updated_map));
    2252           5 : }
    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          40 : 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          40 :   Expectations expectations(isolate);
    2283             : 
    2284             :   // Create a map, add required properties to it and initialize expectations.
    2285          40 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    2286          40 :   Handle<Map> map = initial_map;
    2287         320 :   for (int i = 0; i < kPropCount; i++) {
    2288         280 :     map = expectations.AddDataField(map, NONE, from.constness,
    2289         280 :                                     from.representation, from.type);
    2290             :   }
    2291          40 :   CHECK(!map->is_deprecated());
    2292          40 :   CHECK(map->is_stable());
    2293          40 :   CHECK(expectations.Check(*map));
    2294             : 
    2295          40 :   Expectations expectations2 = expectations;
    2296             : 
    2297             :   // Apply some special transition to |map|.
    2298          40 :   CHECK(map->owns_descriptors());
    2299          40 :   Handle<Map> map2 = config.Transition(map, expectations2);
    2300             : 
    2301             :   // |map| should still match expectations.
    2302          40 :   CHECK(!map->is_deprecated());
    2303          40 :   CHECK(expectations.Check(*map));
    2304             : 
    2305             :   if (config.generalizes_representations()) {
    2306          70 :     for (int i = 0; i < kPropCount; i++) {
    2307          70 :       expectations2.GeneralizeField(i);
    2308             :     }
    2309             :   }
    2310             : 
    2311          40 :   CHECK(!map2->is_deprecated());
    2312          40 :   CHECK(map2->is_stable());
    2313          40 :   CHECK(expectations2.Check(*map2));
    2314             : 
    2315             :   // Create new maps by generalizing representation of propX field.
    2316         280 :   Handle<Map> maps[kPropCount];
    2317         280 :   for (int i = 0; i < kPropCount; i++) {
    2318             :     Handle<Map> new_map = Map::ReconfigureProperty(isolate, map, i, kData, NONE,
    2319         280 :                                                    to.representation, to.type);
    2320         280 :     maps[i] = new_map;
    2321             : 
    2322         280 :     expectations.SetDataField(i, expected.constness, expected.representation,
    2323         280 :                               expected.type);
    2324             : 
    2325         280 :     CHECK(map->is_deprecated());
    2326         840 :     CHECK_NE(*map, *new_map);
    2327         520 :     CHECK(i == 0 || maps[i - 1]->is_deprecated());
    2328         280 :     CHECK(expectations.Check(*new_map));
    2329             : 
    2330         280 :     Handle<Map> new_map2 = Map::Update(isolate, map2);
    2331         280 :     CHECK(!new_map2->is_deprecated());
    2332         280 :     CHECK(!new_map2->is_dictionary_map());
    2333             : 
    2334             :     Handle<Map> tmp_map;
    2335         560 :     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         840 :       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         490 :       for (int i = 0; i < kPropCount; i++) {
    2348         490 :         expectations2.GeneralizeField(i);
    2349             :       }
    2350         140 :       CHECK(new_map2->GetBackPointer()->IsUndefined(isolate));
    2351          70 :       CHECK(expectations2.Check(*new_map2));
    2352             :     } else {
    2353         210 :       expectations2.SetDataField(i, expected.constness, expected.representation,
    2354         210 :                                  expected.type);
    2355             : 
    2356         420 :       CHECK(!new_map2->GetBackPointer()->IsUndefined(isolate));
    2357         210 :       CHECK(expectations2.Check(*new_map2));
    2358             :     }
    2359             :   }
    2360             : 
    2361          40 :   Handle<Map> active_map = maps[kPropCount - 1];
    2362          40 :   CHECK(!active_map->is_deprecated());
    2363             : 
    2364             :   // Update all deprecated maps and check that they are now the same.
    2365          40 :   Handle<Map> updated_map = Map::Update(isolate, map);
    2366         120 :   CHECK_EQ(*active_map, *updated_map);
    2367          40 :   CheckMigrationTarget(isolate, *map, *updated_map);
    2368         320 :   for (int i = 0; i < kPropCount; i++) {
    2369         280 :     updated_map = Map::Update(isolate, maps[i]);
    2370         840 :     CHECK_EQ(*active_map, *updated_map);
    2371         560 :     CheckMigrationTarget(isolate, *maps[i], *updated_map);
    2372             :   }
    2373          40 : }
    2374             : 
    2375             : 
    2376       25880 : TEST(ElementsKindTransitionFromMapOwningDescriptor) {
    2377           5 :   CcTest::InitializeVM();
    2378           5 :   v8::HandleScope scope(CcTest::isolate());
    2379             :   Isolate* isolate = CcTest::i_isolate();
    2380             : 
    2381           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2382             :   Handle<FieldType> value_type =
    2383           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2384             : 
    2385             :   struct TestConfig {
    2386             :     TestConfig(PropertyAttributes attributes, Handle<Symbol> symbol)
    2387          15 :         : attributes(attributes), symbol(symbol) {}
    2388             : 
    2389          15 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2390             :       expectations.SetElementsKind(DICTIONARY_ELEMENTS);
    2391          15 :       expectations.ChangeAttributesForAllProperties(attributes);
    2392             :       return Map::CopyForPreventExtensions(CcTest::i_isolate(), map, attributes,
    2393          30 :                                            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          20 :   for (size_t i = 0; i < arraysize(configs); i++) {
    2407             :     TestGeneralizeFieldWithSpecialTransition(
    2408             :         configs[i],
    2409             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2410             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2411          15 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2412           5 :   }
    2413           5 : }
    2414             : 
    2415             : 
    2416       25880 : TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
    2417           5 :   CcTest::InitializeVM();
    2418           5 :   v8::HandleScope scope(CcTest::isolate());
    2419             :   Isolate* isolate = CcTest::i_isolate();
    2420             : 
    2421           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2422             :   Handle<FieldType> value_type =
    2423           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2424             : 
    2425             :   struct TestConfig {
    2426             :     TestConfig(PropertyAttributes attributes, Handle<Symbol> symbol)
    2427          15 :         : attributes(attributes), symbol(symbol) {}
    2428             : 
    2429          15 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2430             :       Isolate* isolate = CcTest::i_isolate();
    2431          15 :       Handle<FieldType> any_type = FieldType::Any(isolate);
    2432             : 
    2433             :       // Add one more transition to |map| in order to prevent descriptors
    2434             :       // ownership.
    2435          15 :       CHECK(map->owns_descriptors());
    2436             :       Map::CopyWithField(isolate, map, MakeString("foo"), any_type, NONE,
    2437             :                          PropertyConstness::kMutable, Representation::Smi(),
    2438          15 :                          INSERT_TRANSITION)
    2439          30 :           .ToHandleChecked();
    2440          15 :       CHECK(!map->owns_descriptors());
    2441             : 
    2442             :       expectations.SetElementsKind(DICTIONARY_ELEMENTS);
    2443          15 :       expectations.ChangeAttributesForAllProperties(attributes);
    2444             :       return Map::CopyForPreventExtensions(isolate, map, attributes, symbol,
    2445          15 :                                            "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          20 :   for (size_t i = 0; i < arraysize(configs); i++) {
    2459             :     TestGeneralizeFieldWithSpecialTransition(
    2460             :         configs[i],
    2461             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2462             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2463          15 :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2464           5 :   }
    2465           5 : }
    2466             : 
    2467             : 
    2468       25880 : TEST(PrototypeTransitionFromMapOwningDescriptor) {
    2469           5 :   CcTest::InitializeVM();
    2470           5 :   v8::HandleScope scope(CcTest::isolate());
    2471             :   Isolate* isolate = CcTest::i_isolate();
    2472             : 
    2473           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2474             :   Handle<FieldType> value_type =
    2475           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2476             : 
    2477             :   struct TestConfig {
    2478             :     Handle<JSObject> prototype_;
    2479             : 
    2480           5 :     TestConfig() {
    2481             :       Isolate* isolate = CcTest::i_isolate();
    2482             :       Factory* factory = isolate->factory();
    2483           5 :       prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
    2484           5 :     }
    2485             : 
    2486           5 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2487           5 :       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           5 :   TestConfig config;
    2496             :   TestGeneralizeFieldWithSpecialTransition(
    2497             :       config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2498             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2499           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2500           5 : }
    2501             : 
    2502             : 
    2503       25880 : TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
    2504           5 :   CcTest::InitializeVM();
    2505           5 :   v8::HandleScope scope(CcTest::isolate());
    2506             :   Isolate* isolate = CcTest::i_isolate();
    2507             : 
    2508           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2509             :   Handle<FieldType> value_type =
    2510           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2511             : 
    2512             :   struct TestConfig {
    2513             :     Handle<JSObject> prototype_;
    2514             : 
    2515           5 :     TestConfig() {
    2516             :       Isolate* isolate = CcTest::i_isolate();
    2517             :       Factory* factory = isolate->factory();
    2518           5 :       prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
    2519           5 :     }
    2520             : 
    2521           5 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2522             :       Isolate* isolate = CcTest::i_isolate();
    2523           5 :       Handle<FieldType> any_type = FieldType::Any(isolate);
    2524             : 
    2525             :       // Add one more transition to |map| in order to prevent descriptors
    2526             :       // ownership.
    2527           5 :       CHECK(map->owns_descriptors());
    2528             :       Map::CopyWithField(isolate, map, MakeString("foo"), any_type, NONE,
    2529             :                          PropertyConstness::kMutable, Representation::Smi(),
    2530           5 :                          INSERT_TRANSITION)
    2531          10 :           .ToHandleChecked();
    2532           5 :       CHECK(!map->owns_descriptors());
    2533             : 
    2534           5 :       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           5 :   TestConfig config;
    2543             :   TestGeneralizeFieldWithSpecialTransition(
    2544             :       config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2545             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2546           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2547           5 : }
    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          15 :         value_(value) {}
    2571             : 
    2572             :   Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
    2573             :     return expectations.TransitionToDataField(
    2574          15 :         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          20 :       : attributes_(attributes), value_(value) {}
    2586             : 
    2587             :   Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
    2588          25 :     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           5 :       : attributes_(attributes), pair_(pair) {}
    2600             : 
    2601             :   Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
    2602          10 :     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          10 :         heap_type_(heap_type) {}
    2665             : 
    2666          10 :   void Check(Isolate* isolate, Expectations& expectations2, Handle<Map> map1,
    2667             :              Handle<Map> map2) {
    2668          10 :     CHECK(!map2->is_deprecated());
    2669             : 
    2670          10 :     CHECK(map1->is_deprecated());
    2671          30 :     CHECK_NE(*map1, *map2);
    2672          10 :     Handle<Map> updated_map = Map::Update(isolate, map1);
    2673          30 :     CHECK_EQ(*map2, *updated_map);
    2674          10 :     CheckMigrationTarget(isolate, *map1, *updated_map);
    2675             : 
    2676             :     expectations2.SetDataField(descriptor_, attributes_, constness_,
    2677          10 :                                representation_, heap_type_);
    2678          10 :     CHECK(expectations2.Check(*map2));
    2679          10 :   }
    2680             : };
    2681             : 
    2682             : 
    2683             : // Checks that existing transition was taken as is.
    2684             : struct SameMapChecker {
    2685          15 :   void Check(Isolate* isolate, Expectations& expectations, Handle<Map> map1,
    2686             :              Handle<Map> map2) {
    2687          15 :     CHECK(!map2->is_deprecated());
    2688          45 :     CHECK_EQ(*map1, *map2);
    2689          15 :     CHECK(expectations.Check(*map2));
    2690          15 :   }
    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          45 : static void TestTransitionTo(TransitionOp1& transition_op1,
    2723          15 :                              TransitionOp2& transition_op2, Checker& checker) {
    2724             :   Isolate* isolate = CcTest::i_isolate();
    2725          25 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2726             : 
    2727          25 :   Expectations expectations(isolate);
    2728             : 
    2729             :   // Create a map, add required properties to it and initialize expectations.
    2730          25 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    2731          25 :   Handle<Map> map = initial_map;
    2732         175 :   for (int i = 0; i < kPropCount - 1; i++) {
    2733         150 :     map = expectations.AddDataField(map, NONE, PropertyConstness::kMutable,
    2734             :                                     Representation::Smi(), any_type);
    2735             :   }
    2736          25 :   CHECK(expectations.Check(*map));
    2737             : 
    2738          25 :   Expectations expectations1 = expectations;
    2739             :   Handle<Map> map1 = transition_op1.DoTransition(expectations1, map);
    2740          25 :   CHECK(expectations1.Check(*map1));
    2741             : 
    2742          25 :   Expectations expectations2 = expectations;
    2743          25 :   Handle<Map> map2 = transition_op2.DoTransition(expectations2, map);
    2744             : 
    2745             :   // Let the test customization do the check.
    2746          25 :   checker.Check(isolate, expectations2, map1, map2);
    2747          25 : }
    2748             : 
    2749             : 
    2750       25880 : TEST(TransitionDataFieldToDataField) {
    2751           5 :   CcTest::InitializeVM();
    2752           5 :   v8::HandleScope scope(CcTest::isolate());
    2753             :   Isolate* isolate = CcTest::i_isolate();
    2754             : 
    2755           5 :   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           5 :   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           5 :   TestTransitionTo(transition_op1, transition_op2, checker);
    2769           5 : }
    2770             : 
    2771       25880 : TEST(TransitionDataConstantToSameDataConstant) {
    2772           5 :   CcTest::InitializeVM();
    2773           5 :   v8::HandleScope scope(CcTest::isolate());
    2774             :   Isolate* isolate = CcTest::i_isolate();
    2775             :   Factory* factory = isolate->factory();
    2776             : 
    2777             :   Handle<JSFunction> js_func =
    2778           5 :       factory->NewFunctionForTest(factory->empty_string());
    2779             :   TransitionToDataConstantOperator transition_op(js_func);
    2780             : 
    2781             :   SameMapChecker checker;
    2782           5 :   TestTransitionTo(transition_op, transition_op, checker);
    2783           5 : }
    2784             : 
    2785             : 
    2786       25880 : TEST(TransitionDataConstantToAnotherDataConstant) {
    2787           5 :   CcTest::InitializeVM();
    2788           5 :   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           5 :       Map::CopyInitialMap(isolate, isolate->sloppy_function_map());
    2795             :   Handle<SharedFunctionInfo> info =
    2796           5 :       factory->NewSharedFunctionInfoForBuiltin(name, Builtins::kIllegal);
    2797           5 :   Handle<FieldType> function_type = FieldType::Class(sloppy_map, isolate);
    2798           5 :   CHECK(sloppy_map->is_stable());
    2799             : 
    2800             :   Handle<JSFunction> js_func1 =
    2801          10 :       factory->NewFunction(sloppy_map, info, isolate->native_context());
    2802             :   TransitionToDataConstantOperator transition_op1(js_func1);
    2803             : 
    2804             :   Handle<JSFunction> js_func2 =
    2805          10 :       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           5 :     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           5 :   }
    2818           5 : }
    2819             : 
    2820             : 
    2821       25880 : TEST(TransitionDataConstantToDataField) {
    2822           5 :   CcTest::InitializeVM();
    2823           5 :   v8::HandleScope scope(CcTest::isolate());
    2824             :   Isolate* isolate = CcTest::i_isolate();
    2825             :   Factory* factory = isolate->factory();
    2826             : 
    2827           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2828             : 
    2829             :   Handle<JSFunction> js_func1 =
    2830           5 :       factory->NewFunctionForTest(factory->empty_string());
    2831             :   TransitionToDataConstantOperator transition_op1(js_func1);
    2832             : 
    2833           5 :   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           5 :   TestTransitionTo(transition_op1, transition_op2, checker);
    2841           5 : }
    2842             : 
    2843             : 
    2844       25880 : TEST(TransitionAccessorConstantToSameAccessorConstant) {
    2845           5 :   CcTest::InitializeVM();
    2846           5 :   v8::HandleScope scope(CcTest::isolate());
    2847             : 
    2848           5 :   Handle<AccessorPair> pair = CreateAccessorPair(true, true);
    2849             :   TransitionToAccessorConstantOperator transition_op(pair);
    2850             : 
    2851             :   SameMapChecker checker;
    2852           5 :   TestTransitionTo(transition_op, transition_op, checker);
    2853           5 : }
    2854             : 
    2855             : // TODO(ishell): add this test once IS_ACCESSOR_FIELD_SUPPORTED is supported.
    2856             : // TEST(TransitionAccessorConstantToAnotherAccessorConstant)
    2857             : 
    2858       25880 : TEST(HoleyMutableHeapNumber) {
    2859           5 :   CcTest::InitializeVM();
    2860           5 :   v8::HandleScope scope(CcTest::isolate());
    2861             :   Isolate* isolate = CcTest::i_isolate();
    2862             : 
    2863             :   auto mhn = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
    2864           5 :   CHECK_EQ(kHoleNanInt64, mhn->value_as_bits());
    2865             : 
    2866           5 :   mhn = isolate->factory()->NewMutableHeapNumber(0.0);
    2867           5 :   CHECK_EQ(uint64_t{0}, mhn->value_as_bits());
    2868             : 
    2869             :   mhn->set_value_as_bits(kHoleNanInt64);
    2870           5 :   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           5 :                             Representation::Double());
    2878          10 :   CHECK(obj->IsMutableHeapNumber());
    2879           5 :   CHECK_EQ(kHoleNanInt64, MutableHeapNumber::cast(*obj)->value_as_bits());
    2880             : 
    2881           5 :   obj = Object::NewStorageFor(isolate, mhn, Representation::Double());
    2882          10 :   CHECK(obj->IsMutableHeapNumber());
    2883           5 :   CHECK_EQ(kHoleNanInt64, MutableHeapNumber::cast(*obj)->value_as_bits());
    2884           5 : }
    2885             : 
    2886             : }  // namespace test_field_type_tracking
    2887             : }  // namespace compiler
    2888             : }  // namespace internal
    2889       77625 : }  // namespace v8

Generated by: LCOV version 1.10