LCOV - code coverage report
Current view: top level - test/cctest - test-field-type-tracking.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1006 1032 97.5 %
Date: 2019-01-20 Functions: 106 107 99.1 %

          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/property.h"
      26             : #include "src/transitions.h"
      27             : 
      28             : namespace v8 {
      29             : namespace internal {
      30             : namespace compiler {
      31             : namespace test_field_type_tracking {
      32             : 
      33             : // TODO(ishell): fix this once TransitionToPrototype stops generalizing
      34             : // all field representations (similar to crbug/448711 where elements kind
      35             : // and observed transitions caused generalization of all fields).
      36             : const bool IS_PROTO_TRANS_ISSUE_FIXED = false;
      37             : 
      38             : 
      39             : // TODO(ishell): fix this once TransitionToAccessorProperty is able to always
      40             : // keep map in fast mode.
      41             : const bool IS_ACCESSOR_FIELD_SUPPORTED = false;
      42             : 
      43             : 
      44             : // Number of properties used in the tests.
      45             : const int kPropCount = 7;
      46             : 
      47             : 
      48             : //
      49             : // Helper functions.
      50             : //
      51             : 
      52             : static Handle<String> MakeString(const char* str) {
      53             :   Isolate* isolate = CcTest::i_isolate();
      54             :   Factory* factory = isolate->factory();
      55       11005 :   return factory->InternalizeUtf8String(str);
      56             : }
      57             : 
      58             : 
      59       10995 : static Handle<String> MakeName(const char* str, int suffix) {
      60             :   EmbeddedVector<char, 128> buffer;
      61       10995 :   SNPrintF(buffer, "%s%d", str, suffix);
      62       21990 :   return MakeString(buffer.start());
      63             : }
      64             : 
      65             : 
      66          40 : static Handle<AccessorPair> CreateAccessorPair(bool with_getter,
      67             :                                                bool with_setter) {
      68             :   Isolate* isolate = CcTest::i_isolate();
      69             :   Factory* factory = isolate->factory();
      70          40 :   Handle<AccessorPair> pair = factory->NewAccessorPair();
      71          40 :   Handle<String> empty_string = factory->empty_string();
      72          40 :   if (with_getter) {
      73          40 :     Handle<JSFunction> func = factory->NewFunctionForTest(empty_string);
      74          80 :     pair->set_getter(*func);
      75             :   }
      76          40 :   if (with_setter) {
      77          40 :     Handle<JSFunction> func = factory->NewFunctionForTest(empty_string);
      78          80 :     pair->set_setter(*func);
      79             :   }
      80          40 :   return pair;
      81             : }
      82             : 
      83             : // Check cached migration target map after Map::Update() and Map::TryUpdate()
      84         500 : static void CheckMigrationTarget(Isolate* isolate, Map old_map, Map new_map) {
      85             :   Map target = TransitionsAccessor(isolate, handle(old_map, isolate))
      86         500 :                    .GetMigrationTarget();
      87        1000 :   if (target.is_null()) return;
      88           0 :   CHECK_EQ(new_map, target);
      89           0 :   CHECK_EQ(Map::TryUpdateSlow(isolate, old_map), target);
      90             : }
      91             : 
      92             : class Expectations {
      93             :   static const int MAX_PROPERTIES = 10;
      94             :   Isolate* isolate_;
      95             :   ElementsKind elements_kind_;
      96             :   PropertyKind kinds_[MAX_PROPERTIES];
      97             :   PropertyLocation locations_[MAX_PROPERTIES];
      98             :   PropertyConstness constnesses_[MAX_PROPERTIES];
      99             :   PropertyAttributes attributes_[MAX_PROPERTIES];
     100             :   Representation representations_[MAX_PROPERTIES];
     101             :   // FieldType for kField, value for DATA_CONSTANT and getter for
     102             :   // ACCESSOR_CONSTANT.
     103             :   Handle<Object> values_[MAX_PROPERTIES];
     104             :   // Setter for ACCESSOR_CONSTANT.
     105             :   Handle<Object> setter_values_[MAX_PROPERTIES];
     106             :   int number_of_properties_;
     107             : 
     108             :  public:
     109         450 :   explicit Expectations(Isolate* isolate, ElementsKind elements_kind)
     110             :       : isolate_(isolate),
     111             :         elements_kind_(elements_kind),
     112       13950 :         number_of_properties_(0) {}
     113             : 
     114         390 :   explicit Expectations(Isolate* isolate)
     115             :       : Expectations(
     116             :             isolate,
     117        1170 :             isolate->object_function()->initial_map()->elements_kind()) {}
     118             : 
     119        3990 :   void Init(int index, PropertyKind kind, PropertyAttributes attributes,
     120             :             PropertyConstness constness, PropertyLocation location,
     121             :             Representation representation, Handle<Object> value) {
     122        3990 :     CHECK(index < MAX_PROPERTIES);
     123        3990 :     kinds_[index] = kind;
     124        3990 :     locations_[index] = location;
     125       11865 :     if (kind == kData && location == kField &&
     126        4440 :         IsTransitionableFastElementsKind(elements_kind_) &&
     127             :         Map::IsInplaceGeneralizableField(constness, representation,
     128         450 :                                          FieldType::cast(*value))) {
     129             :       // Maps with transitionable elements kinds must have non in-place
     130             :       // generalizable fields.
     131             :       if (FLAG_track_constant_fields && FLAG_modify_map_inplace &&
     132             :           constness == PropertyConstness::kConst) {
     133             :         constness = PropertyConstness::kMutable;
     134             :       }
     135         450 :       if (representation.IsHeapObject() && !FieldType::cast(*value)->IsAny()) {
     136         150 :         value = FieldType::Any(isolate_);
     137             :       }
     138             :     }
     139        3990 :     constnesses_[index] = constness;
     140        3990 :     attributes_[index] = attributes;
     141        3990 :     representations_[index] = representation;
     142        3990 :     values_[index] = value;
     143        3990 :   }
     144             : 
     145           0 :   void Print() const {
     146           0 :     StdoutStream os;
     147           0 :     os << "Expectations: #" << number_of_properties_ << "\n";
     148           0 :     for (int i = 0; i < number_of_properties_; i++) {
     149           0 :       os << " " << i << ": ";
     150           0 :       os << "Descriptor @ ";
     151             : 
     152           0 :       if (kinds_[i] == kData) {
     153           0 :         os << Brief(*values_[i]);
     154             :       } else {
     155             :         // kAccessor
     156           0 :         os << "(get: " << Brief(*values_[i])
     157           0 :            << ", set: " << Brief(*setter_values_[i]) << ") ";
     158             :       }
     159             : 
     160           0 :       os << " (";
     161           0 :       if (constnesses_[i] == PropertyConstness::kConst) os << "const ";
     162           0 :       os << (kinds_[i] == kData ? "data " : "accessor ");
     163           0 :       if (locations_[i] == kField) {
     164           0 :         os << "field"
     165           0 :            << ": " << representations_[i].Mnemonic();
     166             :       } else {
     167           0 :         os << "descriptor";
     168             :       }
     169           0 :       os << ", attrs: " << attributes_[i] << ")\n";
     170             :     }
     171           0 :     os << "\n";
     172           0 :   }
     173             : 
     174             :   void SetElementsKind(ElementsKind elements_kind) {
     175          10 :     elements_kind_ = elements_kind;
     176             :   }
     177             : 
     178             :   Handle<FieldType> GetFieldType(int index) {
     179             :     CHECK(index < MAX_PROPERTIES);
     180             :     CHECK_EQ(kField, locations_[index]);
     181             :     return Handle<FieldType>::cast(values_[index]);
     182             :   }
     183             : 
     184             :   void SetDataField(int index, PropertyAttributes attrs,
     185             :                     PropertyConstness constness, Representation representation,
     186             :                     Handle<FieldType> field_type) {
     187        3885 :     Init(index, kData, attrs, constness, kField, representation, field_type);
     188             :   }
     189             : 
     190         665 :   void SetDataField(int index, PropertyConstness constness,
     191             :                     Representation representation,
     192             :                     Handle<FieldType> field_type) {
     193             :     SetDataField(index, attributes_[index], constness, representation,
     194         665 :                  field_type);
     195         665 :   }
     196             : 
     197             :   void SetAccessorField(int index, PropertyAttributes attrs) {
     198             :     Init(index, kAccessor, attrs, PropertyConstness::kConst, kDescriptor,
     199             :          Representation::Tagged(), FieldType::Any(isolate_));
     200             :   }
     201             : 
     202             :   void SetAccessorField(int index) {
     203             :     SetAccessorField(index, attributes_[index]);
     204             :   }
     205             : 
     206          50 :   void SetDataConstant(int index, PropertyAttributes attrs,
     207             :                        Handle<JSFunction> value) {
     208             :     if (FLAG_track_constant_fields) {
     209             :       Handle<FieldType> field_type(FieldType::Class(value->map()), isolate_);
     210             :       Init(index, kData, attrs, PropertyConstness::kConst, kField,
     211             :            Representation::HeapObject(), field_type);
     212             : 
     213             :     } else {
     214             :       Init(index, kData, attrs, PropertyConstness::kConst, kDescriptor,
     215          50 :            Representation::HeapObject(), value);
     216             :     }
     217          50 :   }
     218             : 
     219             :   void SetDataConstant(int index, Handle<JSFunction> value) {
     220             :     SetDataConstant(index, attributes_[index], value);
     221             :   }
     222             : 
     223             :   void SetAccessorConstant(int index, PropertyAttributes attrs,
     224             :                            Handle<Object> getter, Handle<Object> setter) {
     225             :     Init(index, kAccessor, attrs, PropertyConstness::kConst, kDescriptor,
     226          55 :          Representation::Tagged(), getter);
     227          55 :     setter_values_[index] = setter;
     228             :   }
     229             : 
     230             :   void SetAccessorConstantComponent(int index, PropertyAttributes attrs,
     231             :                                     AccessorComponent component,
     232             :                                     Handle<Object> accessor) {
     233             :     CHECK_EQ(kAccessor, kinds_[index]);
     234             :     CHECK_EQ(kDescriptor, locations_[index]);
     235             :     CHECK(index < number_of_properties_);
     236             :     if (component == ACCESSOR_GETTER) {
     237             :       values_[index] = accessor;
     238             :     } else {
     239             :       setter_values_[index] = accessor;
     240             :     }
     241             :   }
     242             : 
     243          50 :   void SetAccessorConstant(int index, PropertyAttributes attrs,
     244             :                            Handle<AccessorPair> pair) {
     245         150 :     Handle<Object> getter = handle(pair->getter(), isolate_);
     246         150 :     Handle<Object> setter = handle(pair->setter(), isolate_);
     247             :     SetAccessorConstant(index, attrs, getter, setter);
     248          50 :   }
     249             : 
     250           5 :   void SetAccessorConstant(int index, Handle<Object> getter,
     251             :                            Handle<Object> setter) {
     252           5 :     SetAccessorConstant(index, attributes_[index], getter, setter);
     253           5 :   }
     254             : 
     255           5 :   void SetAccessorConstant(int index, Handle<AccessorPair> pair) {
     256          15 :     Handle<Object> getter = handle(pair->getter(), isolate_);
     257          15 :     Handle<Object> setter = handle(pair->setter(), isolate_);
     258           5 :     SetAccessorConstant(index, getter, setter);
     259           5 :   }
     260             : 
     261        1085 :   void GeneralizeField(int index) {
     262        1085 :     CHECK(index < number_of_properties_);
     263        1085 :     representations_[index] = Representation::Tagged();
     264        1085 :     if (locations_[index] == kField) {
     265        1080 :       values_[index] = FieldType::Any(isolate_);
     266             :     }
     267        1085 :   }
     268             : 
     269        9395 :   bool Check(DescriptorArray descriptors, int descriptor) const {
     270        9395 :     PropertyDetails details = descriptors->GetDetails(descriptor);
     271             : 
     272        9395 :     if (details.kind() != kinds_[descriptor]) return false;
     273        9395 :     if (details.location() != locations_[descriptor]) return false;
     274        9395 :     if (details.constness() != constnesses_[descriptor]) return false;
     275             : 
     276        9395 :     PropertyAttributes expected_attributes = attributes_[descriptor];
     277        9395 :     if (details.attributes() != expected_attributes) return false;
     278             : 
     279        9395 :     Representation expected_representation = representations_[descriptor];
     280        9395 :     if (!details.representation().Equals(expected_representation)) return false;
     281             : 
     282        9395 :     Object expected_value = *values_[descriptor];
     283        9395 :     if (details.location() == kField) {
     284        9215 :       if (details.kind() == kData) {
     285        9215 :         FieldType type = descriptors->GetFieldType(descriptor);
     286       18430 :         return FieldType::cast(expected_value) == type;
     287             :       } else {
     288             :         // kAccessor
     289           0 :         UNREACHABLE();
     290             :       }
     291             :     } else {
     292         180 :       Object value = descriptors->GetStrongValue(descriptor);
     293             :       // kDescriptor
     294         180 :       if (details.kind() == kData) {
     295             :         CHECK(!FLAG_track_constant_fields);
     296          65 :         return value == expected_value;
     297             :       } else {
     298             :         // kAccessor
     299         115 :         if (value == expected_value) return true;
     300         115 :         if (!value->IsAccessorPair()) return false;
     301         115 :         AccessorPair pair = AccessorPair::cast(value);
     302         230 :         return pair->Equals(expected_value, *setter_values_[descriptor]);
     303             :       }
     304             :     }
     305             :     UNREACHABLE();
     306             :   }
     307             : 
     308        1415 :   bool Check(Map map, int expected_nof) const {
     309        1415 :     CHECK_EQ(elements_kind_, map->elements_kind());
     310        1415 :     CHECK(number_of_properties_ <= MAX_PROPERTIES);
     311        1415 :     CHECK_EQ(expected_nof, map->NumberOfOwnDescriptors());
     312        1415 :     CHECK(!map->is_dictionary_map());
     313             : 
     314        1415 :     DescriptorArray descriptors = map->instance_descriptors();
     315        1415 :     CHECK(expected_nof <= number_of_properties_);
     316        9395 :     for (int i = 0; i < expected_nof; i++) {
     317        9395 :       if (!Check(descriptors, i)) {
     318           0 :         Print();
     319             : #ifdef OBJECT_PRINT
     320             :         descriptors->Print();
     321             : #endif
     322           0 :         Check(descriptors, i);
     323           0 :         return false;
     324             :       }
     325             :     }
     326             :     return true;
     327             :   }
     328             : 
     329        1345 :   bool Check(Map map) const { return Check(map, number_of_properties_); }
     330             : 
     331             :   //
     332             :   // Helper methods for initializing expectations and adding properties to
     333             :   // given |map|.
     334             :   //
     335             : 
     336          30 :   Handle<Map> AsElementsKind(Handle<Map> map, ElementsKind elements_kind) {
     337          30 :     elements_kind_ = elements_kind;
     338          30 :     map = Map::AsElementsKind(isolate_, map, elements_kind);
     339          30 :     CHECK_EQ(elements_kind_, map->elements_kind());
     340          30 :     return map;
     341             :   }
     342             : 
     343        3090 :   Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
     344             :                            PropertyConstness constness,
     345             :                            Representation representation,
     346             :                            Handle<FieldType> field_type) {
     347        3090 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     348        3090 :     int property_index = number_of_properties_++;
     349             :     SetDataField(property_index, attributes, constness, representation,
     350             :                  field_type);
     351             : 
     352        3090 :     Handle<String> name = MakeName("prop", property_index);
     353             :     return Map::CopyWithField(isolate_, map, name, field_type, attributes,
     354        6180 :                               constness, representation, INSERT_TRANSITION)
     355        9270 :         .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          90 :   Handle<Map> FollowDataTransition(Handle<Map> map,
     400             :                                    PropertyAttributes attributes,
     401             :                                    PropertyConstness constness,
     402             :                                    Representation representation,
     403             :                                    Handle<FieldType> heap_type) {
     404          90 :     CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
     405          90 :     int property_index = number_of_properties_++;
     406             :     SetDataField(property_index, attributes, constness, representation,
     407             :                  heap_type);
     408             : 
     409          90 :     Handle<String> name = MakeName("prop", property_index);
     410             :     Map target = TransitionsAccessor(isolate_, map)
     411          90 :                      .SearchTransition(*name, kData, attributes);
     412          90 :     CHECK(!target.is_null());
     413         180 :     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          20 :     Handle<Object> getter(pair->getter(), isolate);
     468          20 :     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       28342 : 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       28342 : 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          10 :   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       28342 : 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       28342 : 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       28342 : 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       28342 : 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       28342 : 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       28342 : 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       28342 : 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       28342 : 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       28342 : 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       28342 : 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          20 : static void TestReconfigureDataFieldAttribute_GeneralizeField(
    1003             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
    1004          20 :   Isolate* isolate = CcTest::i_isolate();
    1005             : 
    1006          20 :   Expectations expectations(isolate);
    1007             : 
    1008             :   // Create a map, add required properties to it and initialize expectations.
    1009          20 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1010          20 :   Handle<Map> map = initial_map;
    1011         160 :   for (int i = 0; i < kPropCount; i++) {
    1012             :     map = expectations.AddDataField(map, NONE, from.constness,
    1013         140 :                                     from.representation, from.type);
    1014             :   }
    1015          20 :   CHECK(!map->is_deprecated());
    1016          20 :   CHECK(map->is_stable());
    1017          20 :   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          20 :   Expectations expectations2(isolate);
    1024             : 
    1025             :   Handle<Map> map2 = initial_map;
    1026          80 :   for (int i = 0; i < kSplitProp; i++) {
    1027             :     map2 = expectations2.FollowDataTransition(map2, NONE, from.constness,
    1028          60 :                                               from.representation, from.type);
    1029             :   }
    1030             :   map2 = expectations2.AddDataField(map2, READ_ONLY, to.constness,
    1031          20 :                                     to.representation, to.type);
    1032             : 
    1033          80 :   for (int i = kSplitProp + 1; i < kPropCount; i++) {
    1034             :     map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1035          60 :                                       to.representation, to.type);
    1036             :   }
    1037          20 :   CHECK(!map2->is_deprecated());
    1038          20 :   CHECK(map2->is_stable());
    1039          20 :   CHECK(expectations2.Check(*map2));
    1040             : 
    1041          20 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1042          40 :   CanonicalHandleScope canonical(isolate);
    1043          20 :   JSHeapBroker broker(isolate, &zone);
    1044          20 :   CompilationDependencies dependencies(isolate, &zone);
    1045             :   MapRef map_ref(&broker, map);
    1046          20 :   map_ref.SerializeOwnDescriptors();
    1047          20 :   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          20 :       Map::ReconfigureExistingProperty(isolate, map2, kSplitProp, kData, NONE);
    1053             : 
    1054             :   // |map2| should be left unchanged but marked unstable.
    1055          20 :   CHECK(!map2->is_stable());
    1056          20 :   CHECK(!map2->is_deprecated());
    1057          60 :   CHECK_NE(*map2, *new_map);
    1058          20 :   CHECK(expectations2.Check(*map2));
    1059             : 
    1060             :   // |map| should be deprecated and |new_map| should match new expectations.
    1061          80 :   for (int i = kSplitProp; i < kPropCount; i++) {
    1062             :     expectations.SetDataField(i, expected.constness, expected.representation,
    1063          80 :                               expected.type);
    1064             :   }
    1065          20 :   CHECK(map->is_deprecated());
    1066          20 :   CHECK(dependencies.AreValid());
    1067          60 :   CHECK_NE(*map, *new_map);
    1068             : 
    1069          20 :   CHECK(!new_map->is_deprecated());
    1070          20 :   CHECK(expectations.Check(*new_map));
    1071             : 
    1072             :   // Update deprecated |map|, it should become |new_map|.
    1073          20 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1074          60 :   CHECK_EQ(*new_map, *updated_map);
    1075          40 :   CheckMigrationTarget(isolate, *map, *updated_map);
    1076          20 : }
    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          10 : static void TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1089             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected,
    1090             :     bool expected_field_type_dependency = true) {
    1091          10 :   Isolate* isolate = CcTest::i_isolate();
    1092             : 
    1093          10 :   Expectations expectations(isolate);
    1094             : 
    1095             :   // Create a map, add required properties to it and initialize expectations.
    1096          10 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1097          10 :   Handle<Map> map = initial_map;
    1098          80 :   for (int i = 0; i < kPropCount; i++) {
    1099             :     map = expectations.AddDataField(map, NONE, from.constness,
    1100          70 :                                     from.representation, from.type);
    1101             :   }
    1102          10 :   CHECK(!map->is_deprecated());
    1103          10 :   CHECK(map->is_stable());
    1104          10 :   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          10 :   Expectations expectations2(isolate);
    1111             : 
    1112             :   Handle<Map> map2 = initial_map;
    1113          40 :   for (int i = 0; i < kSplitProp; i++) {
    1114             :     map2 = expectations2.FollowDataTransition(map2, NONE, from.constness,
    1115          30 :                                               from.representation, from.type);
    1116             :   }
    1117             :   map2 = expectations2.AddDataField(map2, READ_ONLY, to.constness,
    1118          10 :                                     to.representation, to.type);
    1119             : 
    1120          40 :   for (int i = kSplitProp + 1; i < kPropCount; i++) {
    1121             :     map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1122          30 :                                       to.representation, to.type);
    1123             :   }
    1124          10 :   CHECK(!map2->is_deprecated());
    1125          10 :   CHECK(map2->is_stable());
    1126          10 :   CHECK(expectations2.Check(*map2));
    1127             : 
    1128          10 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1129          20 :   CanonicalHandleScope canonical(isolate);
    1130          10 :   JSHeapBroker broker(isolate, &zone);
    1131          10 :   CompilationDependencies dependencies(isolate, &zone);
    1132             :   MapRef map_ref(&broker, map);
    1133          10 :   map_ref.SerializeOwnDescriptors();
    1134          10 :   dependencies.DependOnFieldType(map_ref, kSplitProp);
    1135             : 
    1136             :   // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
    1137             :   // should generalize representations in |map1|.
    1138             :   Handle<Map> new_map =
    1139          10 :       Map::ReconfigureExistingProperty(isolate, map2, kSplitProp, kData, NONE);
    1140             : 
    1141             :   // |map2| should be left unchanged but marked unstable.
    1142          10 :   CHECK(!map2->is_stable());
    1143          10 :   CHECK(!map2->is_deprecated());
    1144          30 :   CHECK_NE(*map2, *new_map);
    1145          10 :   CHECK(expectations2.Check(*map2));
    1146             : 
    1147             :   // In trivial case |map| should be returned as a result of the property
    1148             :   // reconfiguration, respective field types should be generalized and
    1149             :   // respective code dependencies should be invalidated. |map| should be NOT
    1150             :   // deprecated and it should match new expectations.
    1151          40 :   for (int i = kSplitProp; i < kPropCount; i++) {
    1152             :     expectations.SetDataField(i, expected.constness, expected.representation,
    1153          40 :                               expected.type);
    1154             :   }
    1155          10 :   CHECK(!map->is_deprecated());
    1156          30 :   CHECK_EQ(*map, *new_map);
    1157          10 :   CHECK_EQ(expected_field_type_dependency, !dependencies.AreValid());
    1158             : 
    1159          10 :   CHECK(!new_map->is_deprecated());
    1160          10 :   CHECK(expectations.Check(*new_map));
    1161             : 
    1162          10 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1163          40 :   CHECK_EQ(*new_map, *updated_map);
    1164          10 : }
    1165             : 
    1166       28342 : TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToDouble) {
    1167           5 :   CcTest::InitializeVM();
    1168           5 :   v8::HandleScope scope(CcTest::isolate());
    1169             :   Isolate* isolate = CcTest::i_isolate();
    1170             : 
    1171           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1172             : 
    1173             :   if (FLAG_track_constant_fields) {
    1174             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1175             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1176             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1177             :         {PropertyConstness::kConst, Representation::Double(), any_type});
    1178             : 
    1179             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1180             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1181             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    1182             :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1183             : 
    1184             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1185             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1186             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1187             :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1188             :   }
    1189             : 
    1190             :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1191             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1192             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    1193           5 :       {PropertyConstness::kMutable, Representation::Double(), any_type});
    1194           5 : }
    1195             : 
    1196       28342 : TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
    1197           5 :   CcTest::InitializeVM();
    1198           5 :   v8::HandleScope scope(CcTest::isolate());
    1199             :   Isolate* isolate = CcTest::i_isolate();
    1200             : 
    1201           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1202             :   Handle<FieldType> value_type =
    1203           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1204             : 
    1205             :   if (FLAG_track_constant_fields) {
    1206             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1207             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1208             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1209             :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    1210             : 
    1211             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1212             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1213             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1214             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1215             : 
    1216             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1217             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1218             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1219             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1220             :   }
    1221             : 
    1222             :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1223             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1224             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1225           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1226           5 : }
    1227             : 
    1228       28342 : TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
    1229           5 :   CcTest::InitializeVM();
    1230           5 :   v8::HandleScope scope(CcTest::isolate());
    1231             :   Isolate* isolate = CcTest::i_isolate();
    1232             : 
    1233           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1234             :   Handle<FieldType> value_type =
    1235           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1236             : 
    1237             :   if (FLAG_track_constant_fields) {
    1238             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1239             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1240             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1241             :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    1242             : 
    1243             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1244             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1245             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1246             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1247             : 
    1248             :     TestReconfigureDataFieldAttribute_GeneralizeField(
    1249             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    1250             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1251             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1252             :   }
    1253             : 
    1254             :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1255             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    1256             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1257           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1258           5 : }
    1259             : 
    1260       28342 : TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjFieldToHeapObj) {
    1261           5 :   CcTest::InitializeVM();
    1262           5 :   v8::HandleScope scope(CcTest::isolate());
    1263             :   Isolate* isolate = CcTest::i_isolate();
    1264             : 
    1265           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1266             : 
    1267             :   Handle<FieldType> current_type =
    1268           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1269             : 
    1270             :   Handle<FieldType> new_type =
    1271           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1272             : 
    1273           5 :   Handle<FieldType> expected_type = any_type;
    1274             : 
    1275             :   // Check generalizations that trigger deopts.
    1276             :   if (FLAG_track_constant_fields) {
    1277             :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1278             :         {PropertyConstness::kConst, Representation::HeapObject(), current_type},
    1279             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1280             :         {PropertyConstness::kConst, Representation::HeapObject(),
    1281             :          expected_type});
    1282             : 
    1283             :     if (FLAG_modify_map_inplace) {
    1284             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration does
    1285             :       // not create a new map, therefore trivial generalization.
    1286             :       TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1287             :           {PropertyConstness::kConst, Representation::HeapObject(),
    1288             :            current_type},
    1289             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1290             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1291             :            expected_type});
    1292             :     } else {
    1293             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration
    1294             :       // causes map change, therefore non-trivial generalization.
    1295             :       TestReconfigureDataFieldAttribute_GeneralizeField(
    1296             :           {PropertyConstness::kConst, Representation::HeapObject(),
    1297             :            current_type},
    1298             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1299             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1300             :            expected_type});
    1301             :     }
    1302             :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1303             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    1304             :          current_type},
    1305             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1306             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    1307             :          expected_type});
    1308             :   }
    1309             :   TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1310             :       {PropertyConstness::kMutable, Representation::HeapObject(), current_type},
    1311             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1312             :       {PropertyConstness::kMutable, Representation::HeapObject(),
    1313           5 :        expected_type});
    1314             :   current_type = expected_type;
    1315             : 
    1316             :   // Check generalizations that do not trigger deopts.
    1317           5 :   new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
    1318             : 
    1319             :   if (FLAG_track_constant_fields) {
    1320             :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1321             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1322             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1323             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1324             :         false);
    1325             : 
    1326             :     if (FLAG_modify_map_inplace) {
    1327             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration does
    1328             :       // not create a new map, therefore trivial generalization.
    1329             :       TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1330             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1331             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1332             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1333             :            any_type});
    1334             :     } else {
    1335             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration
    1336             :       // causes map change, therefore non-trivial generalization.
    1337             :       TestReconfigureDataFieldAttribute_GeneralizeField(
    1338             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    1339             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1340             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    1341             :            any_type});
    1342             :     }
    1343             :     TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1344             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1345             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    1346             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1347             :         false);
    1348             :   }
    1349             :   TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
    1350             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1351             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    1352             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    1353           5 :       false);
    1354           5 : }
    1355             : 
    1356       28342 : TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjectFieldToTagged) {
    1357           5 :   CcTest::InitializeVM();
    1358           5 :   v8::HandleScope scope(CcTest::isolate());
    1359             :   Isolate* isolate = CcTest::i_isolate();
    1360             : 
    1361           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1362             :   Handle<FieldType> value_type =
    1363           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1364             : 
    1365             :   TestReconfigureDataFieldAttribute_GeneralizeField(
    1366             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    1367             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1368           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    1369           5 : }
    1370             : 
    1371             : 
    1372             : // Checks that given |map| is deprecated and that it updates to given |new_map|
    1373             : // which in turn should match expectations.
    1374             : struct CheckDeprecated {
    1375           5 :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1376             :              const Expectations& expectations) {
    1377           5 :     CHECK(map->is_deprecated());
    1378          15 :     CHECK_NE(*map, *new_map);
    1379             : 
    1380           5 :     CHECK(!new_map->is_deprecated());
    1381           5 :     CHECK(expectations.Check(*new_map));
    1382             : 
    1383             :     // Update deprecated |map|, it should become |new_map|.
    1384           5 :     Handle<Map> updated_map = Map::Update(isolate, map);
    1385          15 :     CHECK_EQ(*new_map, *updated_map);
    1386           5 :     CheckMigrationTarget(isolate, *map, *updated_map);
    1387           5 :   }
    1388             : };
    1389             : 
    1390             : 
    1391             : // Checks that given |map| is NOT deprecated, equals to given |new_map| and
    1392             : // matches expectations.
    1393             : struct CheckSameMap {
    1394          10 :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1395             :              const Expectations& expectations) {
    1396             :     // |map| was not reconfigured, therefore it should stay stable.
    1397          10 :     CHECK(map->is_stable());
    1398          10 :     CHECK(!map->is_deprecated());
    1399          30 :     CHECK_EQ(*map, *new_map);
    1400             : 
    1401          10 :     CHECK(!new_map->is_deprecated());
    1402          10 :     CHECK(expectations.Check(*new_map));
    1403             : 
    1404             :     // Update deprecated |map|, it should become |new_map|.
    1405          10 :     Handle<Map> updated_map = Map::Update(isolate, map);
    1406          30 :     CHECK_EQ(*new_map, *updated_map);
    1407          10 :   }
    1408             : };
    1409             : 
    1410             : 
    1411             : // Checks that given |map| is NOT deprecated and matches expectations.
    1412             : // |new_map| is unrelated to |map|.
    1413             : struct CheckUnrelated {
    1414          10 :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1415             :              const Expectations& expectations) {
    1416          10 :     CHECK(!map->is_deprecated());
    1417          30 :     CHECK_NE(*map, *new_map);
    1418          10 :     CHECK(expectations.Check(*map));
    1419             : 
    1420          10 :     CHECK(new_map->is_stable());
    1421          10 :     CHECK(!new_map->is_deprecated());
    1422          10 :   }
    1423             : };
    1424             : 
    1425             : 
    1426             : // Checks that given |map| is NOT deprecated, and |new_map| is a result of
    1427             : // copy-generalize-all-representations.
    1428             : struct CheckCopyGeneralizeAllFields {
    1429           5 :   void Check(Isolate* isolate, Handle<Map> map, Handle<Map> new_map,
    1430             :              Expectations& expectations) {
    1431           5 :     CHECK(!map->is_deprecated());
    1432          15 :     CHECK_NE(*map, *new_map);
    1433             : 
    1434          10 :     CHECK(new_map->GetBackPointer()->IsUndefined(isolate));
    1435          35 :     for (int i = 0; i < kPropCount; i++) {
    1436          35 :       expectations.GeneralizeField(i);
    1437             :     }
    1438             : 
    1439           5 :     CHECK(!new_map->is_deprecated());
    1440           5 :     CHECK(expectations.Check(*new_map));
    1441           5 :   }
    1442             : };
    1443             : 
    1444             : // This test ensures that field generalization is correctly propagated from one
    1445             : // branch of transition tree (|map2|) to another (|map1|).
    1446             : //
    1447             : //             + - p2B - p3 - p4: |map2|
    1448             : //             |
    1449             : //  {} - p0 - p1: |map|
    1450             : //             |
    1451             : //             + - p2A - p3 - p4: |map1|
    1452             : //                        |
    1453             : //                        + - the property customized by the TestConfig provided
    1454             : //
    1455             : // where "p2A" and "p2B" differ only in the attributes.
    1456             : //
    1457             : template <typename TestConfig, typename Checker>
    1458          30 : static void TestReconfigureProperty_CustomPropertyAfterTargetMap(
    1459             :     TestConfig& config, Checker& checker) {
    1460             :   Isolate* isolate = CcTest::i_isolate();
    1461          30 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1462             : 
    1463             :   const int kCustomPropIndex = kPropCount - 2;
    1464          30 :   Expectations expectations(isolate);
    1465             : 
    1466             :   const int kSplitProp = 2;
    1467             :   CHECK_LT(kSplitProp, kCustomPropIndex);
    1468             : 
    1469             :   const PropertyConstness constness = PropertyConstness::kMutable;
    1470          30 :   const Representation representation = Representation::Smi();
    1471             : 
    1472             :   // Create common part of transition tree.
    1473          30 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1474          30 :   Handle<Map> map = initial_map;
    1475          90 :   for (int i = 0; i < kSplitProp; i++) {
    1476          60 :     map = expectations.AddDataField(map, NONE, constness, representation,
    1477             :                                     any_type);
    1478             :   }
    1479          30 :   CHECK(!map->is_deprecated());
    1480          30 :   CHECK(map->is_stable());
    1481          30 :   CHECK(expectations.Check(*map));
    1482             : 
    1483             : 
    1484             :   // Create branch to |map1|.
    1485             :   Handle<Map> map1 = map;
    1486          30 :   Expectations expectations1 = expectations;
    1487         120 :   for (int i = kSplitProp; i < kCustomPropIndex; i++) {
    1488          90 :     map1 = expectations1.AddDataField(map1, NONE, constness, representation,
    1489             :                                       any_type);
    1490             :   }
    1491          30 :   map1 = config.AddPropertyAtBranch(1, expectations1, map1);
    1492          60 :   for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
    1493          30 :     map1 = expectations1.AddDataField(map1, NONE, constness, representation,
    1494             :                                       any_type);
    1495             :   }
    1496          30 :   CHECK(!map1->is_deprecated());
    1497          30 :   CHECK(map1->is_stable());
    1498          30 :   CHECK(expectations1.Check(*map1));
    1499             : 
    1500             : 
    1501             :   // Create another branch in transition tree (property at index |kSplitProp|
    1502             :   // has different attributes), initialize expectations.
    1503             :   Handle<Map> map2 = map;
    1504          30 :   Expectations expectations2 = expectations;
    1505          30 :   map2 = expectations2.AddDataField(map2, READ_ONLY, constness, representation,
    1506             :                                     any_type);
    1507          90 :   for (int i = kSplitProp + 1; i < kCustomPropIndex; i++) {
    1508          60 :     map2 = expectations2.AddDataField(map2, NONE, constness, representation,
    1509             :                                       any_type);
    1510             :   }
    1511          30 :   map2 = config.AddPropertyAtBranch(2, expectations2, map2);
    1512          60 :   for (int i = kCustomPropIndex + 1; i < kPropCount; i++) {
    1513          30 :     map2 = expectations2.AddDataField(map2, NONE, constness, representation,
    1514             :                                       any_type);
    1515             :   }
    1516          30 :   CHECK(!map2->is_deprecated());
    1517          30 :   CHECK(map2->is_stable());
    1518          30 :   CHECK(expectations2.Check(*map2));
    1519             : 
    1520             : 
    1521             :   // Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
    1522             :   // should generalize representations in |map1|.
    1523             :   Handle<Map> new_map =
    1524          30 :       Map::ReconfigureExistingProperty(isolate, map2, kSplitProp, kData, NONE);
    1525             : 
    1526             :   // |map2| should be left unchanged but marked unstable.
    1527          30 :   CHECK(!map2->is_stable());
    1528          30 :   CHECK(!map2->is_deprecated());
    1529          90 :   CHECK_NE(*map2, *new_map);
    1530          30 :   CHECK(expectations2.Check(*map2));
    1531             : 
    1532             :   config.UpdateExpectations(kCustomPropIndex, expectations1);
    1533          30 :   checker.Check(isolate, map1, new_map, expectations1);
    1534          30 : }
    1535             : 
    1536             : 
    1537       28342 : TEST(ReconfigureDataFieldAttribute_SameDataConstantAfterTargetMap) {
    1538           5 :   CcTest::InitializeVM();
    1539           5 :   v8::HandleScope scope(CcTest::isolate());
    1540             : 
    1541             :   struct TestConfig {
    1542             :     Handle<JSFunction> js_func_;
    1543           5 :     TestConfig() {
    1544             :       Isolate* isolate = CcTest::i_isolate();
    1545             :       Factory* factory = isolate->factory();
    1546           5 :       js_func_ = factory->NewFunctionForTest(factory->empty_string());
    1547           5 :     }
    1548             : 
    1549          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1550             :                                     Handle<Map> map) {
    1551          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1552             :       // Add the same data constant property at both transition tree branches.
    1553          10 :       return expectations.AddDataConstant(map, NONE, js_func_);
    1554             :     }
    1555             : 
    1556             :     void UpdateExpectations(int property_index, Expectations& expectations) {
    1557             :       // Expectations stay the same.
    1558             :     }
    1559             :   };
    1560             : 
    1561           5 :   TestConfig config;
    1562             :   // Two branches are "compatible" so the |map1| should NOT be deprecated.
    1563             :   CheckSameMap checker;
    1564           5 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1565           5 : }
    1566             : 
    1567             : 
    1568       28342 : TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) {
    1569           5 :   CcTest::InitializeVM();
    1570           5 :   v8::HandleScope scope(CcTest::isolate());
    1571             : 
    1572             :   struct TestConfig {
    1573             :     Handle<JSFunction> js_func1_;
    1574             :     Handle<JSFunction> js_func2_;
    1575             :     Handle<FieldType> function_type_;
    1576           5 :     TestConfig() {
    1577             :       Isolate* isolate = CcTest::i_isolate();
    1578             :       Factory* factory = isolate->factory();
    1579             :       Handle<String> name = factory->empty_string();
    1580             :       Handle<Map> sloppy_map =
    1581           5 :           Map::CopyInitialMap(isolate, isolate->sloppy_function_map());
    1582             :       Handle<SharedFunctionInfo> info =
    1583           5 :           factory->NewSharedFunctionInfoForBuiltin(name, Builtins::kIllegal);
    1584           5 :       function_type_ = FieldType::Class(sloppy_map, isolate);
    1585           5 :       CHECK(sloppy_map->is_stable());
    1586             : 
    1587             :       js_func1_ =
    1588          10 :           factory->NewFunction(sloppy_map, info, isolate->native_context());
    1589             : 
    1590             :       js_func2_ =
    1591          10 :           factory->NewFunction(sloppy_map, info, isolate->native_context());
    1592           5 :     }
    1593             : 
    1594          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1595             :                                     Handle<Map> map) {
    1596          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1597          10 :       Handle<JSFunction> js_func = branch_id == 1 ? js_func1_ : js_func2_;
    1598          10 :       return expectations.AddDataConstant(map, NONE, js_func);
    1599             :     }
    1600             : 
    1601             :     void UpdateExpectations(int property_index, Expectations& expectations) {
    1602             :       PropertyConstness expected_constness = FLAG_track_constant_fields
    1603             :                                                  ? PropertyConstness::kConst
    1604             :                                                  : PropertyConstness::kMutable;
    1605             :       expectations.SetDataField(property_index, expected_constness,
    1606           5 :                                 Representation::HeapObject(), function_type_);
    1607             :     }
    1608             :   };
    1609             : 
    1610           5 :   TestConfig config;
    1611             :   if (FLAG_track_constant_fields) {
    1612             :     CheckSameMap checker;
    1613             :     TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1614             : 
    1615             :   } else {
    1616             :     // Two branches are "incompatible" so the |map1| should be deprecated.
    1617             :     CheckDeprecated checker;
    1618           5 :     TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1619           5 :   }
    1620           5 : }
    1621             : 
    1622             : 
    1623       28342 : TEST(ReconfigureDataFieldAttribute_DataConstantToAccConstantAfterTargetMap) {
    1624           5 :   CcTest::InitializeVM();
    1625           5 :   v8::HandleScope scope(CcTest::isolate());
    1626             : 
    1627             :   struct TestConfig {
    1628             :     Handle<JSFunction> js_func_;
    1629             :     Handle<AccessorPair> pair_;
    1630           5 :     TestConfig() {
    1631             :       Isolate* isolate = CcTest::i_isolate();
    1632             :       Factory* factory = isolate->factory();
    1633           5 :       js_func_ = factory->NewFunctionForTest(factory->empty_string());
    1634           5 :       pair_ = CreateAccessorPair(true, true);
    1635           5 :     }
    1636             : 
    1637          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1638             :                                     Handle<Map> map) {
    1639          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1640          10 :       if (branch_id == 1) {
    1641           5 :         return expectations.AddDataConstant(map, NONE, js_func_);
    1642             :       } else {
    1643           5 :         return expectations.AddAccessorConstant(map, NONE, pair_);
    1644             :       }
    1645             :     }
    1646             : 
    1647             :     void UpdateExpectations(int property_index, Expectations& expectations) {}
    1648             :   };
    1649             : 
    1650           5 :   TestConfig config;
    1651             :   // These are completely separate branches in transition tree.
    1652             :   CheckUnrelated checker;
    1653           5 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1654           5 : }
    1655             : 
    1656             : 
    1657       28342 : TEST(ReconfigureDataFieldAttribute_SameAccessorConstantAfterTargetMap) {
    1658           5 :   CcTest::InitializeVM();
    1659           5 :   v8::HandleScope scope(CcTest::isolate());
    1660             : 
    1661             :   struct TestConfig {
    1662             :     Handle<AccessorPair> pair_;
    1663           5 :     TestConfig() { pair_ = CreateAccessorPair(true, true); }
    1664             : 
    1665          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1666             :                                     Handle<Map> map) {
    1667          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1668             :       // Add the same accessor constant property at both transition tree
    1669             :       // branches.
    1670          10 :       return expectations.AddAccessorConstant(map, NONE, pair_);
    1671             :     }
    1672             : 
    1673             :     void UpdateExpectations(int property_index, Expectations& expectations) {
    1674             :       // Two branches are "compatible" so the |map1| should NOT be deprecated.
    1675             :     }
    1676             :   };
    1677             : 
    1678             :   TestConfig config;
    1679             :   CheckSameMap checker;
    1680           5 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1681           5 : }
    1682             : 
    1683             : 
    1684       28342 : TEST(ReconfigureDataFieldAttribute_AccConstantToAccFieldAfterTargetMap) {
    1685           5 :   CcTest::InitializeVM();
    1686           5 :   v8::HandleScope scope(CcTest::isolate());
    1687             : 
    1688             :   struct TestConfig {
    1689             :     Handle<AccessorPair> pair1_;
    1690             :     Handle<AccessorPair> pair2_;
    1691           5 :     TestConfig() {
    1692           5 :       pair1_ = CreateAccessorPair(true, true);
    1693           5 :       pair2_ = CreateAccessorPair(true, true);
    1694           5 :     }
    1695             : 
    1696          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1697             :                                     Handle<Map> map) {
    1698          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1699          10 :       Handle<AccessorPair> pair = branch_id == 1 ? pair1_ : pair2_;
    1700          10 :       return expectations.AddAccessorConstant(map, NONE, pair);
    1701             :     }
    1702             : 
    1703             :     void UpdateExpectations(int property_index, Expectations& expectations) {
    1704             :       if (IS_ACCESSOR_FIELD_SUPPORTED) {
    1705             :         expectations.SetAccessorField(property_index);
    1706             :       } else {
    1707             :         // Currently we have a copy-generalize-all-representations case and
    1708             :         // ACCESSOR property becomes ACCESSOR_CONSTANT.
    1709           5 :         expectations.SetAccessorConstant(property_index, pair2_);
    1710             :       }
    1711             :     }
    1712             :   };
    1713             : 
    1714           5 :   TestConfig config;
    1715             :   if (IS_ACCESSOR_FIELD_SUPPORTED) {
    1716             :     CheckCopyGeneralizeAllFields checker;
    1717             :     TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1718             :   } else {
    1719             :     // Currently we have a copy-generalize-all-representations case.
    1720             :     CheckCopyGeneralizeAllFields checker;
    1721           5 :     TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1722           5 :   }
    1723           5 : }
    1724             : 
    1725             : 
    1726       28342 : TEST(ReconfigureDataFieldAttribute_AccConstantToDataFieldAfterTargetMap) {
    1727           5 :   CcTest::InitializeVM();
    1728           5 :   v8::HandleScope scope(CcTest::isolate());
    1729             : 
    1730             :   struct TestConfig {
    1731             :     Handle<AccessorPair> pair_;
    1732           5 :     TestConfig() { pair_ = CreateAccessorPair(true, true); }
    1733             : 
    1734          10 :     Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations,
    1735             :                                     Handle<Map> map) {
    1736          10 :       CHECK(branch_id == 1 || branch_id == 2);
    1737          10 :       if (branch_id == 1) {
    1738           5 :         return expectations.AddAccessorConstant(map, NONE, pair_);
    1739             :       } else {
    1740             :         Isolate* isolate = CcTest::i_isolate();
    1741           5 :         Handle<FieldType> any_type = FieldType::Any(isolate);
    1742             :         return expectations.AddDataField(map, NONE, kDefaultFieldConstness,
    1743           5 :                                          Representation::Smi(), any_type);
    1744             :       }
    1745             :     }
    1746             : 
    1747             :     void UpdateExpectations(int property_index, Expectations& expectations) {}
    1748             :   };
    1749             : 
    1750             :   TestConfig config;
    1751             :   // These are completely separate branches in transition tree.
    1752             :   CheckUnrelated checker;
    1753           5 :   TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker);
    1754           5 : }
    1755             : 
    1756             : 
    1757             : ////////////////////////////////////////////////////////////////////////////////
    1758             : // A set of tests for elements kind reconfiguration case.
    1759             : //
    1760             : 
    1761             : // This test ensures that field generalization is correctly propagated from one
    1762             : // branch of transition tree (|map2) to another (|map|).
    1763             : //
    1764             : //   + - p0 - p1 - p2A - p3 - p4: |map|
    1765             : //   |
    1766             : //  ek
    1767             : //   |
    1768             : //  {} - p0 - p1 - p2B - p3 - p4: |map2|
    1769             : //
    1770             : // where "p2A" and "p2B" differ only in the representation/field type.
    1771             : //
    1772          20 : static void TestReconfigureElementsKind_GeneralizeField(
    1773             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
    1774          20 :   Isolate* isolate = CcTest::i_isolate();
    1775             : 
    1776          20 :   Expectations expectations(isolate, PACKED_SMI_ELEMENTS);
    1777             : 
    1778             :   // Create a map, add required properties to it and initialize expectations.
    1779          20 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1780             :   initial_map->set_instance_type(JS_ARRAY_TYPE);
    1781          20 :   initial_map->set_elements_kind(PACKED_SMI_ELEMENTS);
    1782             : 
    1783             :   Handle<Map> map = initial_map;
    1784          20 :   map = expectations.AsElementsKind(map, PACKED_ELEMENTS);
    1785         160 :   for (int i = 0; i < kPropCount; i++) {
    1786             :     map = expectations.AddDataField(map, NONE, from.constness,
    1787         140 :                                     from.representation, from.type);
    1788             :   }
    1789          20 :   CHECK(!map->is_deprecated());
    1790          20 :   CHECK(map->is_stable());
    1791          20 :   CHECK(expectations.Check(*map));
    1792             : 
    1793             :   // Create another branch in transition tree (property at index |kDiffProp|
    1794             :   // has different representatio/field type), initialize expectations.
    1795             :   const int kDiffProp = kPropCount / 2;
    1796          20 :   Expectations expectations2(isolate, PACKED_SMI_ELEMENTS);
    1797             : 
    1798             :   Handle<Map> map2 = initial_map;
    1799         160 :   for (int i = 0; i < kPropCount; i++) {
    1800         140 :     if (i == kDiffProp) {
    1801             :       map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1802          20 :                                         to.representation, to.type);
    1803             :     } else {
    1804             :       map2 = expectations2.AddDataField(map2, NONE, from.constness,
    1805         120 :                                         from.representation, from.type);
    1806             :     }
    1807             :   }
    1808          20 :   CHECK(!map2->is_deprecated());
    1809          20 :   CHECK(map2->is_stable());
    1810          20 :   CHECK(expectations2.Check(*map2));
    1811             : 
    1812          20 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1813          40 :   CanonicalHandleScope canonical(isolate);
    1814          20 :   JSHeapBroker broker(isolate, &zone);
    1815          20 :   CompilationDependencies dependencies(isolate, &zone);
    1816             :   MapRef map_ref(&broker, map);
    1817          20 :   map_ref.SerializeOwnDescriptors();
    1818          20 :   dependencies.DependOnFieldType(map_ref, kDiffProp);
    1819             : 
    1820             :   // Reconfigure elements kinds of |map2|, which should generalize
    1821             :   // representations in |map|.
    1822             :   Handle<Map> new_map =
    1823          20 :       Map::ReconfigureElementsKind(isolate, map2, PACKED_ELEMENTS);
    1824             : 
    1825             :   // |map2| should be left unchanged but marked unstable.
    1826          20 :   CHECK(!map2->is_stable());
    1827          20 :   CHECK(!map2->is_deprecated());
    1828          60 :   CHECK_NE(*map2, *new_map);
    1829          20 :   CHECK(expectations2.Check(*map2));
    1830             : 
    1831             :   // |map| should be deprecated and |new_map| should match new expectations.
    1832             :   expectations.SetDataField(kDiffProp, expected.constness,
    1833          20 :                             expected.representation, expected.type);
    1834             : 
    1835          20 :   CHECK(map->is_deprecated());
    1836          20 :   CHECK(dependencies.AreValid());
    1837          60 :   CHECK_NE(*map, *new_map);
    1838             : 
    1839          20 :   CHECK(!new_map->is_deprecated());
    1840          20 :   CHECK(expectations.Check(*new_map));
    1841             : 
    1842             :   // Update deprecated |map|, it should become |new_map|.
    1843          20 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1844          60 :   CHECK_EQ(*new_map, *updated_map);
    1845          20 :   CheckMigrationTarget(isolate, *map, *updated_map);
    1846             : 
    1847             :   // Ensure Map::FindElementsKindTransitionedMap() is able to find the
    1848             :   // transitioned map.
    1849             :   {
    1850             :     MapHandles map_list;
    1851          20 :     map_list.push_back(updated_map);
    1852             :     Map transitioned_map =
    1853          20 :         map2->FindElementsKindTransitionedMap(isolate, map_list);
    1854          40 :     CHECK_EQ(*updated_map, transitioned_map);
    1855          20 :   }
    1856          20 : }
    1857             : 
    1858             : // This test ensures that trivial field generalization (from HeapObject to
    1859             : // HeapObject) is correctly propagated from one branch of transition tree
    1860             : // (|map2|) to another (|map|).
    1861             : //
    1862             : //   + - p0 - p1 - p2A - p3 - p4: |map|
    1863             : //   |
    1864             : //  ek
    1865             : //   |
    1866             : //  {} - p0 - p1 - p2B - p3 - p4: |map2|
    1867             : //
    1868             : // where "p2A" and "p2B" differ only in the representation/field type.
    1869             : //
    1870          10 : static void TestReconfigureElementsKind_GeneralizeFieldTrivial(
    1871             :     const CRFTData& from, const CRFTData& to, const CRFTData& expected) {
    1872          10 :   Isolate* isolate = CcTest::i_isolate();
    1873             : 
    1874          10 :   Expectations expectations(isolate, PACKED_SMI_ELEMENTS);
    1875             : 
    1876             :   // Create a map, add required properties to it and initialize expectations.
    1877          10 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    1878             :   initial_map->set_instance_type(JS_ARRAY_TYPE);
    1879          10 :   initial_map->set_elements_kind(PACKED_SMI_ELEMENTS);
    1880             : 
    1881             :   Handle<Map> map = initial_map;
    1882          10 :   map = expectations.AsElementsKind(map, PACKED_ELEMENTS);
    1883          80 :   for (int i = 0; i < kPropCount; i++) {
    1884             :     map = expectations.AddDataField(map, NONE, from.constness,
    1885          70 :                                     from.representation, from.type);
    1886             :   }
    1887          10 :   CHECK(!map->is_deprecated());
    1888          10 :   CHECK(map->is_stable());
    1889          10 :   CHECK(expectations.Check(*map));
    1890             : 
    1891             :   // Create another branch in transition tree (property at index |kDiffProp|
    1892             :   // has different attributes), initialize expectations.
    1893             :   const int kDiffProp = kPropCount / 2;
    1894          10 :   Expectations expectations2(isolate, PACKED_SMI_ELEMENTS);
    1895             : 
    1896             :   Handle<Map> map2 = initial_map;
    1897          80 :   for (int i = 0; i < kPropCount; i++) {
    1898          70 :     if (i == kDiffProp) {
    1899             :       map2 = expectations2.AddDataField(map2, NONE, to.constness,
    1900          10 :                                         to.representation, to.type);
    1901             :     } else {
    1902             :       map2 = expectations2.AddDataField(map2, NONE, from.constness,
    1903          60 :                                         from.representation, from.type);
    1904             :     }
    1905             :   }
    1906          10 :   CHECK(!map2->is_deprecated());
    1907          10 :   CHECK(map2->is_stable());
    1908          10 :   CHECK(expectations2.Check(*map2));
    1909             : 
    1910          10 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1911          20 :   CanonicalHandleScope canonical(isolate);
    1912          10 :   JSHeapBroker broker(isolate, &zone);
    1913          10 :   CompilationDependencies dependencies(isolate, &zone);
    1914             :   MapRef map_ref(&broker, map);
    1915          10 :   map_ref.SerializeOwnDescriptors();
    1916          10 :   dependencies.DependOnFieldType(map_ref, kDiffProp);
    1917             : 
    1918             :   // Reconfigure elements kinds of |map2|, which should generalize
    1919             :   // representations in |map|.
    1920             :   Handle<Map> new_map =
    1921          10 :       Map::ReconfigureElementsKind(isolate, map2, PACKED_ELEMENTS);
    1922             : 
    1923             :   // |map2| should be left unchanged but marked unstable.
    1924          10 :   CHECK(!map2->is_stable());
    1925          10 :   CHECK(!map2->is_deprecated());
    1926          30 :   CHECK_NE(*map2, *new_map);
    1927          10 :   CHECK(expectations2.Check(*map2));
    1928             : 
    1929             :   // In trivial case |map| should be returned as a result of the elements
    1930             :   // kind reconfiguration, respective field types should be generalized and
    1931             :   // respective code dependencies should be invalidated. |map| should be NOT
    1932             :   // deprecated and it should match new expectations.
    1933             :   expectations.SetDataField(kDiffProp, expected.constness,
    1934          10 :                             expected.representation, expected.type);
    1935          10 :   CHECK(!map->is_deprecated());
    1936          30 :   CHECK_EQ(*map, *new_map);
    1937          10 :   CHECK(dependencies.AreValid());
    1938             : 
    1939          10 :   CHECK(!new_map->is_deprecated());
    1940          10 :   CHECK(expectations.Check(*new_map));
    1941             : 
    1942          10 :   Handle<Map> updated_map = Map::Update(isolate, map);
    1943          30 :   CHECK_EQ(*new_map, *updated_map);
    1944             : 
    1945             :   // Ensure Map::FindElementsKindTransitionedMap() is able to find the
    1946             :   // transitioned map.
    1947             :   {
    1948             :     MapHandles map_list;
    1949          10 :     map_list.push_back(updated_map);
    1950             :     Map transitioned_map =
    1951          10 :         map2->FindElementsKindTransitionedMap(isolate, map_list);
    1952          20 :     CHECK_EQ(*updated_map, transitioned_map);
    1953          10 :   }
    1954          10 : }
    1955             : 
    1956       28342 : TEST(ReconfigureElementsKind_GeneralizeSmiFieldToDouble) {
    1957           5 :   CcTest::InitializeVM();
    1958           5 :   v8::HandleScope scope(CcTest::isolate());
    1959             :   Isolate* isolate = CcTest::i_isolate();
    1960             : 
    1961           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1962             : 
    1963             :   if (FLAG_track_constant_fields) {
    1964             :     TestReconfigureElementsKind_GeneralizeField(
    1965             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1966             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1967             :         {PropertyConstness::kConst, Representation::Double(), any_type});
    1968             : 
    1969             :     TestReconfigureElementsKind_GeneralizeField(
    1970             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1971             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    1972             :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1973             : 
    1974             :     TestReconfigureElementsKind_GeneralizeField(
    1975             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1976             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    1977             :         {PropertyConstness::kMutable, Representation::Double(), any_type});
    1978             :   }
    1979             :   TestReconfigureElementsKind_GeneralizeField(
    1980             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    1981             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    1982           5 :       {PropertyConstness::kMutable, Representation::Double(), any_type});
    1983           5 : }
    1984             : 
    1985       28342 : TEST(ReconfigureElementsKind_GeneralizeSmiFieldToTagged) {
    1986           5 :   CcTest::InitializeVM();
    1987           5 :   v8::HandleScope scope(CcTest::isolate());
    1988             :   Isolate* isolate = CcTest::i_isolate();
    1989             : 
    1990           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    1991             :   Handle<FieldType> value_type =
    1992           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    1993             : 
    1994             :   if (FLAG_track_constant_fields) {
    1995             :     TestReconfigureElementsKind_GeneralizeField(
    1996             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    1997             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    1998             :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    1999             : 
    2000             :     TestReconfigureElementsKind_GeneralizeField(
    2001             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2002             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2003             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2004             : 
    2005             :     TestReconfigureElementsKind_GeneralizeField(
    2006             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2007             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2008             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2009             :   }
    2010             :   TestReconfigureElementsKind_GeneralizeField(
    2011             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2012             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2013           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2014           5 : }
    2015             : 
    2016       28342 : TEST(ReconfigureElementsKind_GeneralizeDoubleFieldToTagged) {
    2017           5 :   CcTest::InitializeVM();
    2018           5 :   v8::HandleScope scope(CcTest::isolate());
    2019             :   Isolate* isolate = CcTest::i_isolate();
    2020             : 
    2021           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2022             :   Handle<FieldType> value_type =
    2023           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2024             : 
    2025             :   if (FLAG_track_constant_fields) {
    2026             :     TestReconfigureElementsKind_GeneralizeField(
    2027             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    2028             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2029             :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    2030             : 
    2031             :     TestReconfigureElementsKind_GeneralizeField(
    2032             :         {PropertyConstness::kConst, Representation::Double(), any_type},
    2033             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2034             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2035             : 
    2036             :     TestReconfigureElementsKind_GeneralizeField(
    2037             :         {PropertyConstness::kMutable, Representation::Double(), any_type},
    2038             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2039             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2040             :   }
    2041             :   TestReconfigureElementsKind_GeneralizeField(
    2042             :       {PropertyConstness::kMutable, Representation::Double(), any_type},
    2043             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2044           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2045           5 : }
    2046             : 
    2047       28342 : TEST(ReconfigureElementsKind_GeneralizeHeapObjFieldToHeapObj) {
    2048           5 :   CcTest::InitializeVM();
    2049           5 :   v8::HandleScope scope(CcTest::isolate());
    2050             :   Isolate* isolate = CcTest::i_isolate();
    2051             : 
    2052           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2053             : 
    2054             :   Handle<FieldType> current_type =
    2055           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2056             : 
    2057             :   Handle<FieldType> new_type =
    2058           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2059             : 
    2060           5 :   Handle<FieldType> expected_type = any_type;
    2061             : 
    2062             :   // Check generalizations that trigger deopts.
    2063             :   if (FLAG_track_constant_fields) {
    2064             :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2065             :         {PropertyConstness::kConst, Representation::HeapObject(), current_type},
    2066             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2067             :         {PropertyConstness::kConst, Representation::HeapObject(),
    2068             :          expected_type});
    2069             :     if (FLAG_modify_map_inplace) {
    2070             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration does
    2071             :       // not create a new map, therefore trivial generalization.
    2072             :       TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2073             :           {PropertyConstness::kConst, Representation::HeapObject(),
    2074             :            current_type},
    2075             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2076             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2077             :            expected_type});
    2078             :     } else {
    2079             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration
    2080             :       // causes map change, therefore non-trivial generalization.
    2081             :       TestReconfigureElementsKind_GeneralizeField(
    2082             :           {PropertyConstness::kConst, Representation::HeapObject(),
    2083             :            current_type},
    2084             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2085             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2086             :            expected_type});
    2087             :     }
    2088             :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2089             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    2090             :          current_type},
    2091             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2092             :         {PropertyConstness::kMutable, Representation::HeapObject(),
    2093             :          expected_type});
    2094             :   }
    2095             :   TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2096             :       {PropertyConstness::kMutable, Representation::HeapObject(), current_type},
    2097             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2098             :       {PropertyConstness::kMutable, Representation::HeapObject(),
    2099           5 :        expected_type});
    2100             :   current_type = expected_type;
    2101             : 
    2102             :   // Check generalizations that do not trigger deopts.
    2103           5 :   new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
    2104             : 
    2105             :   if (FLAG_track_constant_fields) {
    2106             :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2107             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    2108             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2109             :         {PropertyConstness::kConst, Representation::HeapObject(), any_type});
    2110             : 
    2111             :     if (FLAG_modify_map_inplace) {
    2112             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration does
    2113             :       // not create a new map, therefore trivial generalization.
    2114             :       TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2115             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    2116             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2117             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2118             :            any_type});
    2119             :     } else {
    2120             :       // PropertyConstness::kConst to PropertyConstness::kMutable migration
    2121             :       // causes map change, therefore non-trivial generalization.
    2122             :       TestReconfigureElementsKind_GeneralizeField(
    2123             :           {PropertyConstness::kConst, Representation::HeapObject(), any_type},
    2124             :           {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2125             :           {PropertyConstness::kMutable, Representation::HeapObject(),
    2126             :            any_type});
    2127             :     }
    2128             : 
    2129             :     TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2130             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    2131             :         {PropertyConstness::kConst, Representation::HeapObject(), new_type},
    2132             :         {PropertyConstness::kMutable, Representation::HeapObject(), any_type});
    2133             :   }
    2134             :   TestReconfigureElementsKind_GeneralizeFieldTrivial(
    2135             :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type},
    2136             :       {PropertyConstness::kMutable, Representation::HeapObject(), new_type},
    2137           5 :       {PropertyConstness::kMutable, Representation::HeapObject(), any_type});
    2138           5 : }
    2139             : 
    2140       28342 : TEST(ReconfigureElementsKind_GeneralizeHeapObjectFieldToTagged) {
    2141           5 :   CcTest::InitializeVM();
    2142           5 :   v8::HandleScope scope(CcTest::isolate());
    2143             :   Isolate* isolate = CcTest::i_isolate();
    2144             : 
    2145           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2146             :   Handle<FieldType> value_type =
    2147           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2148             : 
    2149             :   if (FLAG_track_constant_fields) {
    2150             :     TestReconfigureElementsKind_GeneralizeField(
    2151             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2152             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2153             :         {PropertyConstness::kConst, Representation::Tagged(), any_type});
    2154             : 
    2155             :     TestReconfigureElementsKind_GeneralizeField(
    2156             :         {PropertyConstness::kConst, Representation::HeapObject(), value_type},
    2157             :         {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2158             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2159             : 
    2160             :     TestReconfigureElementsKind_GeneralizeField(
    2161             :         {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2162             :         {PropertyConstness::kConst, Representation::Smi(), any_type},
    2163             :         {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2164             :   }
    2165             :   TestReconfigureElementsKind_GeneralizeField(
    2166             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2167             :       {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2168           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2169           5 : }
    2170             : 
    2171             : ////////////////////////////////////////////////////////////////////////////////
    2172             : // A set of tests checking split map deprecation.
    2173             : //
    2174             : 
    2175       28342 : TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
    2176           5 :   CcTest::InitializeVM();
    2177           5 :   v8::HandleScope scope(CcTest::isolate());
    2178             :   Isolate* isolate = CcTest::i_isolate();
    2179             : 
    2180           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2181             : 
    2182           5 :   Expectations expectations(isolate);
    2183             : 
    2184             :   // Create a map, add required properties to it and initialize expectations.
    2185           5 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    2186           5 :   Handle<Map> map = initial_map;
    2187          40 :   for (int i = 0; i < kPropCount; i++) {
    2188             :     map = expectations.AddDataField(map, NONE, PropertyConstness::kMutable,
    2189          35 :                                     Representation::Smi(), any_type);
    2190             :   }
    2191           5 :   CHECK(!map->is_deprecated());
    2192           5 :   CHECK(map->is_stable());
    2193             : 
    2194             :   // Generalize representation of property at index |kSplitProp|.
    2195             :   const int kSplitProp = kPropCount / 2;
    2196             :   Handle<Map> split_map;
    2197             :   Handle<Map> map2 = initial_map;
    2198             :   {
    2199          20 :     for (int i = 0; i < kSplitProp + 1; i++) {
    2200          20 :       if (i == kSplitProp) {
    2201             :         split_map = map2;
    2202             :       }
    2203             : 
    2204          20 :       Handle<String> name = MakeName("prop", i);
    2205             :       Map target = TransitionsAccessor(isolate, map2)
    2206          20 :                        .SearchTransition(*name, kData, NONE);
    2207          20 :       CHECK(!target.is_null());
    2208             :       map2 = handle(target, isolate);
    2209             :     }
    2210             : 
    2211             :     map2 = Map::ReconfigureProperty(isolate, map2, kSplitProp, kData, NONE,
    2212           5 :                                     Representation::Double(), any_type);
    2213             :     expectations.SetDataField(kSplitProp, PropertyConstness::kMutable,
    2214           5 :                               Representation::Double(), any_type);
    2215             : 
    2216           5 :     CHECK(expectations.Check(*split_map, kSplitProp));
    2217           5 :     CHECK(expectations.Check(*map2, kSplitProp + 1));
    2218             :   }
    2219             : 
    2220             :   // At this point |map| should be deprecated and disconnected from the
    2221             :   // transition tree.
    2222           5 :   CHECK(map->is_deprecated());
    2223           5 :   CHECK(!split_map->is_deprecated());
    2224           5 :   CHECK(map2->is_stable());
    2225           5 :   CHECK(!map2->is_deprecated());
    2226             : 
    2227             :   // Fill in transition tree of |map2| so that it can't have more transitions.
    2228        7680 :   for (int i = 0; i < TransitionsAccessor::kMaxNumberOfTransitions; i++) {
    2229        7680 :     CHECK(TransitionsAccessor(isolate, map2).CanHaveMoreTransitions());
    2230        7680 :     Handle<String> name = MakeName("foo", i);
    2231             :     Map::CopyWithField(isolate, map2, name, any_type, NONE,
    2232             :                        PropertyConstness::kMutable, Representation::Smi(),
    2233        7680 :                        INSERT_TRANSITION)
    2234       15360 :         .ToHandleChecked();
    2235             :   }
    2236           5 :   CHECK(!TransitionsAccessor(isolate, map2).CanHaveMoreTransitions());
    2237             : 
    2238             :   // Try to update |map|, since there is no place for propX transition at |map2|
    2239             :   // |map| should become "copy-generalized".
    2240           5 :   Handle<Map> updated_map = Map::Update(isolate, map);
    2241          10 :   CHECK(updated_map->GetBackPointer()->IsUndefined(isolate));
    2242             : 
    2243          35 :   for (int i = 0; i < kPropCount; i++) {
    2244             :     expectations.SetDataField(i, PropertyConstness::kMutable,
    2245          35 :                               Representation::Tagged(), any_type);
    2246             :   }
    2247           5 :   CHECK(expectations.Check(*updated_map));
    2248           5 : }
    2249             : 
    2250             : 
    2251             : ////////////////////////////////////////////////////////////////////////////////
    2252             : // A set of tests involving special transitions (such as elements kind
    2253             : // transition, observed transition or prototype transition).
    2254             : //
    2255             : 
    2256             : // This test ensures that field generalization is correctly propagated from one
    2257             : // branch of transition tree (|map2|) to another (|map|).
    2258             : //
    2259             : //                            p4B: |map2|
    2260             : //                             |
    2261             : //                             * - special transition
    2262             : //                             |
    2263             : //  {} - p0 - p1 - p2A - p3 - p4A: |map|
    2264             : //
    2265             : // where "p4A" and "p4B" are exactly the same properties.
    2266             : //
    2267             : // TODO(ishell): unify this test template with
    2268             : // TestReconfigureDataFieldAttribute_GeneralizeField once
    2269             : // IS_PROTO_TRANS_ISSUE_FIXED and IS_NON_EQUIVALENT_TRANSITION_SUPPORTED are
    2270             : // fixed.
    2271             : template <typename TestConfig>
    2272          20 : static void TestGeneralizeFieldWithSpecialTransition(TestConfig& config,
    2273             :                                                      const CRFTData& from,
    2274             :                                                      const CRFTData& to,
    2275             :                                                      const CRFTData& expected) {
    2276             :   Isolate* isolate = CcTest::i_isolate();
    2277             : 
    2278          20 :   Expectations expectations(isolate);
    2279             : 
    2280             :   // Create a map, add required properties to it and initialize expectations.
    2281          20 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    2282          20 :   Handle<Map> map = initial_map;
    2283         150 :   for (int i = 0; i < kPropCount; i++) {
    2284         140 :     map = expectations.AddDataField(map, NONE, from.constness,
    2285         140 :                                     from.representation, from.type);
    2286             :   }
    2287          20 :   CHECK(!map->is_deprecated());
    2288          20 :   CHECK(map->is_stable());
    2289          20 :   CHECK(expectations.Check(*map));
    2290             : 
    2291          20 :   Expectations expectations2 = expectations;
    2292             : 
    2293             :   // Apply some special transition to |map|.
    2294          20 :   CHECK(map->owns_descriptors());
    2295          20 :   Handle<Map> map2 = config.Transition(map, expectations2);
    2296             : 
    2297             :   // |map| should still match expectations.
    2298          20 :   CHECK(!map->is_deprecated());
    2299          20 :   CHECK(expectations.Check(*map));
    2300             : 
    2301             :   if (config.generalizes_representations()) {
    2302          70 :     for (int i = 0; i < kPropCount; i++) {
    2303          70 :       expectations2.GeneralizeField(i);
    2304             :     }
    2305             :   }
    2306             : 
    2307          20 :   CHECK(!map2->is_deprecated());
    2308          20 :   CHECK(map2->is_stable());
    2309          20 :   CHECK(expectations2.Check(*map2));
    2310             : 
    2311             :   // Create new maps by generalizing representation of propX field.
    2312         140 :   Handle<Map> maps[kPropCount];
    2313         140 :   for (int i = 0; i < kPropCount; i++) {
    2314             :     Handle<Map> new_map = Map::ReconfigureProperty(isolate, map, i, kData, NONE,
    2315         140 :                                                    to.representation, to.type);
    2316         140 :     maps[i] = new_map;
    2317             : 
    2318         140 :     expectations.SetDataField(i, expected.constness, expected.representation,
    2319         140 :                               expected.type);
    2320             : 
    2321         140 :     CHECK(map->is_deprecated());
    2322         420 :     CHECK_NE(*map, *new_map);
    2323         260 :     CHECK(i == 0 || maps[i - 1]->is_deprecated());
    2324         140 :     CHECK(expectations.Check(*new_map));
    2325             : 
    2326         140 :     Handle<Map> new_map2 = Map::Update(isolate, map2);
    2327         140 :     CHECK(!new_map2->is_deprecated());
    2328         140 :     CHECK(!new_map2->is_dictionary_map());
    2329             : 
    2330             :     Handle<Map> tmp_map;
    2331         280 :     if (Map::TryUpdate(isolate, map2).ToHandle(&tmp_map)) {
    2332             :       // If Map::TryUpdate() manages to succeed the result must match the result
    2333             :       // of Map::Update().
    2334         210 :       CHECK_EQ(*new_map2, *tmp_map);
    2335             :     }
    2336             : 
    2337             :     if (config.is_non_equevalent_transition()) {
    2338             :       // In case of non-equivalent transition currently we generalize all
    2339             :       // representations.
    2340         980 :       for (int i = 0; i < kPropCount; i++) {
    2341         980 :         expectations2.GeneralizeField(i);
    2342             :       }
    2343         280 :       CHECK(new_map2->GetBackPointer()->IsUndefined(isolate));
    2344         140 :       CHECK(expectations2.Check(*new_map2));
    2345             :     } else {
    2346             :       CHECK(!new_map2->GetBackPointer()->IsUndefined(isolate));
    2347             :       CHECK(expectations2.Check(*new_map2));
    2348             :     }
    2349             :   }
    2350             : 
    2351          20 :   Handle<Map> active_map = maps[kPropCount - 1];
    2352          20 :   CHECK(!active_map->is_deprecated());
    2353             : 
    2354             :   // Update all deprecated maps and check that they are now the same.
    2355          20 :   Handle<Map> updated_map = Map::Update(isolate, map);
    2356          60 :   CHECK_EQ(*active_map, *updated_map);
    2357          20 :   CheckMigrationTarget(isolate, *map, *updated_map);
    2358         150 :   for (int i = 0; i < kPropCount; i++) {
    2359         140 :     updated_map = Map::Update(isolate, maps[i]);
    2360         420 :     CHECK_EQ(*active_map, *updated_map);
    2361         280 :     CheckMigrationTarget(isolate, *maps[i], *updated_map);
    2362             :   }
    2363          20 : }
    2364             : 
    2365             : 
    2366       28342 : TEST(ElementsKindTransitionFromMapOwningDescriptor) {
    2367           5 :   CcTest::InitializeVM();
    2368           5 :   v8::HandleScope scope(CcTest::isolate());
    2369             :   Isolate* isolate = CcTest::i_isolate();
    2370             : 
    2371           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2372             :   Handle<FieldType> value_type =
    2373           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2374             : 
    2375             :   struct TestConfig {
    2376           5 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2377          10 :       Handle<Symbol> frozen_symbol(map->GetReadOnlyRoots().frozen_symbol(),
    2378          10 :                                    CcTest::i_isolate());
    2379             :       expectations.SetElementsKind(DICTIONARY_ELEMENTS);
    2380             :       return Map::CopyForPreventExtensions(CcTest::i_isolate(), map, NONE,
    2381             :                                            frozen_symbol,
    2382           5 :                                            "CopyForPreventExtensions");
    2383             :     }
    2384             :     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
    2385             :     bool generalizes_representations() const { return false; }
    2386             :     bool is_non_equevalent_transition() const { return true; }
    2387             :   };
    2388             :   TestConfig config;
    2389             :   TestGeneralizeFieldWithSpecialTransition(
    2390             :       config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2391             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2392           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2393           5 : }
    2394             : 
    2395             : 
    2396       28342 : TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
    2397           5 :   CcTest::InitializeVM();
    2398           5 :   v8::HandleScope scope(CcTest::isolate());
    2399             :   Isolate* isolate = CcTest::i_isolate();
    2400             : 
    2401           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2402             :   Handle<FieldType> value_type =
    2403           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2404             : 
    2405             :   struct TestConfig {
    2406           5 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2407             :       Isolate* isolate = CcTest::i_isolate();
    2408           5 :       Handle<FieldType> any_type = FieldType::Any(isolate);
    2409             : 
    2410             :       // Add one more transition to |map| in order to prevent descriptors
    2411             :       // ownership.
    2412           5 :       CHECK(map->owns_descriptors());
    2413             :       Map::CopyWithField(isolate, map, MakeString("foo"), any_type, NONE,
    2414             :                          PropertyConstness::kMutable, Representation::Smi(),
    2415           5 :                          INSERT_TRANSITION)
    2416          10 :           .ToHandleChecked();
    2417           5 :       CHECK(!map->owns_descriptors());
    2418             : 
    2419             :       Handle<Symbol> frozen_symbol(ReadOnlyRoots(isolate).frozen_symbol(),
    2420             :                                    isolate);
    2421             :       expectations.SetElementsKind(DICTIONARY_ELEMENTS);
    2422             :       return Map::CopyForPreventExtensions(isolate, map, NONE, frozen_symbol,
    2423           5 :                                            "CopyForPreventExtensions");
    2424             :     }
    2425             :     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
    2426             :     bool generalizes_representations() const { return false; }
    2427             :     bool is_non_equevalent_transition() const { return true; }
    2428             :   };
    2429             :   TestConfig config;
    2430             :   TestGeneralizeFieldWithSpecialTransition(
    2431             :       config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2432             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2433           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2434           5 : }
    2435             : 
    2436             : 
    2437       28342 : TEST(PrototypeTransitionFromMapOwningDescriptor) {
    2438           5 :   CcTest::InitializeVM();
    2439           5 :   v8::HandleScope scope(CcTest::isolate());
    2440             :   Isolate* isolate = CcTest::i_isolate();
    2441             : 
    2442           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2443             :   Handle<FieldType> value_type =
    2444           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2445             : 
    2446             :   struct TestConfig {
    2447             :     Handle<JSObject> prototype_;
    2448             : 
    2449           5 :     TestConfig() {
    2450             :       Isolate* isolate = CcTest::i_isolate();
    2451             :       Factory* factory = isolate->factory();
    2452           5 :       prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
    2453           5 :     }
    2454             : 
    2455           5 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2456           5 :       return Map::TransitionToPrototype(CcTest::i_isolate(), map, prototype_);
    2457             :     }
    2458             :     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
    2459             :     bool generalizes_representations() const {
    2460             :       return !IS_PROTO_TRANS_ISSUE_FIXED;
    2461             :     }
    2462             :     bool is_non_equevalent_transition() const { return true; }
    2463             :   };
    2464           5 :   TestConfig config;
    2465             :   TestGeneralizeFieldWithSpecialTransition(
    2466             :       config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2467             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2468           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2469           5 : }
    2470             : 
    2471             : 
    2472       28342 : TEST(PrototypeTransitionFromMapNotOwningDescriptor) {
    2473           5 :   CcTest::InitializeVM();
    2474           5 :   v8::HandleScope scope(CcTest::isolate());
    2475             :   Isolate* isolate = CcTest::i_isolate();
    2476             : 
    2477           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2478             :   Handle<FieldType> value_type =
    2479           5 :       FieldType::Class(Map::Create(isolate, 0), isolate);
    2480             : 
    2481             :   struct TestConfig {
    2482             :     Handle<JSObject> prototype_;
    2483             : 
    2484           5 :     TestConfig() {
    2485             :       Isolate* isolate = CcTest::i_isolate();
    2486             :       Factory* factory = isolate->factory();
    2487           5 :       prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
    2488           5 :     }
    2489             : 
    2490           5 :     Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
    2491             :       Isolate* isolate = CcTest::i_isolate();
    2492           5 :       Handle<FieldType> any_type = FieldType::Any(isolate);
    2493             : 
    2494             :       // Add one more transition to |map| in order to prevent descriptors
    2495             :       // ownership.
    2496           5 :       CHECK(map->owns_descriptors());
    2497             :       Map::CopyWithField(isolate, map, MakeString("foo"), any_type, NONE,
    2498             :                          PropertyConstness::kMutable, Representation::Smi(),
    2499           5 :                          INSERT_TRANSITION)
    2500          10 :           .ToHandleChecked();
    2501           5 :       CHECK(!map->owns_descriptors());
    2502             : 
    2503           5 :       return Map::TransitionToPrototype(isolate, map, prototype_);
    2504             :     }
    2505             :     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
    2506             :     bool generalizes_representations() const {
    2507             :       return !IS_PROTO_TRANS_ISSUE_FIXED;
    2508             :     }
    2509             :     bool is_non_equevalent_transition() const { return true; }
    2510             :   };
    2511           5 :   TestConfig config;
    2512             :   TestGeneralizeFieldWithSpecialTransition(
    2513             :       config, {PropertyConstness::kMutable, Representation::Smi(), any_type},
    2514             :       {PropertyConstness::kMutable, Representation::HeapObject(), value_type},
    2515           5 :       {PropertyConstness::kMutable, Representation::Tagged(), any_type});
    2516           5 : }
    2517             : 
    2518             : 
    2519             : ////////////////////////////////////////////////////////////////////////////////
    2520             : // A set of tests for higher level transitioning mechanics.
    2521             : //
    2522             : 
    2523             : struct TransitionToDataFieldOperator {
    2524             :   PropertyConstness constness_;
    2525             :   Representation representation_;
    2526             :   PropertyAttributes attributes_;
    2527             :   Handle<FieldType> heap_type_;
    2528             :   Handle<Object> value_;
    2529             : 
    2530             :   TransitionToDataFieldOperator(PropertyConstness constness,
    2531             :                                 Representation representation,
    2532             :                                 Handle<FieldType> heap_type,
    2533             :                                 Handle<Object> value,
    2534             :                                 PropertyAttributes attributes = NONE)
    2535             :       : constness_(constness),
    2536             :         representation_(representation),
    2537             :         attributes_(attributes),
    2538             :         heap_type_(heap_type),
    2539          15 :         value_(value) {}
    2540             : 
    2541             :   Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
    2542             :     return expectations.TransitionToDataField(
    2543          15 :         map, attributes_, constness_, representation_, heap_type_, value_);
    2544             :   }
    2545             : };
    2546             : 
    2547             : 
    2548             : struct TransitionToDataConstantOperator {
    2549             :   PropertyAttributes attributes_;
    2550             :   Handle<JSFunction> value_;
    2551             : 
    2552             :   TransitionToDataConstantOperator(Handle<JSFunction> value,
    2553             :                                    PropertyAttributes attributes = NONE)
    2554          20 :       : attributes_(attributes), value_(value) {}
    2555             : 
    2556             :   Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
    2557          25 :     return expectations.TransitionToDataConstant(map, attributes_, value_);
    2558             :   }
    2559             : };
    2560             : 
    2561             : 
    2562             : struct TransitionToAccessorConstantOperator {
    2563             :   PropertyAttributes attributes_;
    2564             :   Handle<AccessorPair> pair_;
    2565             : 
    2566             :   TransitionToAccessorConstantOperator(Handle<AccessorPair> pair,
    2567             :                                        PropertyAttributes attributes = NONE)
    2568           5 :       : attributes_(attributes), pair_(pair) {}
    2569             : 
    2570             :   Handle<Map> DoTransition(Expectations& expectations, Handle<Map> map) {
    2571          10 :     return expectations.TransitionToAccessorConstant(map, attributes_, pair_);
    2572             :   }
    2573             : };
    2574             : 
    2575             : 
    2576             : struct ReconfigureAsDataPropertyOperator {
    2577             :   int descriptor_;
    2578             :   Representation representation_;
    2579             :   PropertyAttributes attributes_;
    2580             :   Handle<FieldType> heap_type_;
    2581             : 
    2582             :   ReconfigureAsDataPropertyOperator(int descriptor,
    2583             :                                     Representation representation,
    2584             :                                     Handle<FieldType> heap_type,
    2585             :                                     PropertyAttributes attributes = NONE)
    2586             :       : descriptor_(descriptor),
    2587             :         representation_(representation),
    2588             :         attributes_(attributes),
    2589             :         heap_type_(heap_type) {}
    2590             : 
    2591             :   Handle<Map> DoTransition(Isolate* isolate, Expectations& expectations,
    2592             :                            Handle<Map> map) {
    2593             :     expectations.SetDataField(descriptor_, PropertyConstness::kMutable,
    2594             :                               representation_, heap_type_);
    2595             :     return Map::ReconfigureExistingProperty(isolate, map, descriptor_, kData,
    2596             :                                             attributes_);
    2597             :   }
    2598             : };
    2599             : 
    2600             : 
    2601             : struct ReconfigureAsAccessorPropertyOperator {
    2602             :   int descriptor_;
    2603             :   PropertyAttributes attributes_;
    2604             : 
    2605             :   ReconfigureAsAccessorPropertyOperator(int descriptor,
    2606             :                                         PropertyAttributes attributes = NONE)
    2607             :       : descriptor_(descriptor), attributes_(attributes) {}
    2608             : 
    2609             :   Handle<Map> DoTransition(Isolate* isolate, Expectations& expectations,
    2610             :                            Handle<Map> map) {
    2611             :     expectations.SetAccessorField(descriptor_);
    2612             :     return Map::ReconfigureExistingProperty(isolate, map, descriptor_,
    2613             :                                             kAccessor, attributes_);
    2614             :   }
    2615             : };
    2616             : 
    2617             : // Checks that field generalization happened.
    2618             : struct FieldGeneralizationChecker {
    2619             :   int descriptor_;
    2620             :   PropertyConstness constness_;
    2621             :   Representation representation_;
    2622             :   PropertyAttributes attributes_;
    2623             :   Handle<FieldType> heap_type_;
    2624             : 
    2625             :   FieldGeneralizationChecker(int descriptor, PropertyConstness constness,
    2626             :                              Representation representation,
    2627             :                              Handle<FieldType> heap_type,
    2628             :                              PropertyAttributes attributes = NONE)
    2629             :       : descriptor_(descriptor),
    2630             :         constness_(constness),
    2631             :         representation_(representation),
    2632             :         attributes_(attributes),
    2633          15 :         heap_type_(heap_type) {}
    2634             : 
    2635          15 :   void Check(Isolate* isolate, Expectations& expectations2, Handle<Map> map1,
    2636             :              Handle<Map> map2) {
    2637          15 :     CHECK(!map2->is_deprecated());
    2638             : 
    2639          15 :     CHECK(map1->is_deprecated());
    2640          45 :     CHECK_NE(*map1, *map2);
    2641          15 :     Handle<Map> updated_map = Map::Update(isolate, map1);
    2642          45 :     CHECK_EQ(*map2, *updated_map);
    2643          15 :     CheckMigrationTarget(isolate, *map1, *updated_map);
    2644             : 
    2645             :     expectations2.SetDataField(descriptor_, attributes_, constness_,
    2646          15 :                                representation_, heap_type_);
    2647          15 :     CHECK(expectations2.Check(*map2));
    2648          15 :   }
    2649             : };
    2650             : 
    2651             : 
    2652             : // Checks that existing transition was taken as is.
    2653             : struct SameMapChecker {
    2654          10 :   void Check(Isolate* isolate, Expectations& expectations, Handle<Map> map1,
    2655             :              Handle<Map> map2) {
    2656          10 :     CHECK(!map2->is_deprecated());
    2657          30 :     CHECK_EQ(*map1, *map2);
    2658          10 :     CHECK(expectations.Check(*map2));
    2659          10 :   }
    2660             : };
    2661             : 
    2662             : 
    2663             : // Checks that both |map1| and |map2| should stays non-deprecated, this is
    2664             : // the case when property kind is change.
    2665             : struct PropertyKindReconfigurationChecker {
    2666             :   void Check(Expectations& expectations, Handle<Map> map1, Handle<Map> map2) {
    2667             :     CHECK(!map1->is_deprecated());
    2668             :     CHECK(!map2->is_deprecated());
    2669             :     CHECK_NE(*map1, *map2);
    2670             :     CHECK(expectations.Check(*map2));
    2671             :   }
    2672             : };
    2673             : 
    2674             : 
    2675             : // This test transitions to various property types under different
    2676             : // circumstances.
    2677             : // Plan:
    2678             : // 1) create a |map| with p0..p3 properties.
    2679             : // 2) create |map1| by adding "p4" to |map0|.
    2680             : // 3) create |map2| by transition to "p4" from |map0|.
    2681             : //
    2682             : //                       + - p4B: |map2|
    2683             : //                       |
    2684             : //  {} - p0 - p1 - pA - p3: |map|
    2685             : //                       |
    2686             : //                       + - p4A: |map1|
    2687             : //
    2688             : // where "p4A" and "p4B" differ only in the attributes.
    2689             : //
    2690             : template <typename TransitionOp1, typename TransitionOp2, typename Checker>
    2691          45 : static void TestTransitionTo(TransitionOp1& transition_op1,
    2692          15 :                              TransitionOp2& transition_op2, Checker& checker) {
    2693             :   Isolate* isolate = CcTest::i_isolate();
    2694          25 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2695             : 
    2696          25 :   Expectations expectations(isolate);
    2697             : 
    2698             :   // Create a map, add required properties to it and initialize expectations.
    2699          25 :   Handle<Map> initial_map = Map::Create(isolate, 0);
    2700          25 :   Handle<Map> map = initial_map;
    2701         175 :   for (int i = 0; i < kPropCount - 1; i++) {
    2702         150 :     map = expectations.AddDataField(map, NONE, PropertyConstness::kMutable,
    2703             :                                     Representation::Smi(), any_type);
    2704             :   }
    2705          25 :   CHECK(expectations.Check(*map));
    2706             : 
    2707          25 :   Expectations expectations1 = expectations;
    2708             :   Handle<Map> map1 = transition_op1.DoTransition(expectations1, map);
    2709          25 :   CHECK(expectations1.Check(*map1));
    2710             : 
    2711          25 :   Expectations expectations2 = expectations;
    2712          25 :   Handle<Map> map2 = transition_op2.DoTransition(expectations2, map);
    2713             : 
    2714             :   // Let the test customization do the check.
    2715          25 :   checker.Check(isolate, expectations2, map1, map2);
    2716          25 : }
    2717             : 
    2718             : 
    2719       28342 : TEST(TransitionDataFieldToDataField) {
    2720           5 :   CcTest::InitializeVM();
    2721           5 :   v8::HandleScope scope(CcTest::isolate());
    2722             :   Isolate* isolate = CcTest::i_isolate();
    2723             : 
    2724           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2725             : 
    2726             :   Handle<Object> value1 = handle(Smi::kZero, isolate);
    2727             :   TransitionToDataFieldOperator transition_op1(
    2728             :       PropertyConstness::kMutable, Representation::Smi(), any_type, value1);
    2729             : 
    2730           5 :   Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
    2731             :   TransitionToDataFieldOperator transition_op2(
    2732             :       PropertyConstness::kMutable, Representation::Double(), any_type, value2);
    2733             : 
    2734             :   FieldGeneralizationChecker checker(kPropCount - 1,
    2735             :                                      PropertyConstness::kMutable,
    2736             :                                      Representation::Double(), any_type);
    2737           5 :   TestTransitionTo(transition_op1, transition_op2, checker);
    2738           5 : }
    2739             : 
    2740       28342 : TEST(TransitionDataConstantToSameDataConstant) {
    2741           5 :   CcTest::InitializeVM();
    2742           5 :   v8::HandleScope scope(CcTest::isolate());
    2743             :   Isolate* isolate = CcTest::i_isolate();
    2744             :   Factory* factory = isolate->factory();
    2745             : 
    2746             :   Handle<JSFunction> js_func =
    2747           5 :       factory->NewFunctionForTest(factory->empty_string());
    2748             :   TransitionToDataConstantOperator transition_op(js_func);
    2749             : 
    2750             :   SameMapChecker checker;
    2751           5 :   TestTransitionTo(transition_op, transition_op, checker);
    2752           5 : }
    2753             : 
    2754             : 
    2755       28342 : TEST(TransitionDataConstantToAnotherDataConstant) {
    2756           5 :   CcTest::InitializeVM();
    2757           5 :   v8::HandleScope scope(CcTest::isolate());
    2758             :   Isolate* isolate = CcTest::i_isolate();
    2759             :   Factory* factory = isolate->factory();
    2760             : 
    2761             :   Handle<String> name = factory->empty_string();
    2762             :   Handle<Map> sloppy_map =
    2763           5 :       Map::CopyInitialMap(isolate, isolate->sloppy_function_map());
    2764             :   Handle<SharedFunctionInfo> info =
    2765           5 :       factory->NewSharedFunctionInfoForBuiltin(name, Builtins::kIllegal);
    2766           5 :   Handle<FieldType> function_type = FieldType::Class(sloppy_map, isolate);
    2767           5 :   CHECK(sloppy_map->is_stable());
    2768             : 
    2769             :   Handle<JSFunction> js_func1 =
    2770          10 :       factory->NewFunction(sloppy_map, info, isolate->native_context());
    2771             :   TransitionToDataConstantOperator transition_op1(js_func1);
    2772             : 
    2773             :   Handle<JSFunction> js_func2 =
    2774          10 :       factory->NewFunction(sloppy_map, info, isolate->native_context());
    2775             :   TransitionToDataConstantOperator transition_op2(js_func2);
    2776             : 
    2777             :   if (FLAG_track_constant_fields) {
    2778             :     SameMapChecker checker;
    2779             :     TestTransitionTo(transition_op1, transition_op2, checker);
    2780             : 
    2781             :   } else {
    2782             :     FieldGeneralizationChecker checker(
    2783             :         kPropCount - 1, PropertyConstness::kMutable,
    2784             :         Representation::HeapObject(), function_type);
    2785           5 :     TestTransitionTo(transition_op1, transition_op2, checker);
    2786           5 :   }
    2787           5 : }
    2788             : 
    2789             : 
    2790       28342 : TEST(TransitionDataConstantToDataField) {
    2791           5 :   CcTest::InitializeVM();
    2792           5 :   v8::HandleScope scope(CcTest::isolate());
    2793             :   Isolate* isolate = CcTest::i_isolate();
    2794             :   Factory* factory = isolate->factory();
    2795             : 
    2796           5 :   Handle<FieldType> any_type = FieldType::Any(isolate);
    2797             : 
    2798             :   Handle<JSFunction> js_func1 =
    2799           5 :       factory->NewFunctionForTest(factory->empty_string());
    2800             :   TransitionToDataConstantOperator transition_op1(js_func1);
    2801             : 
    2802           5 :   Handle<Object> value2 = isolate->factory()->NewHeapNumber(0);
    2803             :   TransitionToDataFieldOperator transition_op2(
    2804             :       PropertyConstness::kMutable, Representation::Double(), any_type, value2);
    2805             : 
    2806             :   FieldGeneralizationChecker checker(kPropCount - 1,
    2807             :                                      PropertyConstness::kMutable,
    2808             :                                      Representation::Tagged(), any_type);
    2809           5 :   TestTransitionTo(transition_op1, transition_op2, checker);
    2810           5 : }
    2811             : 
    2812             : 
    2813       28342 : TEST(TransitionAccessorConstantToSameAccessorConstant) {
    2814           5 :   CcTest::InitializeVM();
    2815           5 :   v8::HandleScope scope(CcTest::isolate());
    2816             : 
    2817           5 :   Handle<AccessorPair> pair = CreateAccessorPair(true, true);
    2818             :   TransitionToAccessorConstantOperator transition_op(pair);
    2819             : 
    2820             :   SameMapChecker checker;
    2821           5 :   TestTransitionTo(transition_op, transition_op, checker);
    2822           5 : }
    2823             : 
    2824             : // TODO(ishell): add this test once IS_ACCESSOR_FIELD_SUPPORTED is supported.
    2825             : // TEST(TransitionAccessorConstantToAnotherAccessorConstant)
    2826             : 
    2827       28342 : TEST(HoleyMutableHeapNumber) {
    2828           5 :   CcTest::InitializeVM();
    2829           5 :   v8::HandleScope scope(CcTest::isolate());
    2830             :   Isolate* isolate = CcTest::i_isolate();
    2831             : 
    2832             :   auto mhn = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
    2833           5 :   CHECK_EQ(kHoleNanInt64, mhn->value_as_bits());
    2834             : 
    2835           5 :   mhn = isolate->factory()->NewMutableHeapNumber(0.0);
    2836           5 :   CHECK_EQ(uint64_t{0}, mhn->value_as_bits());
    2837             : 
    2838             :   mhn->set_value_as_bits(kHoleNanInt64);
    2839           5 :   CHECK_EQ(kHoleNanInt64, mhn->value_as_bits());
    2840             : 
    2841             :   // Ensure that new storage for uninitialized value or mutable heap number
    2842             :   // with uninitialized sentinel (kHoleNanInt64) is a mutable heap number
    2843             :   // with uninitialized sentinel.
    2844             :   Handle<Object> obj =
    2845             :       Object::NewStorageFor(isolate, isolate->factory()->uninitialized_value(),
    2846           5 :                             Representation::Double());
    2847          10 :   CHECK(obj->IsMutableHeapNumber());
    2848           5 :   CHECK_EQ(kHoleNanInt64, MutableHeapNumber::cast(*obj)->value_as_bits());
    2849             : 
    2850           5 :   obj = Object::NewStorageFor(isolate, mhn, Representation::Double());
    2851          10 :   CHECK(obj->IsMutableHeapNumber());
    2852           5 :   CHECK_EQ(kHoleNanInt64, MutableHeapNumber::cast(*obj)->value_as_bits());
    2853           5 : }
    2854             : 
    2855             : }  // namespace test_field_type_tracking
    2856             : }  // namespace compiler
    2857             : }  // namespace internal
    2858       85011 : }  // namespace v8

Generated by: LCOV version 1.10