LCOV - code coverage report
Current view: top level - src/objects - map.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 816 931 87.6 %
Date: 2019-04-19 Functions: 88 98 89.8 %

          Line data    Source code
       1             : // Copyright 2019 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 "src/objects/map.h"
       6             : 
       7             : #include "src/bootstrapper.h"
       8             : #include "src/counters-inl.h"
       9             : #include "src/field-type.h"
      10             : #include "src/frames.h"
      11             : #include "src/handles-inl.h"
      12             : #include "src/heap/heap-write-barrier-inl.h"
      13             : #include "src/isolate.h"
      14             : #include "src/layout-descriptor.h"
      15             : #include "src/log.h"
      16             : #include "src/map-updater.h"
      17             : #include "src/maybe-handles.h"
      18             : #include "src/objects/descriptor-array.h"
      19             : #include "src/objects/js-objects.h"
      20             : #include "src/objects/maybe-object.h"
      21             : #include "src/objects/oddball.h"
      22             : #include "src/ostreams.h"
      23             : #include "src/property.h"
      24             : #include "src/transitions-inl.h"
      25             : #include "src/zone/zone-containers.h"
      26             : 
      27             : namespace v8 {
      28             : namespace internal {
      29             : 
      30     3841764 : Map Map::GetPrototypeChainRootMap(Isolate* isolate) const {
      31             :   DisallowHeapAllocation no_alloc;
      32     3841764 :   if (IsJSReceiverMap()) {
      33     3454891 :     return *this;
      34             :   }
      35             :   int constructor_function_index = GetConstructorFunctionIndex();
      36      386873 :   if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
      37             :     Context native_context = isolate->context()->native_context();
      38             :     JSFunction constructor_function =
      39             :         JSFunction::cast(native_context->get(constructor_function_index));
      40             :     return constructor_function->initial_map();
      41             :   }
      42             :   return ReadOnlyRoots(isolate).null_value()->map();
      43             : }
      44             : 
      45             : // static
      46       31375 : MaybeHandle<JSFunction> Map::GetConstructorFunction(
      47             :     Handle<Map> map, Handle<Context> native_context) {
      48       31375 :   if (map->IsPrimitiveMap()) {
      49             :     int const constructor_function_index = map->GetConstructorFunctionIndex();
      50        8138 :     if (constructor_function_index != kNoConstructorFunctionIndex) {
      51             :       return handle(
      52             :           JSFunction::cast(native_context->get(constructor_function_index)),
      53        8138 :           native_context->GetIsolate());
      54             :     }
      55             :   }
      56       23237 :   return MaybeHandle<JSFunction>();
      57             : }
      58             : 
      59    47870506 : bool Map::IsMapOfGlobalProxy(Handle<NativeContext> native_context) const {
      60             :   DisallowHeapAllocation no_gc;
      61    47870506 :   if (IsJSGlobalProxyMap()) {
      62      464654 :     Object maybe_constructor = GetConstructor();
      63             :     // Detached global proxies have |null| as their constructor.
      64      929303 :     return maybe_constructor.IsJSFunction() &&
      65             :            JSFunction::cast(maybe_constructor).native_context() ==
      66             :                *native_context;
      67             :   }
      68             :   return false;
      69             : }
      70             : 
      71           0 : void Map::PrintReconfiguration(Isolate* isolate, FILE* file, int modify_index,
      72             :                                PropertyKind kind,
      73             :                                PropertyAttributes attributes) {
      74           0 :   OFStream os(file);
      75           0 :   os << "[reconfiguring]";
      76             :   Name name = instance_descriptors()->GetKey(modify_index);
      77           0 :   if (name->IsString()) {
      78           0 :     String::cast(name)->PrintOn(file);
      79             :   } else {
      80           0 :     os << "{symbol " << reinterpret_cast<void*>(name.ptr()) << "}";
      81             :   }
      82           0 :   os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
      83           0 :   os << attributes << " [";
      84           0 :   JavaScriptFrame::PrintTop(isolate, file, false, true);
      85           0 :   os << "]\n";
      86           0 : }
      87             : 
      88    55718484 : VisitorId Map::GetVisitorId(Map map) {
      89             :   STATIC_ASSERT(kVisitorIdCount <= 256);
      90             : 
      91    55718484 :   const int instance_type = map->instance_type();
      92             : 
      93    55718484 :   if (instance_type < FIRST_NONSTRING_TYPE) {
      94        1064 :     switch (instance_type & kStringRepresentationMask) {
      95             :       case kSeqStringTag:
      96         224 :         if ((instance_type & kStringEncodingMask) == kOneByteStringTag) {
      97             :           return kVisitSeqOneByteString;
      98             :         } else {
      99         112 :           return kVisitSeqTwoByteString;
     100             :         }
     101             : 
     102             :       case kConsStringTag:
     103         112 :         if (IsShortcutCandidate(instance_type)) {
     104             :           return kVisitShortcutCandidate;
     105             :         } else {
     106           0 :           return kVisitConsString;
     107             :         }
     108             : 
     109             :       case kSlicedStringTag:
     110             :         return kVisitSlicedString;
     111             : 
     112             :       case kExternalStringTag:
     113         504 :         return kVisitDataObject;
     114             : 
     115             :       case kThinStringTag:
     116         112 :         return kVisitThinString;
     117             :     }
     118           0 :     UNREACHABLE();
     119             :   }
     120             : 
     121    55717420 :   switch (instance_type) {
     122             :     case BYTE_ARRAY_TYPE:
     123             :       return kVisitByteArray;
     124             : 
     125             :     case BYTECODE_ARRAY_TYPE:
     126          56 :       return kVisitBytecodeArray;
     127             : 
     128             :     case FREE_SPACE_TYPE:
     129          56 :       return kVisitFreeSpace;
     130             : 
     131             :     case EMBEDDER_DATA_ARRAY_TYPE:
     132          56 :       return kVisitEmbedderDataArray;
     133             : 
     134             :     case FIXED_ARRAY_TYPE:
     135             :     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
     136             :     case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
     137             :     case HASH_TABLE_TYPE:
     138             :     case ORDERED_HASH_MAP_TYPE:
     139             :     case ORDERED_HASH_SET_TYPE:
     140             :     case ORDERED_NAME_DICTIONARY_TYPE:
     141             :     case NAME_DICTIONARY_TYPE:
     142             :     case GLOBAL_DICTIONARY_TYPE:
     143             :     case NUMBER_DICTIONARY_TYPE:
     144             :     case SIMPLE_NUMBER_DICTIONARY_TYPE:
     145             :     case STRING_TABLE_TYPE:
     146             :     case SCOPE_INFO_TYPE:
     147             :     case SCRIPT_CONTEXT_TABLE_TYPE:
     148        1008 :       return kVisitFixedArray;
     149             : 
     150             :     case AWAIT_CONTEXT_TYPE:
     151             :     case BLOCK_CONTEXT_TYPE:
     152             :     case CATCH_CONTEXT_TYPE:
     153             :     case DEBUG_EVALUATE_CONTEXT_TYPE:
     154             :     case EVAL_CONTEXT_TYPE:
     155             :     case FUNCTION_CONTEXT_TYPE:
     156             :     case MODULE_CONTEXT_TYPE:
     157             :     case SCRIPT_CONTEXT_TYPE:
     158             :     case WITH_CONTEXT_TYPE:
     159         504 :       return kVisitContext;
     160             : 
     161             :     case NATIVE_CONTEXT_TYPE:
     162          56 :       return kVisitNativeContext;
     163             : 
     164             :     case EPHEMERON_HASH_TABLE_TYPE:
     165          56 :       return kVisitEphemeronHashTable;
     166             : 
     167             :     case WEAK_FIXED_ARRAY_TYPE:
     168             :     case WEAK_ARRAY_LIST_TYPE:
     169         112 :       return kVisitWeakArray;
     170             : 
     171             :     case FIXED_DOUBLE_ARRAY_TYPE:
     172          56 :       return kVisitFixedDoubleArray;
     173             : 
     174             :     case PROPERTY_ARRAY_TYPE:
     175          56 :       return kVisitPropertyArray;
     176             : 
     177             :     case FEEDBACK_CELL_TYPE:
     178         168 :       return kVisitFeedbackCell;
     179             : 
     180             :     case FEEDBACK_VECTOR_TYPE:
     181          56 :       return kVisitFeedbackVector;
     182             : 
     183             :     case ODDBALL_TYPE:
     184         616 :       return kVisitOddball;
     185             : 
     186             :     case MAP_TYPE:
     187          56 :       return kVisitMap;
     188             : 
     189             :     case CODE_TYPE:
     190          56 :       return kVisitCode;
     191             : 
     192             :     case CELL_TYPE:
     193          56 :       return kVisitCell;
     194             : 
     195             :     case PROPERTY_CELL_TYPE:
     196          56 :       return kVisitPropertyCell;
     197             : 
     198             :     case DESCRIPTOR_ARRAY_TYPE:
     199          56 :       return kVisitDescriptorArray;
     200             : 
     201             :     case TRANSITION_ARRAY_TYPE:
     202          56 :       return kVisitTransitionArray;
     203             : 
     204             :     case JS_WEAK_MAP_TYPE:
     205             :     case JS_WEAK_SET_TYPE:
     206       24001 :       return kVisitJSWeakCollection;
     207             : 
     208             :     case CALL_HANDLER_INFO_TYPE:
     209         168 :       return kVisitStruct;
     210             : 
     211             :     case SHARED_FUNCTION_INFO_TYPE:
     212          56 :       return kVisitSharedFunctionInfo;
     213             : 
     214             :     case JS_PROXY_TYPE:
     215         555 :       return kVisitStruct;
     216             : 
     217             :     case SYMBOL_TYPE:
     218          56 :       return kVisitSymbol;
     219             : 
     220             :     case JS_ARRAY_BUFFER_TYPE:
     221       13104 :       return kVisitJSArrayBuffer;
     222             : 
     223             :     case JS_DATA_VIEW_TYPE:
     224         874 :       return kVisitJSDataView;
     225             : 
     226             :     case JS_FUNCTION_TYPE:
     227     1758413 :       return kVisitJSFunction;
     228             : 
     229             :     case JS_TYPED_ARRAY_TYPE:
     230       31431 :       return kVisitJSTypedArray;
     231             : 
     232             :     case SMALL_ORDERED_HASH_MAP_TYPE:
     233          56 :       return kVisitSmallOrderedHashMap;
     234             : 
     235             :     case SMALL_ORDERED_HASH_SET_TYPE:
     236          56 :       return kVisitSmallOrderedHashSet;
     237             : 
     238             :     case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
     239          56 :       return kVisitSmallOrderedNameDictionary;
     240             : 
     241             :     case CODE_DATA_CONTAINER_TYPE:
     242          56 :       return kVisitCodeDataContainer;
     243             : 
     244             :     case WASM_INSTANCE_TYPE:
     245       82891 :       return kVisitWasmInstanceObject;
     246             : 
     247             :     case PREPARSE_DATA_TYPE:
     248          56 :       return kVisitPreparseData;
     249             : 
     250             :     case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE:
     251          56 :       return kVisitUncompiledDataWithoutPreparseData;
     252             : 
     253             :     case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE:
     254          56 :       return kVisitUncompiledDataWithPreparseData;
     255             : 
     256             :     case JS_OBJECT_TYPE:
     257             :     case JS_ERROR_TYPE:
     258             :     case JS_ARGUMENTS_TYPE:
     259             :     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
     260             :     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
     261             :     case JS_GENERATOR_OBJECT_TYPE:
     262             :     case JS_ASYNC_FUNCTION_OBJECT_TYPE:
     263             :     case JS_ASYNC_GENERATOR_OBJECT_TYPE:
     264             :     case JS_MODULE_NAMESPACE_TYPE:
     265             :     case JS_VALUE_TYPE:
     266             :     case JS_DATE_TYPE:
     267             :     case JS_ARRAY_ITERATOR_TYPE:
     268             :     case JS_ARRAY_TYPE:
     269             :     case JS_GLOBAL_PROXY_TYPE:
     270             :     case JS_GLOBAL_OBJECT_TYPE:
     271             :     case JS_MESSAGE_OBJECT_TYPE:
     272             :     case JS_SET_TYPE:
     273             :     case JS_MAP_TYPE:
     274             :     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
     275             :     case JS_SET_VALUE_ITERATOR_TYPE:
     276             :     case JS_MAP_KEY_ITERATOR_TYPE:
     277             :     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
     278             :     case JS_MAP_VALUE_ITERATOR_TYPE:
     279             :     case JS_STRING_ITERATOR_TYPE:
     280             :     case JS_PROMISE_TYPE:
     281             :     case JS_REGEXP_TYPE:
     282             :     case JS_REGEXP_STRING_ITERATOR_TYPE:
     283             :     case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
     284             :     case JS_FINALIZATION_GROUP_TYPE:
     285             : #ifdef V8_INTL_SUPPORT
     286             :     case JS_INTL_V8_BREAK_ITERATOR_TYPE:
     287             :     case JS_INTL_COLLATOR_TYPE:
     288             :     case JS_INTL_DATE_TIME_FORMAT_TYPE:
     289             :     case JS_INTL_LIST_FORMAT_TYPE:
     290             :     case JS_INTL_LOCALE_TYPE:
     291             :     case JS_INTL_NUMBER_FORMAT_TYPE:
     292             :     case JS_INTL_PLURAL_RULES_TYPE:
     293             :     case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
     294             :     case JS_INTL_SEGMENT_ITERATOR_TYPE:
     295             :     case JS_INTL_SEGMENTER_TYPE:
     296             : #endif  // V8_INTL_SUPPORT
     297             :     case WASM_EXCEPTION_TYPE:
     298             :     case WASM_GLOBAL_TYPE:
     299             :     case WASM_MEMORY_TYPE:
     300             :     case WASM_MODULE_TYPE:
     301             :     case WASM_TABLE_TYPE:
     302             :     case JS_BOUND_FUNCTION_TYPE: {
     303             :       const bool has_raw_data_fields =
     304    46175378 :           (FLAG_unbox_double_fields && !map->HasFastPointerLayout()) ||
     305             :           (COMPRESS_POINTERS_BOOL && JSObject::GetEmbedderFieldCount(map) > 0);
     306    46175378 :       return has_raw_data_fields ? kVisitJSObject : kVisitJSObjectFast;
     307             :     }
     308             :     case JS_API_OBJECT_TYPE:
     309             :     case JS_SPECIAL_API_OBJECT_TYPE:
     310     7622515 :       return kVisitJSApiObject;
     311             : 
     312             :     case JS_WEAK_REF_TYPE:
     313         882 :       return kVisitJSWeakRef;
     314             : 
     315             :     case WEAK_CELL_TYPE:
     316          56 :       return kVisitWeakCell;
     317             : 
     318             :     case FILLER_TYPE:
     319             :     case FOREIGN_TYPE:
     320             :     case HEAP_NUMBER_TYPE:
     321             :     case MUTABLE_HEAP_NUMBER_TYPE:
     322             :     case FEEDBACK_METADATA_TYPE:
     323         341 :       return kVisitDataObject;
     324             : 
     325             :     case BIGINT_TYPE:
     326          56 :       return kVisitBigInt;
     327             : 
     328             :     case FIXED_UINT8_ARRAY_TYPE:
     329             :     case FIXED_INT8_ARRAY_TYPE:
     330             :     case FIXED_UINT16_ARRAY_TYPE:
     331             :     case FIXED_INT16_ARRAY_TYPE:
     332             :     case FIXED_UINT32_ARRAY_TYPE:
     333             :     case FIXED_INT32_ARRAY_TYPE:
     334             :     case FIXED_FLOAT32_ARRAY_TYPE:
     335             :     case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
     336             :     case FIXED_BIGUINT64_ARRAY_TYPE:
     337             :     case FIXED_BIGINT64_ARRAY_TYPE:
     338         560 :       return kVisitFixedTypedArrayBase;
     339             : 
     340             :     case FIXED_FLOAT64_ARRAY_TYPE:
     341          56 :       return kVisitFixedFloat64Array;
     342             : 
     343             :     case ALLOCATION_SITE_TYPE:
     344         112 :       return kVisitAllocationSite;
     345             : 
     346             : #define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE:
     347             :       STRUCT_LIST(MAKE_STRUCT_CASE)
     348             : #undef MAKE_STRUCT_CASE
     349        1960 :       if (instance_type == PROTOTYPE_INFO_TYPE) {
     350             :         return kVisitPrototypeInfo;
     351             :       }
     352        1904 :       return kVisitStruct;
     353             : 
     354             :     case LOAD_HANDLER_TYPE:
     355             :     case STORE_HANDLER_TYPE:
     356         392 :       return kVisitDataHandler;
     357             : 
     358             :     default:
     359           0 :       UNREACHABLE();
     360             :   }
     361             : }
     362             : 
     363           0 : void Map::PrintGeneralization(
     364             :     Isolate* isolate, FILE* file, const char* reason, int modify_index,
     365             :     int split, int descriptors, bool descriptor_to_field,
     366             :     Representation old_representation, Representation new_representation,
     367             :     MaybeHandle<FieldType> old_field_type, MaybeHandle<Object> old_value,
     368             :     MaybeHandle<FieldType> new_field_type, MaybeHandle<Object> new_value) {
     369           0 :   OFStream os(file);
     370           0 :   os << "[generalizing]";
     371             :   Name name = instance_descriptors()->GetKey(modify_index);
     372           0 :   if (name->IsString()) {
     373           0 :     String::cast(name)->PrintOn(file);
     374             :   } else {
     375           0 :     os << "{symbol " << reinterpret_cast<void*>(name.ptr()) << "}";
     376             :   }
     377           0 :   os << ":";
     378           0 :   if (descriptor_to_field) {
     379           0 :     os << "c";
     380             :   } else {
     381           0 :     os << old_representation.Mnemonic() << "{";
     382           0 :     if (old_field_type.is_null()) {
     383           0 :       os << Brief(*(old_value.ToHandleChecked()));
     384             :     } else {
     385           0 :       old_field_type.ToHandleChecked()->PrintTo(os);
     386             :     }
     387           0 :     os << "}";
     388             :   }
     389           0 :   os << "->" << new_representation.Mnemonic() << "{";
     390           0 :   if (new_field_type.is_null()) {
     391           0 :     os << Brief(*(new_value.ToHandleChecked()));
     392             :   } else {
     393           0 :     new_field_type.ToHandleChecked()->PrintTo(os);
     394             :   }
     395           0 :   os << "} (";
     396           0 :   if (strlen(reason) > 0) {
     397           0 :     os << reason;
     398             :   } else {
     399           0 :     os << "+" << (descriptors - split) << " maps";
     400             :   }
     401           0 :   os << ") [";
     402           0 :   JavaScriptFrame::PrintTop(isolate, file, false, true);
     403           0 :   os << "]\n";
     404           0 : }
     405             : 
     406             : // static
     407    17305343 : MaybeObjectHandle Map::WrapFieldType(Isolate* isolate, Handle<FieldType> type) {
     408    17305343 :   if (type->IsClass()) {
     409    11636702 :     return MaybeObjectHandle::Weak(type->AsClass(), isolate);
     410             :   }
     411    11486999 :   return MaybeObjectHandle(type);
     412             : }
     413             : 
     414             : // static
     415    37146890 : FieldType Map::UnwrapFieldType(MaybeObject wrapped_type) {
     416    37146890 :   if (wrapped_type->IsCleared()) {
     417         117 :     return FieldType::None();
     418             :   }
     419    37146773 :   HeapObject heap_object;
     420    37146773 :   if (wrapped_type->GetHeapObjectIfWeak(&heap_object)) {
     421     1380508 :     return FieldType::cast(heap_object);
     422             :   }
     423             :   return wrapped_type->cast<FieldType>();
     424             : }
     425             : 
     426    16986724 : MaybeHandle<Map> Map::CopyWithField(Isolate* isolate, Handle<Map> map,
     427             :                                     Handle<Name> name, Handle<FieldType> type,
     428             :                                     PropertyAttributes attributes,
     429             :                                     PropertyConstness constness,
     430             :                                     Representation representation,
     431             :                                     TransitionFlag flag) {
     432             :   DCHECK(DescriptorArray::kNotFound ==
     433             :          map->instance_descriptors()->Search(*name,
     434             :                                              map->NumberOfOwnDescriptors()));
     435             : 
     436             :   // Ensure the descriptor array does not get too big.
     437    16986724 :   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
     438         150 :     return MaybeHandle<Map>();
     439             :   }
     440             : 
     441             :   // Compute the new index for new field.
     442    16986574 :   int index = map->NextFreePropertyIndex();
     443             : 
     444    16986589 :   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
     445        3626 :     constness = PropertyConstness::kMutable;
     446        3626 :     representation = Representation::Tagged();
     447        3626 :     type = FieldType::Any(isolate);
     448             :   } else {
     449    16982963 :     Map::GeneralizeIfCanHaveTransitionableFastElementsKind(
     450    16982963 :         isolate, map->instance_type(), &constness, &representation, &type);
     451             :   }
     452             : 
     453    16986583 :   MaybeObjectHandle wrapped_type = WrapFieldType(isolate, type);
     454             : 
     455             :   DCHECK_IMPLIES(!FLAG_track_constant_fields,
     456             :                  constness == PropertyConstness::kMutable);
     457             :   Descriptor d = Descriptor::DataField(name, index, attributes, constness,
     458    16986575 :                                        representation, wrapped_type);
     459    16986595 :   Handle<Map> new_map = Map::CopyAddDescriptor(isolate, map, &d, flag);
     460    16986591 :   new_map->AccountAddedPropertyField();
     461    16986594 :   return new_map;
     462             : }
     463             : 
     464          30 : MaybeHandle<Map> Map::CopyWithConstant(Isolate* isolate, Handle<Map> map,
     465             :                                        Handle<Name> name,
     466             :                                        Handle<Object> constant,
     467             :                                        PropertyAttributes attributes,
     468             :                                        TransitionFlag flag) {
     469             :   // Ensure the descriptor array does not get too big.
     470          30 :   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
     471           0 :     return MaybeHandle<Map>();
     472             :   }
     473             : 
     474             :   if (FLAG_track_constant_fields) {
     475          30 :     Representation representation = constant->OptimalRepresentation();
     476          30 :     Handle<FieldType> type = constant->OptimalType(isolate, representation);
     477             :     return CopyWithField(isolate, map, name, type, attributes,
     478          30 :                          PropertyConstness::kConst, representation, flag);
     479             :   } else {
     480             :     // Allocate new instance descriptors with (name, constant) added.
     481             :     Descriptor d =
     482             :         Descriptor::DataConstant(isolate, name, 0, constant, attributes);
     483             :     Handle<Map> new_map = Map::CopyAddDescriptor(isolate, map, &d, flag);
     484             :     return new_map;
     485             :   }
     486             : }
     487             : 
     488           0 : bool Map::TransitionRemovesTaggedField(Map target) const {
     489           0 :   int inobject = NumberOfFields();
     490           0 :   int target_inobject = target->NumberOfFields();
     491           0 :   for (int i = target_inobject; i < inobject; i++) {
     492           0 :     FieldIndex index = FieldIndex::ForPropertyIndex(*this, i);
     493           0 :     if (!IsUnboxedDoubleField(index)) return true;
     494             :   }
     495             :   return false;
     496             : }
     497             : 
     498           0 : bool Map::TransitionChangesTaggedFieldToUntaggedField(Map target) const {
     499           0 :   int inobject = NumberOfFields();
     500           0 :   int target_inobject = target->NumberOfFields();
     501             :   int limit = Min(inobject, target_inobject);
     502           0 :   for (int i = 0; i < limit; i++) {
     503           0 :     FieldIndex index = FieldIndex::ForPropertyIndex(target, i);
     504           0 :     if (!IsUnboxedDoubleField(index) && target->IsUnboxedDoubleField(index)) {
     505           0 :       return true;
     506             :     }
     507             :   }
     508             :   return false;
     509             : }
     510             : 
     511           0 : bool Map::TransitionRequiresSynchronizationWithGC(Map target) const {
     512           0 :   return TransitionRemovesTaggedField(target) ||
     513           0 :          TransitionChangesTaggedFieldToUntaggedField(target);
     514             : }
     515             : 
     516       98750 : bool Map::InstancesNeedRewriting(Map target) const {
     517       98750 :   int target_number_of_fields = target->NumberOfFields();
     518       98750 :   int target_inobject = target->GetInObjectProperties();
     519       98750 :   int target_unused = target->UnusedPropertyFields();
     520             :   int old_number_of_fields;
     521             : 
     522             :   return InstancesNeedRewriting(target, target_number_of_fields,
     523             :                                 target_inobject, target_unused,
     524       98750 :                                 &old_number_of_fields);
     525             : }
     526             : 
     527    16370805 : bool Map::InstancesNeedRewriting(Map target, int target_number_of_fields,
     528             :                                  int target_inobject, int target_unused,
     529             :                                  int* old_number_of_fields) const {
     530             :   // If fields were added (or removed), rewrite the instance.
     531    16370805 :   *old_number_of_fields = NumberOfFields();
     532             :   DCHECK(target_number_of_fields >= *old_number_of_fields);
     533    16370832 :   if (target_number_of_fields != *old_number_of_fields) return true;
     534             : 
     535             :   // If smi descriptors were replaced by double descriptors, rewrite.
     536     6449923 :   DescriptorArray old_desc = instance_descriptors();
     537     6449923 :   DescriptorArray new_desc = target->instance_descriptors();
     538             :   int limit = NumberOfOwnDescriptors();
     539    35339793 :   for (int i = 0; i < limit; i++) {
     540    28894844 :     if (new_desc->GetDetails(i).representation().IsDouble() !=
     541    28894846 :         old_desc->GetDetails(i).representation().IsDouble()) {
     542             :       return true;
     543             :     }
     544             :   }
     545             : 
     546             :   // If no fields were added, and no inobject properties were removed, setting
     547             :   // the map is sufficient.
     548     6447433 :   if (target_inobject == GetInObjectProperties()) return false;
     549             :   // In-object slack tracking may have reduced the object size of the new map.
     550             :   // In that case, succeed if all existing fields were inobject, and they still
     551             :   // fit within the new inobject size.
     552             :   DCHECK(target_inobject < GetInObjectProperties());
     553           0 :   if (target_number_of_fields <= target_inobject) {
     554             :     DCHECK(target_number_of_fields + target_unused == target_inobject);
     555             :     return false;
     556             :   }
     557             :   // Otherwise, properties will need to be moved to the backing store.
     558           0 :   return true;
     559             : }
     560             : 
     561    40476022 : int Map::NumberOfFields() const {
     562    40476022 :   DescriptorArray descriptors = instance_descriptors();
     563             :   int result = 0;
     564   512597966 :   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
     565   472121927 :     if (descriptors->GetDetails(i).location() == kField) result++;
     566             :   }
     567    40476039 :   return result;
     568             : }
     569             : 
     570     2558154 : Map::FieldCounts Map::GetFieldCounts() const {
     571     2558154 :   DescriptorArray descriptors = instance_descriptors();
     572             :   int mutable_count = 0;
     573             :   int const_count = 0;
     574   283452710 :   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
     575   140447278 :     PropertyDetails details = descriptors->GetDetails(i);
     576   140447278 :     if (details.location() == kField) {
     577   139477223 :       switch (details.constness()) {
     578             :         case PropertyConstness::kMutable:
     579       24269 :           mutable_count++;
     580       24269 :           break;
     581             :         case PropertyConstness::kConst:
     582   139452954 :           const_count++;
     583   139452954 :           break;
     584             :       }
     585             :     }
     586             :   }
     587     2558154 :   return FieldCounts(mutable_count, const_count);
     588             : }
     589             : 
     590           0 : bool Map::HasOutOfObjectProperties() const {
     591           0 :   return GetInObjectProperties() < NumberOfFields();
     592             : }
     593             : 
     594        1391 : Handle<Map> Map::CopyGeneralizeAllFields(Isolate* isolate, Handle<Map> map,
     595             :                                          ElementsKind elements_kind,
     596             :                                          int modify_index, PropertyKind kind,
     597             :                                          PropertyAttributes attributes,
     598             :                                          const char* reason) {
     599             :   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
     600             :   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
     601             :   Handle<DescriptorArray> descriptors = DescriptorArray::CopyUpTo(
     602        1391 :       isolate, old_descriptors, number_of_own_descriptors);
     603        1391 :   descriptors->GeneralizeAllFields();
     604             : 
     605             :   Handle<LayoutDescriptor> new_layout_descriptor(
     606             :       LayoutDescriptor::FastPointerLayout(), isolate);
     607             :   Handle<Map> new_map = CopyReplaceDescriptors(
     608             :       isolate, map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
     609        1391 :       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
     610             : 
     611             :   // Unless the instance is being migrated, ensure that modify_index is a field.
     612        1391 :   if (modify_index >= 0) {
     613        1378 :     PropertyDetails details = descriptors->GetDetails(modify_index);
     614        1731 :     if (details.constness() != PropertyConstness::kMutable ||
     615        1731 :         details.location() != kField || details.attributes() != attributes) {
     616             :       int field_index = details.location() == kField
     617             :                             ? details.field_index()
     618        2322 :                             : new_map->NumberOfFields();
     619             :       Descriptor d = Descriptor::DataField(
     620             :           isolate, handle(descriptors->GetKey(modify_index), isolate),
     621        1297 :           field_index, attributes, Representation::Tagged());
     622        1297 :       descriptors->Replace(modify_index, &d);
     623        1297 :       if (details.location() != kField) {
     624        1025 :         new_map->AccountAddedPropertyField();
     625             :       }
     626             :     } else {
     627             :       DCHECK(details.attributes() == attributes);
     628             :     }
     629             : 
     630        1378 :     if (FLAG_trace_generalization) {
     631           0 :       MaybeHandle<FieldType> field_type = FieldType::None(isolate);
     632           0 :       if (details.location() == kField) {
     633             :         field_type = handle(
     634           0 :             map->instance_descriptors()->GetFieldType(modify_index), isolate);
     635             :       }
     636           0 :       map->PrintGeneralization(
     637             :           isolate, stdout, reason, modify_index,
     638             :           new_map->NumberOfOwnDescriptors(), new_map->NumberOfOwnDescriptors(),
     639             :           details.location() == kDescriptor, details.representation(),
     640             :           Representation::Tagged(), field_type, MaybeHandle<Object>(),
     641           0 :           FieldType::Any(isolate), MaybeHandle<Object>());
     642             :     }
     643             :   }
     644        2782 :   new_map->set_elements_kind(elements_kind);
     645        1391 :   return new_map;
     646             : }
     647             : 
     648       23351 : void Map::DeprecateTransitionTree(Isolate* isolate) {
     649       23351 :   if (is_deprecated()) return;
     650             :   DisallowHeapAllocation no_gc;
     651             :   TransitionsAccessor transitions(isolate, *this, &no_gc);
     652       23351 :   int num_transitions = transitions.NumberOfTransitions();
     653       64127 :   for (int i = 0; i < num_transitions; ++i) {
     654       20388 :     transitions.GetTarget(i)->DeprecateTransitionTree(isolate);
     655             :   }
     656             :   DCHECK(!constructor_or_backpointer()->IsFunctionTemplateInfo());
     657       23351 :   set_is_deprecated(true);
     658       23351 :   if (FLAG_trace_maps) {
     659          64 :     LOG(isolate, MapEvent("Deprecate", *this, Map()));
     660             :   }
     661       46702 :   dependent_code()->DeoptimizeDependentCodeGroup(
     662       23351 :       isolate, DependentCode::kTransitionGroup);
     663       23351 :   NotifyLeafMapLayoutChange(isolate);
     664             : }
     665             : 
     666             : // Installs |new_descriptors| over the current instance_descriptors to ensure
     667             : // proper sharing of descriptor arrays.
     668        4474 : void Map::ReplaceDescriptors(Isolate* isolate, DescriptorArray new_descriptors,
     669             :                              LayoutDescriptor new_layout_descriptor) {
     670             :   // Don't overwrite the empty descriptor array or initial map's descriptors.
     671        7235 :   if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) {
     672        1740 :     return;
     673             :   }
     674             : 
     675             :   DescriptorArray to_replace = instance_descriptors();
     676             :   // Replace descriptors by new_descriptors in all maps that share it. The old
     677             :   // descriptors will not be trimmed in the mark-compactor, we need to mark
     678             :   // all its elements.
     679        2734 :   Map current = *this;
     680        2734 :   MarkingBarrierForDescriptorArray(isolate->heap(), current, to_replace,
     681             :                                    to_replace->number_of_descriptors());
     682       58630 :   while (current->instance_descriptors() == to_replace) {
     683       28260 :     Object next = current->GetBackPointer();
     684       28260 :     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
     685       27948 :     current->SetEnumLength(kInvalidEnumCacheSentinel);
     686             :     current->UpdateDescriptors(isolate, new_descriptors, new_layout_descriptor,
     687       27948 :                                current->NumberOfOwnDescriptors());
     688       27948 :     current = Map::cast(next);
     689             :   }
     690        2734 :   set_owns_descriptors(false);
     691             : }
     692             : 
     693      975469 : Map Map::FindRootMap(Isolate* isolate) const {
     694      975469 :   Map result = *this;
     695      743348 :   while (true) {
     696     1718817 :     Object back = result->GetBackPointer();
     697     1718823 :     if (back->IsUndefined(isolate)) {
     698             :       // Initial map always owns descriptors and doesn't have unused entries
     699             :       // in the descriptor array.
     700             :       DCHECK(result->owns_descriptors());
     701             :       DCHECK_EQ(result->NumberOfOwnDescriptors(),
     702             :                 result->instance_descriptors()->number_of_descriptors());
     703      975475 :       return result;
     704             :     }
     705      743348 :     result = Map::cast(back);
     706             :   }
     707             : }
     708             : 
     709      640604 : Map Map::FindFieldOwner(Isolate* isolate, int descriptor) const {
     710             :   DisallowHeapAllocation no_allocation;
     711             :   DCHECK_EQ(kField, instance_descriptors()->GetDetails(descriptor).location());
     712      640604 :   Map result = *this;
     713     1084417 :   while (true) {
     714     1725021 :     Object back = result->GetBackPointer();
     715     1725019 :     if (back->IsUndefined(isolate)) break;
     716             :     const Map parent = Map::cast(back);
     717     1569610 :     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
     718     1084417 :     result = parent;
     719             :   }
     720      640602 :   return result;
     721             : }
     722             : 
     723      266124 : void Map::UpdateFieldType(Isolate* isolate, int descriptor, Handle<Name> name,
     724             :                           PropertyConstness new_constness,
     725             :                           Representation new_representation,
     726             :                           const MaybeObjectHandle& new_wrapped_type) {
     727             :   DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeak());
     728             :   // We store raw pointers in the queue, so no allocations are allowed.
     729             :   DisallowHeapAllocation no_allocation;
     730      266124 :   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
     731      266123 :   if (details.location() != kField) return;
     732             :   DCHECK_EQ(kData, details.kind());
     733             : 
     734      532248 :   Zone zone(isolate->allocator(), ZONE_NAME);
     735      266127 :   ZoneQueue<Map> backlog(&zone);
     736             :   backlog.push(*this);
     737             : 
     738     3285390 :   while (!backlog.empty()) {
     739     1509632 :     Map current = backlog.front();
     740             :     backlog.pop();
     741             : 
     742             :     TransitionsAccessor transitions(isolate, current, &no_allocation);
     743     1509635 :     int num_transitions = transitions.NumberOfTransitions();
     744     3996646 :     for (int i = 0; i < num_transitions; ++i) {
     745     1243508 :       Map target = transitions.GetTarget(i);
     746             :       backlog.push(target);
     747             :     }
     748     1509632 :     DescriptorArray descriptors = current->instance_descriptors();
     749     1509632 :     PropertyDetails details = descriptors->GetDetails(descriptor);
     750             : 
     751             :     // It is allowed to change representation here only from None
     752             :     // to something or from Smi or HeapObject to Tagged.
     753             :     DCHECK(details.representation().Equals(new_representation) ||
     754             :            details.representation().CanBeInPlaceChangedTo(new_representation));
     755             : 
     756             :     // Skip if already updated the shared descriptor.
     757     2957651 :     if (new_constness != details.constness() ||
     758     2772651 :         !new_representation.Equals(details.representation()) ||
     759     1263020 :         descriptors->GetFieldType(descriptor) != *new_wrapped_type.object()) {
     760             :       DCHECK_IMPLIES(!FLAG_track_constant_fields,
     761             :                      new_constness == PropertyConstness::kMutable);
     762             :       Descriptor d = Descriptor::DataField(
     763             :           name, descriptors->GetFieldIndex(descriptor), details.attributes(),
     764      267114 :           new_constness, new_representation, new_wrapped_type);
     765      267115 :       descriptors->Replace(descriptor, &d);
     766             :     }
     767             :   }
     768             : }
     769             : 
     770           0 : bool FieldTypeIsCleared(Representation rep, FieldType type) {
     771     1676145 :   return type->IsNone() && rep.IsHeapObject();
     772             : }
     773             : 
     774             : // static
     775      603278 : Handle<FieldType> Map::GeneralizeFieldType(Representation rep1,
     776             :                                            Handle<FieldType> type1,
     777             :                                            Representation rep2,
     778             :                                            Handle<FieldType> type2,
     779             :                                            Isolate* isolate) {
     780             :   // Cleared field types need special treatment. They represent lost knowledge,
     781             :   // so we must be conservative, so their generalization with any other type
     782             :   // is "Any".
     783     1206525 :   if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) {
     784        5091 :     return FieldType::Any(isolate);
     785             :   }
     786      598190 :   if (type1->NowIs(type2)) return type2;
     787       51443 :   if (type2->NowIs(type1)) return type1;
     788       17202 :   return FieldType::Any(isolate);
     789             : }
     790             : 
     791             : // static
     792      709291 : void Map::GeneralizeField(Isolate* isolate, Handle<Map> map, int modify_index,
     793             :                           PropertyConstness new_constness,
     794             :                           Representation new_representation,
     795             :                           Handle<FieldType> new_field_type) {
     796             :   // Check if we actually need to generalize the field type at all.
     797             :   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
     798      709291 :   PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
     799             :   PropertyConstness old_constness = old_details.constness();
     800             :   Representation old_representation = old_details.representation();
     801             :   Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index),
     802     1418583 :                                    isolate);
     803             : 
     804             :   // Return if the current map is general enough to hold requested constness and
     805             :   // representation/field type.
     806     1603035 :   if (IsGeneralizableTo(new_constness, old_constness) &&
     807      463648 :       old_representation.Equals(new_representation) &&
     808     1172935 :       !FieldTypeIsCleared(new_representation, *new_field_type) &&
     809             :       // Checking old_field_type for being cleared is not necessary because
     810             :       // the NowIs check below would fail anyway in that case.
     811     1636578 :       new_field_type->NowIs(old_field_type)) {
     812             :     DCHECK(GeneralizeFieldType(old_representation, old_field_type,
     813             :                                new_representation, new_field_type, isolate)
     814             :                ->NowIs(old_field_type));
     815      443170 :     return;
     816             :   }
     817             : 
     818             :   // Determine the field owner.
     819      532249 :   Handle<Map> field_owner(map->FindFieldOwner(isolate, modify_index), isolate);
     820             :   Handle<DescriptorArray> descriptors(field_owner->instance_descriptors(),
     821             :                                       isolate);
     822             :   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
     823             : 
     824             :   new_field_type =
     825             :       Map::GeneralizeFieldType(old_representation, old_field_type,
     826      266125 :                                new_representation, new_field_type, isolate);
     827             : 
     828             :   new_constness = GeneralizeConstness(old_constness, new_constness);
     829             : 
     830      266128 :   PropertyDetails details = descriptors->GetDetails(modify_index);
     831             :   Handle<Name> name(descriptors->GetKey(modify_index), isolate);
     832             : 
     833      266130 :   MaybeObjectHandle wrapped_type(WrapFieldType(isolate, new_field_type));
     834      532249 :   field_owner->UpdateFieldType(isolate, modify_index, name, new_constness,
     835      266124 :                                new_representation, wrapped_type);
     836      532252 :   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
     837      266125 :       isolate, DependentCode::kFieldOwnerGroup);
     838             : 
     839      266127 :   if (FLAG_trace_generalization) {
     840           0 :     map->PrintGeneralization(
     841             :         isolate, stdout, "field type generalization", modify_index,
     842             :         map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false,
     843             :         details.representation(), details.representation(), old_field_type,
     844           0 :         MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
     845             :   }
     846             : }
     847             : 
     848             : // TODO(ishell): remove.
     849             : // static
     850         734 : Handle<Map> Map::ReconfigureProperty(Isolate* isolate, Handle<Map> map,
     851             :                                      int modify_index, PropertyKind new_kind,
     852             :                                      PropertyAttributes new_attributes,
     853             :                                      Representation new_representation,
     854             :                                      Handle<FieldType> new_field_type) {
     855             :   DCHECK_EQ(kData, new_kind);  // Only kData case is supported.
     856         734 :   MapUpdater mu(isolate, map);
     857             :   return mu.ReconfigureToDataField(modify_index, new_attributes,
     858             :                                    PropertyConstness::kConst,
     859         734 :                                    new_representation, new_field_type);
     860             : }
     861             : 
     862             : // TODO(ishell): remove.
     863             : // static
     864         123 : Handle<Map> Map::ReconfigureElementsKind(Isolate* isolate, Handle<Map> map,
     865             :                                          ElementsKind new_elements_kind) {
     866      292537 :   MapUpdater mu(isolate, map);
     867      292537 :   return mu.ReconfigureElementsKind(new_elements_kind);
     868             : }
     869             : 
     870             : namespace {
     871             : 
     872             : Map SearchMigrationTarget(Isolate* isolate, Map old_map) {
     873             :   DisallowHeapAllocation no_allocation;
     874             :   DisallowDeoptimization no_deoptimization(isolate);
     875             : 
     876             :   Map target = old_map;
     877             :   do {
     878             :     target = TransitionsAccessor(isolate, target, &no_allocation)
     879             :                  .GetMigrationTarget();
     880             :   } while (!target.is_null() && target->is_deprecated());
     881             :   if (target.is_null()) return Map();
     882             : 
     883             :   // TODO(ishell): if this validation ever become a bottleneck consider adding a
     884             :   // bit to the Map telling whether it contains fields whose field types may be
     885             :   // cleared.
     886             :   // TODO(ishell): revisit handling of cleared field types in
     887             :   // TryReplayPropertyTransitions() and consider checking the target map's field
     888             :   // types instead of old_map's types.
     889             :   // Go to slow map updating if the old_map has fast properties with cleared
     890             :   // field types.
     891             :   int old_nof = old_map->NumberOfOwnDescriptors();
     892             :   DescriptorArray old_descriptors = old_map->instance_descriptors();
     893             :   for (int i = 0; i < old_nof; i++) {
     894             :     PropertyDetails old_details = old_descriptors->GetDetails(i);
     895             :     if (old_details.location() == kField && old_details.kind() == kData) {
     896             :       FieldType old_type = old_descriptors->GetFieldType(i);
     897             :       if (FieldTypeIsCleared(old_details.representation(), old_type)) {
     898             :         return Map();
     899             :       }
     900             :     }
     901             :   }
     902             : 
     903             :   SLOW_DCHECK(Map::TryUpdateSlow(isolate, old_map) == target);
     904             :   return target;
     905             : }
     906             : }  // namespace
     907             : 
     908             : // TODO(ishell): Move TryUpdate() and friends to MapUpdater
     909             : // static
     910      192370 : MaybeHandle<Map> Map::TryUpdate(Isolate* isolate, Handle<Map> old_map) {
     911             :   DisallowHeapAllocation no_allocation;
     912             :   DisallowDeoptimization no_deoptimization(isolate);
     913             : 
     914      192370 :   if (!old_map->is_deprecated()) return old_map;
     915             : 
     916             :   if (FLAG_fast_map_update) {
     917             :     Map target_map = SearchMigrationTarget(isolate, *old_map);
     918             :     if (!target_map.is_null()) {
     919             :       return handle(target_map, isolate);
     920             :     }
     921             :   }
     922             : 
     923         233 :   Map new_map = TryUpdateSlow(isolate, *old_map);
     924         233 :   if (new_map.is_null()) return MaybeHandle<Map>();
     925             :   if (FLAG_fast_map_update) {
     926             :     TransitionsAccessor(isolate, *old_map, &no_allocation)
     927             :         .SetMigrationTarget(new_map);
     928             :   }
     929         226 :   return handle(new_map, isolate);
     930             : }
     931             : 
     932             : namespace {
     933             : 
     934             : struct IntegrityLevelTransitionInfo {
     935             :   explicit IntegrityLevelTransitionInfo(Map map)
     936         196 :       : integrity_level_source_map(map) {}
     937             : 
     938             :   bool has_integrity_level_transition = false;
     939             :   PropertyAttributes integrity_level = NONE;
     940             :   Map integrity_level_source_map;
     941             :   Symbol integrity_level_symbol;
     942             : };
     943             : 
     944         196 : IntegrityLevelTransitionInfo DetectIntegrityLevelTransitions(
     945             :     Map map, Isolate* isolate, DisallowHeapAllocation* no_allocation) {
     946             :   IntegrityLevelTransitionInfo info(map);
     947             : 
     948             :   // Figure out the most restrictive integrity level transition (it should
     949             :   // be the last one in the transition tree).
     950             :   DCHECK(!map->is_extensible());
     951         196 :   Map previous = Map::cast(map->GetBackPointer());
     952             :   TransitionsAccessor last_transitions(isolate, previous, no_allocation);
     953         196 :   if (!last_transitions.HasIntegrityLevelTransitionTo(
     954             :           map, &(info.integrity_level_symbol), &(info.integrity_level))) {
     955             :     // The last transition was not integrity level transition - just bail out.
     956             :     // This can happen in the following cases:
     957             :     // - there are private symbol transitions following the integrity level
     958             :     //   transitions (see crbug.com/v8/8854).
     959             :     // - there is a getter added in addition to an existing setter (or a setter
     960             :     //   in addition to an existing getter).
     961             :     return info;
     962             :   }
     963             : 
     964         196 :   Map source_map = previous;
     965             :   // Now walk up the back pointer chain and skip all integrity level
     966             :   // transitions. If we encounter any non-integrity level transition interleaved
     967             :   // with integrity level transitions, just bail out.
     968         210 :   while (!source_map->is_extensible()) {
     969          14 :     previous = Map::cast(source_map->GetBackPointer());
     970             :     TransitionsAccessor transitions(isolate, previous, no_allocation);
     971          14 :     if (!transitions.HasIntegrityLevelTransitionTo(source_map)) {
     972           0 :       return info;
     973             :     }
     974          14 :     source_map = previous;
     975             :   }
     976             : 
     977             :   // Integrity-level transitions never change number of descriptors.
     978         196 :   CHECK_EQ(map->NumberOfOwnDescriptors(), source_map->NumberOfOwnDescriptors());
     979             : 
     980         196 :   info.has_integrity_level_transition = true;
     981         196 :   info.integrity_level_source_map = source_map;
     982             :   return info;
     983             : }
     984             : 
     985             : }  // namespace
     986             : 
     987         233 : Map Map::TryUpdateSlow(Isolate* isolate, Map old_map) {
     988             :   DisallowHeapAllocation no_allocation;
     989             :   DisallowDeoptimization no_deoptimization(isolate);
     990             : 
     991             :   // Check the state of the root map.
     992         233 :   Map root_map = old_map->FindRootMap(isolate);
     993         233 :   if (root_map->is_deprecated()) {
     994           0 :     JSFunction constructor = JSFunction::cast(root_map->GetConstructor());
     995             :     DCHECK(constructor->has_initial_map());
     996             :     DCHECK(constructor->initial_map()->is_dictionary_map());
     997           0 :     if (constructor->initial_map()->elements_kind() !=
     998             :         old_map->elements_kind()) {
     999           0 :       return Map();
    1000             :     }
    1001             :     return constructor->initial_map();
    1002             :   }
    1003         233 :   if (!old_map->EquivalentToForTransition(root_map)) return Map();
    1004             : 
    1005             :   ElementsKind from_kind = root_map->elements_kind();
    1006             :   ElementsKind to_kind = old_map->elements_kind();
    1007             : 
    1008             :   IntegrityLevelTransitionInfo info(old_map);
    1009         233 :   if (root_map->is_extensible() != old_map->is_extensible()) {
    1010             :     DCHECK(!old_map->is_extensible());
    1011             :     DCHECK(root_map->is_extensible());
    1012         196 :     info = DetectIntegrityLevelTransitions(old_map, isolate, &no_allocation);
    1013             :     // Bail out if there were some private symbol transitions mixed up
    1014             :     // with the integrity level transitions.
    1015         196 :     if (!info.has_integrity_level_transition) return Map();
    1016             :     // Make sure to replay the original elements kind transitions, before
    1017             :     // the integrity level transition sets the elements to dictionary mode.
    1018             :     DCHECK(to_kind == DICTIONARY_ELEMENTS ||
    1019             :            to_kind == SLOW_STRING_WRAPPER_ELEMENTS ||
    1020             :            IsFixedTypedArrayElementsKind(to_kind));
    1021             :     to_kind = info.integrity_level_source_map->elements_kind();
    1022             :   }
    1023         233 :   if (from_kind != to_kind) {
    1024             :     // Try to follow existing elements kind transitions.
    1025           7 :     root_map = root_map->LookupElementsTransitionMap(isolate, to_kind);
    1026           7 :     if (root_map.is_null()) return Map();
    1027             :     // From here on, use the map with correct elements kind as root map.
    1028             :   }
    1029             : 
    1030             :   // Replay the transitions as they were before the integrity level transition.
    1031             :   Map result = root_map->TryReplayPropertyTransitions(
    1032         233 :       isolate, info.integrity_level_source_map);
    1033         233 :   if (result.is_null()) return Map();
    1034             : 
    1035         226 :   if (info.has_integrity_level_transition) {
    1036             :     // Now replay the integrity level transition.
    1037             :     result = TransitionsAccessor(isolate, result, &no_allocation)
    1038         196 :                  .SearchSpecial(info.integrity_level_symbol);
    1039             :   }
    1040             : 
    1041             :   DCHECK_IMPLIES(!result.is_null(),
    1042             :                  old_map->elements_kind() == result->elements_kind());
    1043             :   DCHECK_IMPLIES(!result.is_null(),
    1044             :                  old_map->instance_type() == result->instance_type());
    1045         226 :   return result;
    1046             : }
    1047             : 
    1048      105109 : Map Map::TryReplayPropertyTransitions(Isolate* isolate, Map old_map) {
    1049             :   DisallowHeapAllocation no_allocation;
    1050             :   DisallowDeoptimization no_deoptimization(isolate);
    1051             : 
    1052             :   int root_nof = NumberOfOwnDescriptors();
    1053             : 
    1054             :   int old_nof = old_map->NumberOfOwnDescriptors();
    1055      105109 :   DescriptorArray old_descriptors = old_map->instance_descriptors();
    1056             : 
    1057      105109 :   Map new_map = *this;
    1058      111081 :   for (int i = root_nof; i < old_nof; ++i) {
    1059        9119 :     PropertyDetails old_details = old_descriptors->GetDetails(i);
    1060             :     Map transition =
    1061             :         TransitionsAccessor(isolate, new_map, &no_allocation)
    1062             :             .SearchTransition(old_descriptors->GetKey(i), old_details.kind(),
    1063        9119 :                               old_details.attributes());
    1064        9119 :     if (transition.is_null()) return Map();
    1065             :     new_map = transition;
    1066        3019 :     DescriptorArray new_descriptors = new_map->instance_descriptors();
    1067             : 
    1068        3019 :     PropertyDetails new_details = new_descriptors->GetDetails(i);
    1069             :     DCHECK_EQ(old_details.kind(), new_details.kind());
    1070             :     DCHECK_EQ(old_details.attributes(), new_details.attributes());
    1071        3019 :     if (!IsGeneralizableTo(old_details.constness(), new_details.constness())) {
    1072           0 :       return Map();
    1073             :     }
    1074             :     DCHECK(IsGeneralizableTo(old_details.location(), new_details.location()));
    1075        3019 :     if (!old_details.representation().fits_into(new_details.representation())) {
    1076          33 :       return Map();
    1077             :     }
    1078        2986 :     if (new_details.location() == kField) {
    1079        2986 :       if (new_details.kind() == kData) {
    1080        2986 :         FieldType new_type = new_descriptors->GetFieldType(i);
    1081             :         // Cleared field types need special treatment. They represent lost
    1082             :         // knowledge, so we must first generalize the new_type to "Any".
    1083        2986 :         if (FieldTypeIsCleared(new_details.representation(), new_type)) {
    1084           0 :           return Map();
    1085             :         }
    1086             :         DCHECK_EQ(kData, old_details.kind());
    1087        2986 :         if (old_details.location() == kField) {
    1088        2986 :           FieldType old_type = old_descriptors->GetFieldType(i);
    1089        5972 :           if (FieldTypeIsCleared(old_details.representation(), old_type) ||
    1090        2986 :               !old_type->NowIs(new_type)) {
    1091           0 :             return Map();
    1092             :           }
    1093             :         } else {
    1094             :           DCHECK_EQ(kDescriptor, old_details.location());
    1095             :           DCHECK(!FLAG_track_constant_fields);
    1096           0 :           Object old_value = old_descriptors->GetStrongValue(i);
    1097           0 :           if (!new_type->NowContains(old_value)) {
    1098           0 :             return Map();
    1099             :           }
    1100             :         }
    1101             : 
    1102             :       } else {
    1103             :         DCHECK_EQ(kAccessor, new_details.kind());
    1104             : #ifdef DEBUG
    1105             :         FieldType new_type = new_descriptors->GetFieldType(i);
    1106             :         DCHECK(new_type->IsAny());
    1107             : #endif
    1108           0 :         UNREACHABLE();
    1109             :       }
    1110             :     } else {
    1111             :       DCHECK_EQ(kDescriptor, new_details.location());
    1112           0 :       if (old_details.location() == kField ||
    1113             :           old_descriptors->GetStrongValue(i) !=
    1114             :               new_descriptors->GetStrongValue(i)) {
    1115           0 :         return Map();
    1116             :       }
    1117             :     }
    1118             :   }
    1119       98976 :   if (new_map->NumberOfOwnDescriptors() != old_nof) return Map();
    1120       98976 :   return new_map;
    1121             : }
    1122             : 
    1123             : // static
    1124    25780747 : Handle<Map> Map::Update(Isolate* isolate, Handle<Map> map) {
    1125    25780747 :   if (!map->is_deprecated()) return map;
    1126             :   if (FLAG_fast_map_update) {
    1127             :     Map target_map = SearchMigrationTarget(isolate, *map);
    1128             :     if (!target_map.is_null()) {
    1129             :       return handle(target_map, isolate);
    1130             :     }
    1131             :   }
    1132        1105 :   MapUpdater mu(isolate, map);
    1133        1105 :   return mu.Update();
    1134             : }
    1135             : 
    1136     2322671 : void Map::EnsureDescriptorSlack(Isolate* isolate, Handle<Map> map, int slack) {
    1137             :   // Only supports adding slack to owned descriptors.
    1138             :   DCHECK(map->owns_descriptors());
    1139             : 
    1140             :   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
    1141             :   int old_size = map->NumberOfOwnDescriptors();
    1142     2326894 :   if (slack <= descriptors->number_of_slack_descriptors()) return;
    1143             : 
    1144             :   Handle<DescriptorArray> new_descriptors =
    1145     2322671 :       DescriptorArray::CopyUpTo(isolate, descriptors, old_size, slack);
    1146             : 
    1147             :   DisallowHeapAllocation no_allocation;
    1148             :   // The descriptors are still the same, so keep the layout descriptor.
    1149     2322673 :   LayoutDescriptor layout_descriptor = map->GetLayoutDescriptor();
    1150             : 
    1151     2322673 :   if (old_size == 0) {
    1152        8446 :     map->UpdateDescriptors(isolate, *new_descriptors, layout_descriptor,
    1153        4223 :                            map->NumberOfOwnDescriptors());
    1154        4223 :     return;
    1155             :   }
    1156             : 
    1157             :   // If the source descriptors had an enum cache we copy it. This ensures
    1158             :   // that the maps to which we push the new descriptor array back can rely
    1159             :   // on a cache always being available once it is set. If the map has more
    1160             :   // enumerated descriptors than available in the original cache, the cache
    1161             :   // will be lazily replaced by the extended cache when needed.
    1162     4636898 :   new_descriptors->CopyEnumCacheFrom(*descriptors);
    1163             : 
    1164             :   // Replace descriptors by new_descriptors in all maps that share it. The old
    1165             :   // descriptors will not be trimmed in the mark-compactor, we need to mark
    1166             :   // all its elements.
    1167     2318448 :   MarkingBarrierForDescriptorArray(isolate->heap(), *map, *descriptors,
    1168             :                                    descriptors->number_of_descriptors());
    1169             : 
    1170     2318449 :   Map current = *map;
    1171    55402803 :   while (current->instance_descriptors() == *descriptors) {
    1172    26542861 :     Object next = current->GetBackPointer();
    1173    26542862 :     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
    1174             :     current->UpdateDescriptors(isolate, *new_descriptors, layout_descriptor,
    1175    26542178 :                                current->NumberOfOwnDescriptors());
    1176    26542177 :     current = Map::cast(next);
    1177             :   }
    1178     4636900 :   map->UpdateDescriptors(isolate, *new_descriptors, layout_descriptor,
    1179     2318449 :                          map->NumberOfOwnDescriptors());
    1180             : }
    1181             : 
    1182             : // static
    1183      120901 : Handle<Map> Map::GetObjectCreateMap(Isolate* isolate,
    1184             :                                     Handle<HeapObject> prototype) {
    1185      362703 :   Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
    1186             :                   isolate);
    1187      120901 :   if (map->prototype() == *prototype) return map;
    1188      120874 :   if (prototype->IsNull(isolate)) {
    1189         365 :     return isolate->slow_object_with_null_prototype_map();
    1190             :   }
    1191      120509 :   if (prototype->IsJSObject()) {
    1192             :     Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
    1193      119771 :     if (!js_prototype->map()->is_prototype_map()) {
    1194      117024 :       JSObject::OptimizeAsPrototype(js_prototype);
    1195             :     }
    1196             :     Handle<PrototypeInfo> info =
    1197      119771 :         Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
    1198             :     // TODO(verwaest): Use inobject slack tracking for this map.
    1199      119771 :     if (info->HasObjectCreateMap()) {
    1200             :       map = handle(info->ObjectCreateMap(), isolate);
    1201             :     } else {
    1202      119671 :       map = Map::CopyInitialMap(isolate, map);
    1203      119671 :       Map::SetPrototype(isolate, map, prototype);
    1204             :       PrototypeInfo::SetObjectCreateMap(info, map);
    1205             :     }
    1206      119771 :     return map;
    1207             :   }
    1208             : 
    1209         738 :   return Map::TransitionToPrototype(isolate, map, prototype);
    1210             : }
    1211             : 
    1212             : // static
    1213           0 : MaybeHandle<Map> Map::TryGetObjectCreateMap(Isolate* isolate,
    1214             :                                             Handle<HeapObject> prototype) {
    1215           0 :   Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
    1216             :                   isolate);
    1217           0 :   if (map->prototype() == *prototype) return map;
    1218           0 :   if (prototype->IsNull(isolate)) {
    1219           0 :     return isolate->slow_object_with_null_prototype_map();
    1220             :   }
    1221           0 :   if (!prototype->IsJSObject()) return MaybeHandle<Map>();
    1222             :   Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
    1223           0 :   if (!js_prototype->map()->is_prototype_map()) return MaybeHandle<Map>();
    1224             :   Handle<PrototypeInfo> info =
    1225           0 :       Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
    1226           0 :   if (!info->HasObjectCreateMap()) return MaybeHandle<Map>();
    1227           0 :   return handle(info->ObjectCreateMap(), isolate);
    1228             : }
    1229             : 
    1230             : static bool ContainsMap(MapHandles const& maps, Map map) {
    1231             :   DCHECK(!map.is_null());
    1232      180334 :   for (Handle<Map> current : maps) {
    1233      188755 :     if (!current.is_null() && *current == map) return true;
    1234             :   }
    1235             :   return false;
    1236             : }
    1237             : 
    1238       62099 : Map Map::FindElementsKindTransitionedMap(Isolate* isolate,
    1239             :                                          MapHandles const& candidates) {
    1240             :   DisallowHeapAllocation no_allocation;
    1241             :   DisallowDeoptimization no_deoptimization(isolate);
    1242             : 
    1243       62099 :   if (is_prototype_map()) return Map();
    1244             : 
    1245             :   ElementsKind kind = elements_kind();
    1246             :   bool packed = IsFastPackedElementsKind(kind);
    1247             : 
    1248             :   Map transition;
    1249       61526 :   if (IsTransitionableFastElementsKind(kind)) {
    1250             :     // Check the state of the root map.
    1251       32055 :     Map root_map = FindRootMap(isolate);
    1252       32055 :     if (!EquivalentToForElementsKindTransition(root_map)) return Map();
    1253       32055 :     root_map = root_map->LookupElementsTransitionMap(isolate, kind);
    1254             :     DCHECK(!root_map.is_null());
    1255             :     // Starting from the next existing elements kind transition try to
    1256             :     // replay the property transitions that does not involve instance rewriting
    1257             :     // (ElementsTransitionAndStoreStub does not support that).
    1258      273863 :     for (root_map = root_map->ElementsTransitionMap();
    1259      243947 :          !root_map.is_null() && root_map->has_fast_elements();
    1260             :          root_map = root_map->ElementsTransitionMap()) {
    1261      104876 :       Map current = root_map->TryReplayPropertyTransitions(isolate, *this);
    1262      104876 :       if (current.is_null()) continue;
    1263       98750 :       if (InstancesNeedRewriting(current)) continue;
    1264             : 
    1265      197464 :       if (ContainsMap(candidates, current) &&
    1266        1541 :           (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
    1267             :         transition = current;
    1268       23450 :         packed = packed && IsFastPackedElementsKind(current->elements_kind());
    1269             :       }
    1270             :     }
    1271             :   }
    1272       61526 :   return transition;
    1273             : }
    1274             : 
    1275     3200253 : static Map FindClosestElementsTransition(Isolate* isolate, Map map,
    1276             :                                          ElementsKind to_kind) {
    1277             :   // Ensure we are requested to search elements kind transition "near the root".
    1278             :   DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
    1279             :             map->NumberOfOwnDescriptors());
    1280     3200253 :   Map current_map = map;
    1281             : 
    1282             :   ElementsKind kind = map->elements_kind();
    1283    18815077 :   while (kind != to_kind) {
    1284     7975007 :     Map next_map = current_map->ElementsTransitionMap();
    1285     7975019 :     if (next_map.is_null()) return current_map;
    1286             :     kind = next_map->elements_kind();
    1287     7807412 :     current_map = next_map;
    1288             :   }
    1289             : 
    1290             :   DCHECK_EQ(to_kind, current_map->elements_kind());
    1291     3032658 :   return current_map;
    1292             : }
    1293             : 
    1294       32063 : Map Map::LookupElementsTransitionMap(Isolate* isolate, ElementsKind to_kind) {
    1295       32063 :   Map to_map = FindClosestElementsTransition(isolate, *this, to_kind);
    1296       32063 :   if (to_map->elements_kind() == to_kind) return to_map;
    1297           0 :   return Map();
    1298             : }
    1299             : 
    1300      150670 : bool Map::IsMapInArrayPrototypeChain(Isolate* isolate) const {
    1301      301340 :   if (isolate->initial_array_prototype()->map() == *this) {
    1302             :     return true;
    1303             :   }
    1304             : 
    1305      300080 :   if (isolate->initial_object_prototype()->map() == *this) {
    1306             :     return true;
    1307             :   }
    1308             : 
    1309      149830 :   return false;
    1310             : }
    1311             : 
    1312     1197090 : Handle<Map> Map::TransitionElementsTo(Isolate* isolate, Handle<Map> map,
    1313             :                                       ElementsKind to_kind) {
    1314             :   ElementsKind from_kind = map->elements_kind();
    1315     1197090 :   if (from_kind == to_kind) return map;
    1316             : 
    1317      467404 :   Context native_context = isolate->context()->native_context();
    1318      467404 :   if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
    1319        1478 :     if (*map == native_context->fast_aliased_arguments_map()) {
    1320             :       DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
    1321         676 :       return handle(native_context->slow_aliased_arguments_map(), isolate);
    1322             :     }
    1323      466665 :   } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
    1324           0 :     if (*map == native_context->slow_aliased_arguments_map()) {
    1325             :       DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
    1326           0 :       return handle(native_context->fast_aliased_arguments_map(), isolate);
    1327             :     }
    1328      466665 :   } else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
    1329             :     // Reuse map transitions for JSArrays.
    1330             :     DisallowHeapAllocation no_gc;
    1331      354021 :     if (native_context->GetInitialJSArrayMap(from_kind) == *map) {
    1332             :       Object maybe_transitioned_map =
    1333             :           native_context->get(Context::ArrayMapIndex(to_kind));
    1334      173791 :       if (maybe_transitioned_map->IsMap()) {
    1335             :         return handle(Map::cast(maybe_transitioned_map), isolate);
    1336             :       }
    1337             :     }
    1338             :   }
    1339             : 
    1340             :   DCHECK(!map->IsUndefined(isolate));
    1341             :   // Check if we can go back in the elements kind transition chain.
    1342      870567 :   if (IsHoleyElementsKind(from_kind) &&
    1343           0 :       to_kind == GetPackedElementsKind(from_kind) &&
    1344      585876 :       map->GetBackPointer()->IsMap() &&
    1345      292938 :       Map::cast(map->GetBackPointer())->elements_kind() == to_kind) {
    1346           0 :     return handle(Map::cast(map->GetBackPointer()), isolate);
    1347             :   }
    1348             : 
    1349             :   bool allow_store_transition = IsTransitionElementsKind(from_kind);
    1350             :   // Only store fast element maps in ascending generality.
    1351      292938 :   if (IsFastElementsKind(to_kind)) {
    1352             :     allow_store_transition =
    1353       10175 :         allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
    1354        3220 :         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
    1355             :   }
    1356             : 
    1357      292938 :   if (!allow_store_transition) {
    1358         524 :     return Map::CopyAsElementsKind(isolate, map, to_kind, OMIT_TRANSITION);
    1359             :   }
    1360             : 
    1361             :   return Map::ReconfigureElementsKind(isolate, map, to_kind);
    1362             : }
    1363             : 
    1364      167607 : static Handle<Map> AddMissingElementsTransitions(Isolate* isolate,
    1365             :                                                  Handle<Map> map,
    1366             :                                                  ElementsKind to_kind) {
    1367             :   DCHECK(IsTransitionElementsKind(map->elements_kind()));
    1368             : 
    1369             :   Handle<Map> current_map = map;
    1370             : 
    1371             :   ElementsKind kind = map->elements_kind();
    1372             :   TransitionFlag flag;
    1373      167607 :   if (map->is_prototype_map()) {
    1374             :     flag = OMIT_TRANSITION;
    1375             :   } else {
    1376             :     flag = INSERT_TRANSITION;
    1377      166364 :     if (IsFastElementsKind(kind)) {
    1378      340264 :       while (kind != to_kind && !IsTerminalElementsKind(kind)) {
    1379        2997 :         kind = GetNextTransitionElementsKind(kind);
    1380        2997 :         current_map = Map::CopyAsElementsKind(isolate, current_map, kind, flag);
    1381             :       }
    1382             :     }
    1383             :   }
    1384             : 
    1385             :   // In case we are exiting the fast elements kind system, just add the map in
    1386             :   // the end.
    1387      167607 :   if (kind != to_kind) {
    1388      166322 :     current_map = Map::CopyAsElementsKind(isolate, current_map, to_kind, flag);
    1389             :   }
    1390             : 
    1391             :   DCHECK(current_map->elements_kind() == to_kind);
    1392      167607 :   return current_map;
    1393             : }
    1394             : 
    1395             : // static
    1396     3168193 : Handle<Map> Map::AsElementsKind(Isolate* isolate, Handle<Map> map,
    1397             :                                 ElementsKind kind) {
    1398             :   Handle<Map> closest_map(FindClosestElementsTransition(isolate, *map, kind),
    1399     6336386 :                           isolate);
    1400             : 
    1401     3168202 :   if (closest_map->elements_kind() == kind) {
    1402     3000595 :     return closest_map;
    1403             :   }
    1404             : 
    1405      167607 :   return AddMissingElementsTransitions(isolate, closest_map, kind);
    1406             : }
    1407             : 
    1408      168361 : int Map::NumberOfEnumerableProperties() const {
    1409             :   int result = 0;
    1410      168361 :   DescriptorArray descs = instance_descriptors();
    1411             :   int limit = NumberOfOwnDescriptors();
    1412     1446389 :   for (int i = 0; i < limit; i++) {
    1413     2247970 :     if ((descs->GetDetails(i).attributes() & ONLY_ENUMERABLE) == 0 &&
    1414      969942 :         !descs->GetKey(i)->FilterKey(ENUMERABLE_STRINGS)) {
    1415      329127 :       result++;
    1416             :     }
    1417             :   }
    1418      168361 :   return result;
    1419             : }
    1420             : 
    1421    64733991 : int Map::NextFreePropertyIndex() const {
    1422             :   int free_index = 0;
    1423             :   int number_of_own_descriptors = NumberOfOwnDescriptors();
    1424    64733991 :   DescriptorArray descs = instance_descriptors();
    1425  1391944201 :   for (int i = 0; i < number_of_own_descriptors; i++) {
    1426   663605113 :     PropertyDetails details = descs->GetDetails(i);
    1427   663605105 :     if (details.location() == kField) {
    1428   608605620 :       int candidate = details.field_index() + details.field_width_in_words();
    1429   608605620 :       if (candidate > free_index) free_index = candidate;
    1430             :     }
    1431             :   }
    1432    64733983 :   return free_index;
    1433             : }
    1434             : 
    1435       81504 : bool Map::OnlyHasSimpleProperties() const {
    1436             :   // Wrapped string elements aren't explicitly stored in the elements backing
    1437             :   // store, but are loaded indirectly from the underlying string.
    1438       79291 :   return !IsStringWrapperElementsKind(elements_kind()) &&
    1439      201950 :          !IsSpecialReceiverMap() && !has_hidden_prototype() &&
    1440       81504 :          !is_dictionary_map();
    1441             : }
    1442             : 
    1443       63980 : bool Map::DictionaryElementsInPrototypeChainOnly(Isolate* isolate) {
    1444       63980 :   if (IsDictionaryElementsKind(elements_kind())) {
    1445             :     return false;
    1446             :   }
    1447             : 
    1448      200659 :   for (PrototypeIterator iter(isolate, *this); !iter.IsAtEnd();
    1449      138864 :        iter.Advance()) {
    1450             :     // Be conservative, don't walk into proxies.
    1451      149052 :     if (iter.GetCurrent()->IsJSProxy()) return true;
    1452             :     // String wrappers have non-configurable, non-writable elements.
    1453      143958 :     if (iter.GetCurrent()->IsStringWrapper()) return true;
    1454      143940 :     JSObject current = iter.GetCurrent<JSObject>();
    1455             : 
    1456      431820 :     if (current->HasDictionaryElements() &&
    1457      154110 :         current->element_dictionary()->requires_slow_elements()) {
    1458             :       return true;
    1459             :     }
    1460             : 
    1461      138864 :     if (current->HasSlowArgumentsElements()) {
    1462             :       FixedArray parameter_map = FixedArray::cast(current->elements());
    1463             :       Object arguments = parameter_map->get(1);
    1464           0 :       if (NumberDictionary::cast(arguments)->requires_slow_elements()) {
    1465             :         return true;
    1466             :       }
    1467             :     }
    1468             :   }
    1469             : 
    1470       56701 :   return false;
    1471             : }
    1472             : 
    1473    25450771 : Handle<Map> Map::RawCopy(Isolate* isolate, Handle<Map> map, int instance_size,
    1474             :                          int inobject_properties) {
    1475             :   Handle<Map> result = isolate->factory()->NewMap(
    1476             :       map->instance_type(), instance_size, TERMINAL_FAST_ELEMENTS_KIND,
    1477    25450771 :       inobject_properties);
    1478             :   Handle<HeapObject> prototype(map->prototype(), isolate);
    1479    25450760 :   Map::SetPrototype(isolate, result, prototype);
    1480    50901536 :   result->set_constructor_or_backpointer(map->GetConstructor());
    1481             :   result->set_bit_field(map->bit_field());
    1482             :   result->set_bit_field2(map->bit_field2());
    1483             :   int new_bit_field3 = map->bit_field3();
    1484             :   new_bit_field3 = OwnsDescriptorsBit::update(new_bit_field3, true);
    1485             :   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
    1486             :   new_bit_field3 =
    1487             :       EnumLengthBits::update(new_bit_field3, kInvalidEnumCacheSentinel);
    1488    25450758 :   new_bit_field3 = IsDeprecatedBit::update(new_bit_field3, false);
    1489    25450758 :   if (!map->is_dictionary_map()) {
    1490    24464725 :     new_bit_field3 = IsUnstableBit::update(new_bit_field3, false);
    1491             :   }
    1492    25450758 :   result->set_bit_field3(new_bit_field3);
    1493             :   result->clear_padding();
    1494    25450758 :   return result;
    1495             : }
    1496             : 
    1497      679586 : Handle<Map> Map::Normalize(Isolate* isolate, Handle<Map> fast_map,
    1498             :                            PropertyNormalizationMode mode, const char* reason) {
    1499             :   DCHECK(!fast_map->is_dictionary_map());
    1500             : 
    1501     2038757 :   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
    1502      679586 :                              isolate);
    1503             :   bool use_cache =
    1504     1276239 :       !fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate);
    1505             :   Handle<NormalizedMapCache> cache;
    1506      679585 :   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
    1507             : 
    1508             :   Handle<Map> new_map;
    1509     1872671 :   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
    1510             : #ifdef VERIFY_HEAP
    1511             :     if (FLAG_verify_heap) new_map->DictionaryMapVerify(isolate);
    1512             : #endif
    1513             : #ifdef ENABLE_SLOW_DCHECKS
    1514             :     if (FLAG_enable_slow_asserts) {
    1515             :       // The cached map should match newly created normalized map bit-by-bit,
    1516             :       // except for the code cache, which can contain some ICs which can be
    1517             :       // applied to the shared map, dependent code and weak cell cache.
    1518             :       Handle<Map> fresh = Map::CopyNormalized(isolate, fast_map, mode);
    1519             : 
    1520             :       if (new_map->is_prototype_map()) {
    1521             :         // For prototype maps, the PrototypeInfo is not copied.
    1522             :         DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),
    1523             :                             reinterpret_cast<void*>(new_map->address()),
    1524             :                             kTransitionsOrPrototypeInfoOffset));
    1525             :         DCHECK_EQ(fresh->raw_transitions(),
    1526             :                   MaybeObject::FromObject(Smi::kZero));
    1527             :         STATIC_ASSERT(kDescriptorsOffset ==
    1528             :                       kTransitionsOrPrototypeInfoOffset + kTaggedSize);
    1529             :         DCHECK_EQ(0, memcmp(fresh->RawField(kDescriptorsOffset).ToVoidPtr(),
    1530             :                             new_map->RawField(kDescriptorsOffset).ToVoidPtr(),
    1531             :                             kDependentCodeOffset - kDescriptorsOffset));
    1532             :       } else {
    1533             :         DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),
    1534             :                             reinterpret_cast<void*>(new_map->address()),
    1535             :                             Map::kDependentCodeOffset));
    1536             :       }
    1537             :       STATIC_ASSERT(Map::kPrototypeValidityCellOffset ==
    1538             :                     Map::kDependentCodeOffset + kTaggedSize);
    1539             :       int offset = Map::kPrototypeValidityCellOffset + kTaggedSize;
    1540             :       DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address() + offset),
    1541             :                           reinterpret_cast<void*>(new_map->address() + offset),
    1542             :                           Map::kSize - offset));
    1543             :     }
    1544             : #endif
    1545             :   } else {
    1546      248462 :     new_map = Map::CopyNormalized(isolate, fast_map, mode);
    1547      248465 :     if (use_cache) {
    1548      165420 :       cache->Set(fast_map, new_map);
    1549      165420 :       isolate->counters()->maps_normalized()->Increment();
    1550             :     }
    1551      248466 :     if (FLAG_trace_maps) {
    1552         844 :       LOG(isolate, MapEvent("Normalize", *fast_map, *new_map, reason));
    1553             :     }
    1554             :   }
    1555      679589 :   fast_map->NotifyLeafMapLayoutChange(isolate);
    1556      679589 :   return new_map;
    1557             : }
    1558             : 
    1559      248572 : Handle<Map> Map::CopyNormalized(Isolate* isolate, Handle<Map> map,
    1560             :                                 PropertyNormalizationMode mode) {
    1561             :   int new_instance_size = map->instance_size();
    1562      248572 :   if (mode == CLEAR_INOBJECT_PROPERTIES) {
    1563       70248 :     new_instance_size -= map->GetInObjectProperties() * kTaggedSize;
    1564             :   }
    1565             : 
    1566             :   Handle<Map> result = RawCopy(
    1567             :       isolate, map, new_instance_size,
    1568      426896 :       mode == CLEAR_INOBJECT_PROPERTIES ? 0 : map->GetInObjectProperties());
    1569             :   // Clear the unused_property_fields explicitly as this field should not
    1570             :   // be accessed for normalized maps.
    1571      248576 :   result->SetInObjectUnusedPropertyFields(0);
    1572      248576 :   result->set_is_dictionary_map(true);
    1573      248576 :   result->set_is_migration_target(false);
    1574      248576 :   result->set_may_have_interesting_symbols(true);
    1575      248576 :   result->set_construction_counter(kNoSlackTracking);
    1576             : 
    1577             : #ifdef VERIFY_HEAP
    1578             :   if (FLAG_verify_heap) result->DictionaryMapVerify(isolate);
    1579             : #endif
    1580             : 
    1581      248576 :   return result;
    1582             : }
    1583             : 
    1584             : // Return an immutable prototype exotic object version of the input map.
    1585             : // Never even try to cache it in the transition tree, as it is intended
    1586             : // for the global object and its prototype chain, and excluding it saves
    1587             : // memory on the map transition tree.
    1588             : 
    1589             : // static
    1590           6 : Handle<Map> Map::TransitionToImmutableProto(Isolate* isolate, Handle<Map> map) {
    1591           6 :   Handle<Map> new_map = Map::Copy(isolate, map, "ImmutablePrototype");
    1592           6 :   new_map->set_is_immutable_proto(true);
    1593           6 :   return new_map;
    1594             : }
    1595             : 
    1596             : namespace {
    1597             : void EnsureInitialMap(Isolate* isolate, Handle<Map> map) {
    1598             : #ifdef DEBUG
    1599             :   // Strict function maps have Function as a constructor but the
    1600             :   // Function's initial map is a sloppy function map. Same holds for
    1601             :   // GeneratorFunction / AsyncFunction and its initial map.
    1602             :   Object constructor = map->GetConstructor();
    1603             :   DCHECK(constructor->IsJSFunction());
    1604             :   DCHECK(*map == JSFunction::cast(constructor)->initial_map() ||
    1605             :          *map == *isolate->strict_function_map() ||
    1606             :          *map == *isolate->strict_function_with_name_map() ||
    1607             :          *map == *isolate->generator_function_map() ||
    1608             :          *map == *isolate->generator_function_with_name_map() ||
    1609             :          *map == *isolate->generator_function_with_home_object_map() ||
    1610             :          *map == *isolate->generator_function_with_name_and_home_object_map() ||
    1611             :          *map == *isolate->async_function_map() ||
    1612             :          *map == *isolate->async_function_with_name_map() ||
    1613             :          *map == *isolate->async_function_with_home_object_map() ||
    1614             :          *map == *isolate->async_function_with_name_and_home_object_map());
    1615             : #endif
    1616             :   // Initial maps must always own their descriptors and it's descriptor array
    1617             :   // does not contain descriptors that do not belong to the map.
    1618             :   DCHECK(map->owns_descriptors());
    1619             :   DCHECK_EQ(map->NumberOfOwnDescriptors(),
    1620             :             map->instance_descriptors()->number_of_descriptors());
    1621             : }
    1622             : }  // namespace
    1623             : 
    1624             : // static
    1625         111 : Handle<Map> Map::CopyInitialMapNormalized(Isolate* isolate, Handle<Map> map,
    1626             :                                           PropertyNormalizationMode mode) {
    1627             :   EnsureInitialMap(isolate, map);
    1628         111 :   return CopyNormalized(isolate, map, mode);
    1629             : }
    1630             : 
    1631             : // static
    1632      426075 : Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map,
    1633             :                                 int instance_size, int inobject_properties,
    1634             :                                 int unused_property_fields) {
    1635             :   EnsureInitialMap(isolate, map);
    1636             :   Handle<Map> result =
    1637      426075 :       RawCopy(isolate, map, instance_size, inobject_properties);
    1638             : 
    1639             :   // Please note instance_type and instance_size are set when allocated.
    1640      426077 :   result->SetInObjectUnusedPropertyFields(unused_property_fields);
    1641             : 
    1642             :   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
    1643      426077 :   if (number_of_own_descriptors > 0) {
    1644             :     // The copy will use the same descriptors array.
    1645        3968 :     result->UpdateDescriptors(isolate, map->instance_descriptors(),
    1646             :                               map->GetLayoutDescriptor(),
    1647        1984 :                               number_of_own_descriptors);
    1648             : 
    1649             :     DCHECK_EQ(result->NumberOfFields(),
    1650             :               result->GetInObjectProperties() - result->UnusedPropertyFields());
    1651             :   }
    1652             : 
    1653      426077 :   return result;
    1654             : }
    1655             : 
    1656    24776112 : Handle<Map> Map::CopyDropDescriptors(Isolate* isolate, Handle<Map> map) {
    1657             :   Handle<Map> result =
    1658             :       RawCopy(isolate, map, map->instance_size(),
    1659    49552229 :               map->IsJSObjectMap() ? map->GetInObjectProperties() : 0);
    1660             : 
    1661             :   // Please note instance_type and instance_size are set when allocated.
    1662    24776111 :   if (map->IsJSObjectMap()) {
    1663    24775890 :     result->CopyUnusedPropertyFields(*map);
    1664             :   }
    1665    24776107 :   map->NotifyLeafMapLayoutChange(isolate);
    1666    24776119 :   return result;
    1667             : }
    1668             : 
    1669     6187950 : Handle<Map> Map::ShareDescriptor(Isolate* isolate, Handle<Map> map,
    1670             :                                  Handle<DescriptorArray> descriptors,
    1671             :                                  Descriptor* descriptor) {
    1672             :   // Sanity check. This path is only to be taken if the map owns its descriptor
    1673             :   // array, implying that its NumberOfOwnDescriptors equals the number of
    1674             :   // descriptors in the descriptor array.
    1675             :   DCHECK_EQ(map->NumberOfOwnDescriptors(),
    1676             :             map->instance_descriptors()->number_of_descriptors());
    1677             : 
    1678     6187950 :   Handle<Map> result = CopyDropDescriptors(isolate, map);
    1679             :   Handle<Name> name = descriptor->GetKey();
    1680             : 
    1681             :   // Properly mark the {result} if the {name} is an "interesting symbol".
    1682     6187954 :   if (name->IsInterestingSymbol()) {
    1683          64 :     result->set_may_have_interesting_symbols(true);
    1684             :   }
    1685             : 
    1686             :   // Ensure there's space for the new descriptor in the shared descriptor array.
    1687     6187953 :   if (descriptors->number_of_slack_descriptors() == 0) {
    1688     2318447 :     int old_size = descriptors->number_of_descriptors();
    1689     2318447 :     if (old_size == 0) {
    1690         442 :       descriptors = DescriptorArray::Allocate(isolate, 0, 1);
    1691             :     } else {
    1692     2318005 :       int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
    1693     2318005 :       EnsureDescriptorSlack(isolate, map, slack);
    1694             :       descriptors = handle(map->instance_descriptors(), isolate);
    1695             :     }
    1696             :   }
    1697             : 
    1698             :   Handle<LayoutDescriptor> layout_descriptor =
    1699             :       FLAG_unbox_double_fields
    1700             :           ? LayoutDescriptor::ShareAppend(isolate, map,
    1701             :                                           descriptor->GetDetails())
    1702     6187956 :           : handle(LayoutDescriptor::FastPointerLayout(), isolate);
    1703             : 
    1704             :   {
    1705             :     DisallowHeapAllocation no_gc;
    1706     6187957 :     descriptors->Append(descriptor);
    1707     6187954 :     result->InitializeDescriptors(isolate, *descriptors, *layout_descriptor);
    1708             :   }
    1709             : 
    1710             :   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
    1711     6187957 :   ConnectTransition(isolate, map, result, name, SIMPLE_PROPERTY_TRANSITION);
    1712             : 
    1713     6187957 :   return result;
    1714             : }
    1715             : 
    1716    14532694 : void Map::ConnectTransition(Isolate* isolate, Handle<Map> parent,
    1717             :                             Handle<Map> child, Handle<Name> name,
    1718             :                             SimpleTransitionFlag flag) {
    1719             :   DCHECK_IMPLIES(name->IsInterestingSymbol(),
    1720             :                  child->may_have_interesting_symbols());
    1721             :   DCHECK_IMPLIES(parent->may_have_interesting_symbols(),
    1722             :                  child->may_have_interesting_symbols());
    1723             :   // Do not track transitions during bootstrap except for element transitions.
    1724    21726589 :   if (isolate->bootstrapper()->IsActive() &&
    1725             :       !name.is_identical_to(isolate->factory()->elements_transition_symbol())) {
    1726     7192675 :     if (FLAG_trace_maps) {
    1727        3736 :       LOG(isolate,
    1728             :           MapEvent("Transition", *parent, *child,
    1729             :                    child->is_prototype_map() ? "prototype" : "", *name));
    1730             :     }
    1731             :     return;
    1732             :   }
    1733    14680038 :   if (!parent->GetBackPointer()->IsUndefined(isolate)) {
    1734     6399000 :     parent->set_owns_descriptors(false);
    1735             :   } else {
    1736             :     // |parent| is initial map and it must keep the ownership, there must be no
    1737             :     // descriptors in the descriptors array that do not belong to the map.
    1738             :     DCHECK(parent->owns_descriptors());
    1739             :     DCHECK_EQ(parent->NumberOfOwnDescriptors(),
    1740             :               parent->instance_descriptors()->number_of_descriptors());
    1741             :   }
    1742     7340020 :   if (parent->is_prototype_map()) {
    1743             :     DCHECK(child->is_prototype_map());
    1744           0 :     if (FLAG_trace_maps) {
    1745           0 :       LOG(isolate, MapEvent("Transition", *parent, *child, "prototype", *name));
    1746             :     }
    1747             :   } else {
    1748     7340021 :     TransitionsAccessor(isolate, parent).Insert(name, child, flag);
    1749     7340019 :     if (FLAG_trace_maps) {
    1750        4839 :       LOG(isolate, MapEvent("Transition", *parent, *child, "", *name));
    1751             :     }
    1752             :   }
    1753             : }
    1754             : 
    1755    17929559 : Handle<Map> Map::CopyReplaceDescriptors(
    1756             :     Isolate* isolate, Handle<Map> map, Handle<DescriptorArray> descriptors,
    1757             :     Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
    1758             :     MaybeHandle<Name> maybe_name, const char* reason,
    1759             :     SimpleTransitionFlag simple_flag) {
    1760             :   DCHECK(descriptors->IsSortedNoDuplicates());
    1761             : 
    1762    17929559 :   Handle<Map> result = CopyDropDescriptors(isolate, map);
    1763             : 
    1764             :   // Properly mark the {result} if the {name} is an "interesting symbol".
    1765             :   Handle<Name> name;
    1766    30144714 :   if (maybe_name.ToHandle(&name) && name->IsInterestingSymbol()) {
    1767      877862 :     result->set_may_have_interesting_symbols(true);
    1768             :   }
    1769             : 
    1770    17929600 :   if (!map->is_prototype_map()) {
    1771    41604779 :     if (flag == INSERT_TRANSITION &&
    1772    30319364 :         TransitionsAccessor(isolate, map).CanHaveMoreTransitions()) {
    1773     8225552 :       result->InitializeDescriptors(isolate, *descriptors, *layout_descriptor);
    1774             : 
    1775             :       DCHECK(!maybe_name.is_null());
    1776     8225554 :       ConnectTransition(isolate, map, result, name, simple_flag);
    1777             :     } else {
    1778     5642707 :       descriptors->GeneralizeAllFields();
    1779    11285411 :       result->InitializeDescriptors(isolate, *descriptors,
    1780     5642704 :                                     LayoutDescriptor::FastPointerLayout());
    1781             :     }
    1782             :   } else {
    1783     4061339 :     result->InitializeDescriptors(isolate, *descriptors, *layout_descriptor);
    1784             :   }
    1785    35863011 :   if (FLAG_trace_maps &&
    1786             :       // Mirror conditions above that did not call ConnectTransition().
    1787        3222 :       (map->is_prototype_map() ||
    1788             :        !(flag == INSERT_TRANSITION &&
    1789        2260 :          TransitionsAccessor(isolate, map).CanHaveMoreTransitions()))) {
    1790        4009 :     LOG(isolate, MapEvent("ReplaceDescriptors", *map, *result, reason,
    1791             :                           maybe_name.is_null() ? Name() : *name));
    1792             :   }
    1793    17929547 :   return result;
    1794             : }
    1795             : 
    1796             : // Creates transition tree starting from |split_map| and adding all descriptors
    1797             : // starting from descriptor with index |split_map|.NumberOfOwnDescriptors().
    1798             : // The way how it is done is tricky because of GC and special descriptors
    1799             : // marking logic.
    1800        4539 : Handle<Map> Map::AddMissingTransitions(
    1801             :     Isolate* isolate, Handle<Map> split_map,
    1802             :     Handle<DescriptorArray> descriptors,
    1803             :     Handle<LayoutDescriptor> full_layout_descriptor) {
    1804             :   DCHECK(descriptors->IsSortedNoDuplicates());
    1805             :   int split_nof = split_map->NumberOfOwnDescriptors();
    1806        4539 :   int nof_descriptors = descriptors->number_of_descriptors();
    1807             :   DCHECK_LT(split_nof, nof_descriptors);
    1808             : 
    1809             :   // Start with creating last map which will own full descriptors array.
    1810             :   // This is necessary to guarantee that GC will mark the whole descriptor
    1811             :   // array if any of the allocations happening below fail.
    1812             :   // Number of unused properties is temporarily incorrect and the layout
    1813             :   // descriptor could unnecessarily be in slow mode but we will fix after
    1814             :   // all the other intermediate maps are created.
    1815             :   // Also the last map might have interesting symbols, we temporarily set
    1816             :   // the flag and clear it right before the descriptors are installed. This
    1817             :   // makes heap verification happy and ensures the flag ends up accurate.
    1818        4539 :   Handle<Map> last_map = CopyDropDescriptors(isolate, split_map);
    1819        9078 :   last_map->InitializeDescriptors(isolate, *descriptors,
    1820        4539 :                                   *full_layout_descriptor);
    1821        4539 :   last_map->SetInObjectUnusedPropertyFields(0);
    1822        4539 :   last_map->set_may_have_interesting_symbols(true);
    1823             : 
    1824             :   // During creation of intermediate maps we violate descriptors sharing
    1825             :   // invariant since the last map is not yet connected to the transition tree
    1826             :   // we create here. But it is safe because GC never trims map's descriptors
    1827             :   // if there are no dead transitions from that map and this is exactly the
    1828             :   // case for all the intermediate maps we create here.
    1829             :   Handle<Map> map = split_map;
    1830       57301 :   for (int i = split_nof; i < nof_descriptors - 1; ++i) {
    1831       26381 :     Handle<Map> new_map = CopyDropDescriptors(isolate, map);
    1832             :     InstallDescriptors(isolate, map, new_map, i, descriptors,
    1833       26381 :                        full_layout_descriptor);
    1834             : 
    1835       26381 :     map = new_map;
    1836             :   }
    1837        4539 :   map->NotifyLeafMapLayoutChange(isolate);
    1838        4539 :   last_map->set_may_have_interesting_symbols(false);
    1839             :   InstallDescriptors(isolate, map, last_map, nof_descriptors - 1, descriptors,
    1840        4539 :                      full_layout_descriptor);
    1841        4539 :   return last_map;
    1842             : }
    1843             : 
    1844             : // Since this method is used to rewrite an existing transition tree, it can
    1845             : // always insert transitions without checking.
    1846       30920 : void Map::InstallDescriptors(Isolate* isolate, Handle<Map> parent,
    1847             :                              Handle<Map> child, int new_descriptor,
    1848             :                              Handle<DescriptorArray> descriptors,
    1849             :                              Handle<LayoutDescriptor> full_layout_descriptor) {
    1850             :   DCHECK(descriptors->IsSortedNoDuplicates());
    1851             : 
    1852       61840 :   child->SetInstanceDescriptors(isolate, *descriptors, new_descriptor + 1);
    1853       30920 :   child->CopyUnusedPropertyFields(*parent);
    1854       30920 :   PropertyDetails details = descriptors->GetDetails(new_descriptor);
    1855       30920 :   if (details.location() == kField) {
    1856       30232 :     child->AccountAddedPropertyField();
    1857             :   }
    1858             : 
    1859             :   if (FLAG_unbox_double_fields) {
    1860             :     Handle<LayoutDescriptor> layout_descriptor =
    1861             :         LayoutDescriptor::AppendIfFastOrUseFull(isolate, parent, details,
    1862       30920 :                                                 full_layout_descriptor);
    1863       30920 :     child->set_layout_descriptor(*layout_descriptor);
    1864             : #ifdef VERIFY_HEAP
    1865             :     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
    1866             :     if (FLAG_verify_heap) {
    1867             :       CHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
    1868             :     }
    1869             : #else
    1870             :     SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
    1871             : #endif
    1872       61840 :     child->set_visitor_id(Map::GetVisitorId(*child));
    1873             :   }
    1874             : 
    1875             :   Handle<Name> name = handle(descriptors->GetKey(new_descriptor), isolate);
    1876       61787 :   if (parent->may_have_interesting_symbols() || name->IsInterestingSymbol()) {
    1877          62 :     child->set_may_have_interesting_symbols(true);
    1878             :   }
    1879       30920 :   ConnectTransition(isolate, parent, child, name, SIMPLE_PROPERTY_TRANSITION);
    1880       30920 : }
    1881             : 
    1882      170953 : Handle<Map> Map::CopyAsElementsKind(Isolate* isolate, Handle<Map> map,
    1883             :                                     ElementsKind kind, TransitionFlag flag) {
    1884             :   // Only certain objects are allowed to have non-terminal fast transitional
    1885             :   // elements kinds.
    1886             :   DCHECK(map->IsJSObjectMap());
    1887             :   DCHECK_IMPLIES(
    1888             :       !map->CanHaveFastTransitionableElementsKind(),
    1889             :       IsDictionaryElementsKind(kind) || IsTerminalElementsKind(kind));
    1890             : 
    1891             :   Map maybe_elements_transition_map;
    1892      170953 :   if (flag == INSERT_TRANSITION) {
    1893             :     // Ensure we are requested to add elements kind transition "near the root".
    1894             :     DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
    1895             :               map->NumberOfOwnDescriptors());
    1896             : 
    1897      169186 :     maybe_elements_transition_map = map->ElementsTransitionMap();
    1898             :     DCHECK(maybe_elements_transition_map.is_null() ||
    1899             :            (maybe_elements_transition_map->elements_kind() ==
    1900             :                 DICTIONARY_ELEMENTS &&
    1901             :             kind == DICTIONARY_ELEMENTS));
    1902             :     DCHECK(!IsFastElementsKind(kind) ||
    1903             :            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
    1904             :     DCHECK(kind != map->elements_kind());
    1905             :   }
    1906             : 
    1907             :   bool insert_transition =
    1908      169186 :       flag == INSERT_TRANSITION &&
    1909      597475 :       TransitionsAccessor(isolate, map).CanHaveMoreTransitions() &&
    1910        1767 :       maybe_elements_transition_map.is_null();
    1911             : 
    1912      170953 :   if (insert_transition) {
    1913       88150 :     Handle<Map> new_map = CopyForElementsTransition(isolate, map);
    1914      176300 :     new_map->set_elements_kind(kind);
    1915             : 
    1916             :     Handle<Name> name = isolate->factory()->elements_transition_symbol();
    1917       88150 :     ConnectTransition(isolate, map, new_map, name, SPECIAL_TRANSITION);
    1918       88150 :     return new_map;
    1919             :   }
    1920             : 
    1921             :   // Create a new free-floating map only if we are not allowed to store it.
    1922       82803 :   Handle<Map> new_map = Copy(isolate, map, "CopyAsElementsKind");
    1923      165606 :   new_map->set_elements_kind(kind);
    1924       82803 :   return new_map;
    1925             : }
    1926             : 
    1927         671 : Handle<Map> Map::AsLanguageMode(Isolate* isolate, Handle<Map> initial_map,
    1928             :                                 Handle<SharedFunctionInfo> shared_info) {
    1929             :   DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
    1930             :   // Initial map for sloppy mode function is stored in the function
    1931             :   // constructor. Initial maps for strict mode are cached as special transitions
    1932             :   // using |strict_function_transition_symbol| as a key.
    1933         671 :   if (is_sloppy(shared_info->language_mode())) return initial_map;
    1934             : 
    1935         459 :   Handle<Map> function_map(Map::cast(isolate->native_context()->get(
    1936             :                                shared_info->function_map_index())),
    1937             :                            isolate);
    1938             : 
    1939             :   STATIC_ASSERT(LanguageModeSize == 2);
    1940             :   DCHECK_EQ(LanguageMode::kStrict, shared_info->language_mode());
    1941             :   Handle<Symbol> transition_symbol =
    1942             :       isolate->factory()->strict_function_transition_symbol();
    1943             :   Map maybe_transition = TransitionsAccessor(isolate, initial_map)
    1944         153 :                              .SearchSpecial(*transition_symbol);
    1945         153 :   if (!maybe_transition.is_null()) {
    1946             :     return handle(maybe_transition, isolate);
    1947             :   }
    1948         117 :   initial_map->NotifyLeafMapLayoutChange(isolate);
    1949             : 
    1950             :   // Create new map taking descriptors from the |function_map| and all
    1951             :   // the other details from the |initial_map|.
    1952             :   Handle<Map> map =
    1953             :       Map::CopyInitialMap(isolate, function_map, initial_map->instance_size(),
    1954             :                           initial_map->GetInObjectProperties(),
    1955         351 :                           initial_map->UnusedPropertyFields());
    1956         234 :   map->SetConstructor(initial_map->GetConstructor());
    1957         117 :   map->set_prototype(initial_map->prototype());
    1958         117 :   map->set_construction_counter(initial_map->construction_counter());
    1959             : 
    1960         117 :   if (TransitionsAccessor(isolate, initial_map).CanHaveMoreTransitions()) {
    1961         117 :     Map::ConnectTransition(isolate, initial_map, map, transition_symbol,
    1962         117 :                            SPECIAL_TRANSITION);
    1963             :   }
    1964         117 :   return map;
    1965             : }
    1966             : 
    1967       88150 : Handle<Map> Map::CopyForElementsTransition(Isolate* isolate, Handle<Map> map) {
    1968             :   DCHECK(!map->is_prototype_map());
    1969       88150 :   Handle<Map> new_map = CopyDropDescriptors(isolate, map);
    1970             : 
    1971       88150 :   if (map->owns_descriptors()) {
    1972             :     // In case the map owned its own descriptors, share the descriptors and
    1973             :     // transfer ownership to the new map.
    1974             :     // The properties did not change, so reuse descriptors.
    1975      176160 :     new_map->InitializeDescriptors(isolate, map->instance_descriptors(),
    1976       88080 :                                    map->GetLayoutDescriptor());
    1977             :   } else {
    1978             :     // In case the map did not own its own descriptors, a split is forced by
    1979             :     // copying the map; creating a new descriptor array cell.
    1980             :     Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
    1981             :     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
    1982             :     Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
    1983          70 :         isolate, descriptors, number_of_own_descriptors);
    1984             :     Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
    1985             :                                                    isolate);
    1986         140 :     new_map->InitializeDescriptors(isolate, *new_descriptors,
    1987          70 :                                    *new_layout_descriptor);
    1988             :   }
    1989       88150 :   return new_map;
    1990             : }
    1991             : 
    1992     5713079 : Handle<Map> Map::Copy(Isolate* isolate, Handle<Map> map, const char* reason) {
    1993             :   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
    1994             :   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
    1995             :   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
    1996     5713079 :       isolate, descriptors, number_of_own_descriptors);
    1997             :   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
    1998             :                                                  isolate);
    1999             :   return CopyReplaceDescriptors(
    2000             :       isolate, map, new_descriptors, new_layout_descriptor, OMIT_TRANSITION,
    2001     5713079 :       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
    2002             : }
    2003             : 
    2004      150250 : Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
    2005             :   Handle<Map> copy =
    2006      300500 :       Copy(isolate, handle(isolate->object_function()->initial_map(), isolate),
    2007      150251 :            "MapCreate");
    2008             : 
    2009             :   // Check that we do not overflow the instance size when adding the extra
    2010             :   // inobject properties. If the instance size overflows, we allocate as many
    2011             :   // properties as we can as inobject properties.
    2012      150250 :   if (inobject_properties > JSObject::kMaxInObjectProperties) {
    2013             :     inobject_properties = JSObject::kMaxInObjectProperties;
    2014             :   }
    2015             : 
    2016             :   int new_instance_size =
    2017      150250 :       JSObject::kHeaderSize + kTaggedSize * inobject_properties;
    2018             : 
    2019             :   // Adjust the map with the extra inobject properties.
    2020      150250 :   copy->set_instance_size(new_instance_size);
    2021      150251 :   copy->SetInObjectPropertiesStartInWords(JSObject::kHeaderSize / kTaggedSize);
    2022             :   DCHECK_EQ(copy->GetInObjectProperties(), inobject_properties);
    2023      150251 :   copy->SetInObjectUnusedPropertyFields(inobject_properties);
    2024      300498 :   copy->set_visitor_id(Map::GetVisitorId(*copy));
    2025      150249 :   return copy;
    2026             : }
    2027             : 
    2028      137257 : Handle<Map> Map::CopyForPreventExtensions(Isolate* isolate, Handle<Map> map,
    2029             :                                           PropertyAttributes attrs_to_add,
    2030             :                                           Handle<Symbol> transition_marker,
    2031             :                                           const char* reason) {
    2032             :   int num_descriptors = map->NumberOfOwnDescriptors();
    2033             :   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
    2034             :       isolate, handle(map->instance_descriptors(), isolate), num_descriptors,
    2035      137260 :       attrs_to_add);
    2036             :   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
    2037             :                                                  isolate);
    2038             :   Handle<Map> new_map = CopyReplaceDescriptors(
    2039             :       isolate, map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
    2040      137258 :       transition_marker, reason, SPECIAL_TRANSITION);
    2041             :   new_map->set_is_extensible(false);
    2042      137263 :   if (!IsFixedTypedArrayElementsKind(map->elements_kind())) {
    2043             :     ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
    2044             :                                 ? SLOW_STRING_WRAPPER_ELEMENTS
    2045      137197 :                                 : DICTIONARY_ELEMENTS;
    2046      137197 :     if (FLAG_enable_sealed_frozen_elements_kind) {
    2047      137197 :       switch (map->elements_kind()) {
    2048             :         case PACKED_ELEMENTS:
    2049         514 :           if (attrs_to_add == SEALED) {
    2050             :             new_kind = PACKED_SEALED_ELEMENTS;
    2051         416 :           } else if (attrs_to_add == FROZEN) {
    2052             :             new_kind = PACKED_FROZEN_ELEMENTS;
    2053             :           }
    2054             :           break;
    2055             :         case PACKED_SEALED_ELEMENTS:
    2056           9 :           if (attrs_to_add == FROZEN) {
    2057             :             new_kind = PACKED_FROZEN_ELEMENTS;
    2058             :           }
    2059             :           break;
    2060             :         default:
    2061             :           break;
    2062             :       }
    2063             :     }
    2064      274394 :     new_map->set_elements_kind(new_kind);
    2065             :   }
    2066      137261 :   return new_map;
    2067             : }
    2068             : 
    2069             : namespace {
    2070             : 
    2071     7278544 : bool CanHoldValue(DescriptorArray descriptors, int descriptor,
    2072             :                   PropertyConstness constness, Object value) {
    2073     7278544 :   PropertyDetails details = descriptors->GetDetails(descriptor);
    2074     7278539 :   if (details.location() == kField) {
    2075     7278539 :     if (details.kind() == kData) {
    2076     7216439 :       return IsGeneralizableTo(constness, details.constness()) &&
    2077    21495387 :              value->FitsRepresentation(details.representation()) &&
    2078    14278950 :              descriptors->GetFieldType(descriptor)->NowContains(value);
    2079             :     } else {
    2080             :       DCHECK_EQ(kAccessor, details.kind());
    2081             :       return false;
    2082             :     }
    2083             : 
    2084             :   } else {
    2085             :     DCHECK_EQ(kDescriptor, details.location());
    2086             :     DCHECK_EQ(PropertyConstness::kConst, details.constness());
    2087           0 :     if (details.kind() == kData) {
    2088             :       DCHECK(!FLAG_track_constant_fields);
    2089             :       DCHECK(descriptors->GetStrongValue(descriptor) != value ||
    2090             :              value->FitsRepresentation(details.representation()));
    2091             :       return descriptors->GetStrongValue(descriptor) == value;
    2092             :     } else {
    2093             :       DCHECK_EQ(kAccessor, details.kind());
    2094             :       return false;
    2095             :     }
    2096             :   }
    2097             :   UNREACHABLE();
    2098             : }
    2099             : 
    2100     7278542 : Handle<Map> UpdateDescriptorForValue(Isolate* isolate, Handle<Map> map,
    2101             :                                      int descriptor,
    2102             :                                      PropertyConstness constness,
    2103             :                                      Handle<Object> value) {
    2104     7278542 :   if (CanHoldValue(map->instance_descriptors(), descriptor, constness,
    2105             :                    *value)) {
    2106     6993946 :     return map;
    2107             :   }
    2108             : 
    2109             :   PropertyAttributes attributes =
    2110      569206 :       map->instance_descriptors()->GetDetails(descriptor).attributes();
    2111      284603 :   Representation representation = value->OptimalRepresentation();
    2112      284603 :   Handle<FieldType> type = value->OptimalType(isolate, representation);
    2113             : 
    2114      284603 :   MapUpdater mu(isolate, map);
    2115             :   return mu.ReconfigureToDataField(descriptor, attributes, constness,
    2116      284602 :                                    representation, type);
    2117             : }
    2118             : 
    2119             : }  // namespace
    2120             : 
    2121             : // static
    2122     1902470 : Handle<Map> Map::PrepareForDataProperty(Isolate* isolate, Handle<Map> map,
    2123             :                                         int descriptor,
    2124             :                                         PropertyConstness constness,
    2125             :                                         Handle<Object> value) {
    2126             :   // Dictionaries can store any property value.
    2127             :   DCHECK(!map->is_dictionary_map());
    2128             :   // Update to the newest map before storing the property.
    2129             :   return UpdateDescriptorForValue(isolate, Update(isolate, map), descriptor,
    2130     1902470 :                                   constness, value);
    2131             : }
    2132             : 
    2133    22366059 : Handle<Map> Map::TransitionToDataProperty(Isolate* isolate, Handle<Map> map,
    2134             :                                           Handle<Name> name,
    2135             :                                           Handle<Object> value,
    2136             :                                           PropertyAttributes attributes,
    2137             :                                           PropertyConstness constness,
    2138             :                                           StoreOrigin store_origin) {
    2139             :   RuntimeCallTimerScope stats_scope(
    2140             :       isolate, *map,
    2141             :       map->is_prototype_map()
    2142             :           ? RuntimeCallCounterId::kPrototypeMap_TransitionToDataProperty
    2143    22366059 :           : RuntimeCallCounterId::kMap_TransitionToDataProperty);
    2144             : 
    2145             :   DCHECK(name->IsUniqueName());
    2146             :   DCHECK(!map->is_dictionary_map());
    2147             : 
    2148             :   // Migrate to the newest map before storing the property.
    2149    22366059 :   map = Update(isolate, map);
    2150             : 
    2151             :   Map maybe_transition = TransitionsAccessor(isolate, map)
    2152    22366054 :                              .SearchTransition(*name, kData, attributes);
    2153    22366051 :   if (!maybe_transition.is_null()) {
    2154             :     Handle<Map> transition(maybe_transition, isolate);
    2155             :     int descriptor = transition->LastAdded();
    2156             : 
    2157             :     DCHECK_EQ(attributes, transition->instance_descriptors()
    2158             :                               ->GetDetails(descriptor)
    2159             :                               .attributes());
    2160             : 
    2161             :     return UpdateDescriptorForValue(isolate, transition, descriptor, constness,
    2162     5376079 :                                     value);
    2163             :   }
    2164             : 
    2165             :   TransitionFlag flag = INSERT_TRANSITION;
    2166             :   MaybeHandle<Map> maybe_map;
    2167    16989972 :   if (!map->TooManyFastProperties(store_origin)) {
    2168             :     if (!FLAG_track_constant_fields && value->IsJSFunction()) {
    2169             :       maybe_map =
    2170             :           Map::CopyWithConstant(isolate, map, name, value, attributes, flag);
    2171             :     } else {
    2172    16969801 :       Representation representation = value->OptimalRepresentation();
    2173    16969800 :       Handle<FieldType> type = value->OptimalType(isolate, representation);
    2174             :       maybe_map = Map::CopyWithField(isolate, map, name, type, attributes,
    2175    16969794 :                                      constness, representation, flag);
    2176             :     }
    2177             :   }
    2178             : 
    2179             :   Handle<Map> result;
    2180    16989983 :   if (!maybe_map.ToHandle(&result)) {
    2181             :     const char* reason = "TooManyFastProperties";
    2182             : #if V8_TRACE_MAPS
    2183             :     std::unique_ptr<ScopedVector<char>> buffer;
    2184             :     if (FLAG_trace_maps) {
    2185             :       ScopedVector<char> name_buffer(100);
    2186             :       name->NameShortPrint(name_buffer);
    2187             :       buffer.reset(new ScopedVector<char>(128));
    2188             :       SNPrintF(*buffer, "TooManyFastProperties %s", name_buffer.start());
    2189             :       reason = buffer->start();
    2190             :     }
    2191             : #endif
    2192       40662 :     Handle<Object> maybe_constructor(map->GetConstructor(), isolate);
    2193       20331 :     if (FLAG_feedback_normalization && map->new_target_is_base() &&
    2194       20331 :         maybe_constructor->IsJSFunction() &&
    2195             :         !JSFunction::cast(*maybe_constructor)->shared()->native()) {
    2196             :       Handle<JSFunction> constructor =
    2197             :           Handle<JSFunction>::cast(maybe_constructor);
    2198             :       DCHECK_NE(*constructor,
    2199             :                 constructor->context()->native_context()->object_function());
    2200             :       Handle<Map> initial_map(constructor->initial_map(), isolate);
    2201             :       result = Map::Normalize(isolate, initial_map, CLEAR_INOBJECT_PROPERTIES,
    2202           0 :                               reason);
    2203           0 :       initial_map->DeprecateTransitionTree(isolate);
    2204             :       Handle<HeapObject> prototype(result->prototype(), isolate);
    2205           0 :       JSFunction::SetInitialMap(constructor, result, prototype);
    2206             : 
    2207             :       // Deoptimize all code that embeds the previous initial map.
    2208           0 :       initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
    2209           0 :           isolate, DependentCode::kInitialMapChangedGroup);
    2210           0 :       if (!result->EquivalentToForNormalization(*map,
    2211             :                                                 CLEAR_INOBJECT_PROPERTIES)) {
    2212             :         result =
    2213           0 :             Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
    2214             :       }
    2215             :     } else {
    2216       20331 :       result = Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
    2217             :     }
    2218             :   }
    2219             : 
    2220    16989983 :   return result;
    2221             : }
    2222             : 
    2223        2752 : Handle<Map> Map::ReconfigureExistingProperty(Isolate* isolate, Handle<Map> map,
    2224             :                                              int descriptor, PropertyKind kind,
    2225             :                                              PropertyAttributes attributes) {
    2226             :   // Dictionaries have to be reconfigured in-place.
    2227             :   DCHECK(!map->is_dictionary_map());
    2228             : 
    2229        5504 :   if (!map->GetBackPointer()->IsMap()) {
    2230             :     // There is no benefit from reconstructing transition tree for maps without
    2231             :     // back pointers.
    2232             :     return CopyGeneralizeAllFields(isolate, map, map->elements_kind(),
    2233             :                                    descriptor, kind, attributes,
    2234        1211 :                                    "GenAll_AttributesMismatchProtoMap");
    2235             :   }
    2236             : 
    2237        1541 :   if (FLAG_trace_generalization) {
    2238           0 :     map->PrintReconfiguration(isolate, stdout, descriptor, kind, attributes);
    2239             :   }
    2240             : 
    2241        1541 :   MapUpdater mu(isolate, map);
    2242             :   DCHECK_EQ(kData, kind);  // Only kData case is supported so far.
    2243             :   Handle<Map> new_map = mu.ReconfigureToDataField(
    2244             :       descriptor, attributes, kDefaultFieldConstness, Representation::None(),
    2245        1541 :       FieldType::None(isolate));
    2246        1541 :   return new_map;
    2247             : }
    2248             : 
    2249     1510660 : Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
    2250             :                                               Handle<Name> name, int descriptor,
    2251             :                                               Handle<Object> getter,
    2252             :                                               Handle<Object> setter,
    2253             :                                               PropertyAttributes attributes) {
    2254             :   RuntimeCallTimerScope stats_scope(
    2255             :       isolate,
    2256             :       map->is_prototype_map()
    2257             :           ? RuntimeCallCounterId::kPrototypeMap_TransitionToAccessorProperty
    2258     1510660 :           : RuntimeCallCounterId::kMap_TransitionToAccessorProperty);
    2259             : 
    2260             :   // At least one of the accessors needs to be a new value.
    2261             :   DCHECK(!getter->IsNull(isolate) || !setter->IsNull(isolate));
    2262             :   DCHECK(name->IsUniqueName());
    2263             : 
    2264             :   // Dictionary maps can always have additional data properties.
    2265     1510660 :   if (map->is_dictionary_map()) return map;
    2266             : 
    2267             :   // Migrate to the newest map before transitioning to the new property.
    2268     1510660 :   map = Update(isolate, map);
    2269             : 
    2270             :   PropertyNormalizationMode mode = map->is_prototype_map()
    2271             :                                        ? KEEP_INOBJECT_PROPERTIES
    2272     1510661 :                                        : CLEAR_INOBJECT_PROPERTIES;
    2273             : 
    2274             :   Map maybe_transition = TransitionsAccessor(isolate, map)
    2275     1510661 :                              .SearchTransition(*name, kAccessor, attributes);
    2276     1510659 :   if (!maybe_transition.is_null()) {
    2277             :     Handle<Map> transition(maybe_transition, isolate);
    2278             :     DescriptorArray descriptors = transition->instance_descriptors();
    2279             :     int descriptor = transition->LastAdded();
    2280             :     DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
    2281             : 
    2282             :     DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
    2283             :     DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
    2284             : 
    2285             :     Handle<Object> maybe_pair(descriptors->GetStrongValue(descriptor), isolate);
    2286       12127 :     if (!maybe_pair->IsAccessorPair()) {
    2287             :       return Map::Normalize(isolate, map, mode,
    2288           0 :                             "TransitionToAccessorFromNonPair");
    2289             :     }
    2290             : 
    2291             :     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
    2292       12127 :     if (!pair->Equals(*getter, *setter)) {
    2293             :       return Map::Normalize(isolate, map, mode,
    2294       11595 :                             "TransitionToDifferentAccessor");
    2295             :     }
    2296             : 
    2297         532 :     return transition;
    2298             :   }
    2299             : 
    2300             :   Handle<AccessorPair> pair;
    2301     1498532 :   DescriptorArray old_descriptors = map->instance_descriptors();
    2302     1498532 :   if (descriptor != DescriptorArray::kNotFound) {
    2303      219550 :     if (descriptor != map->LastAdded()) {
    2304      117679 :       return Map::Normalize(isolate, map, mode, "AccessorsOverwritingNonLast");
    2305             :     }
    2306      101871 :     PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
    2307      101871 :     if (old_details.kind() != kAccessor) {
    2308             :       return Map::Normalize(isolate, map, mode,
    2309      100182 :                             "AccessorsOverwritingNonAccessors");
    2310             :     }
    2311             : 
    2312        1689 :     if (old_details.attributes() != attributes) {
    2313          81 :       return Map::Normalize(isolate, map, mode, "AccessorsWithAttributes");
    2314             :     }
    2315             : 
    2316             :     Handle<Object> maybe_pair(old_descriptors->GetStrongValue(descriptor),
    2317             :                               isolate);
    2318        1608 :     if (!maybe_pair->IsAccessorPair()) {
    2319          24 :       return Map::Normalize(isolate, map, mode, "AccessorsOverwritingNonPair");
    2320             :     }
    2321             : 
    2322             :     Handle<AccessorPair> current_pair = Handle<AccessorPair>::cast(maybe_pair);
    2323        1584 :     if (current_pair->Equals(*getter, *setter)) return map;
    2324             : 
    2325             :     bool overwriting_accessor = false;
    2326        3154 :     if (!getter->IsNull(isolate) &&
    2327        3064 :         !current_pair->get(ACCESSOR_GETTER)->IsNull(isolate) &&
    2328             :         current_pair->get(ACCESSOR_GETTER) != *getter) {
    2329             :       overwriting_accessor = true;
    2330             :     }
    2331        3159 :     if (!setter->IsNull(isolate) &&
    2332        2760 :         !current_pair->get(ACCESSOR_SETTER)->IsNull(isolate) &&
    2333             :         current_pair->get(ACCESSOR_SETTER) != *setter) {
    2334             :       overwriting_accessor = true;
    2335             :     }
    2336        1584 :     if (overwriting_accessor) {
    2337             :       return Map::Normalize(isolate, map, mode,
    2338        1392 :                             "AccessorsOverwritingAccessors");
    2339             :     }
    2340             : 
    2341         192 :     pair = AccessorPair::Copy(isolate, Handle<AccessorPair>::cast(maybe_pair));
    2342     3836948 :   } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
    2343     2557965 :              map->TooManyFastProperties(StoreOrigin::kNamed)) {
    2344             :     return Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES,
    2345           0 :                           "TooManyAccessors");
    2346             :   } else {
    2347     1278983 :     pair = isolate->factory()->NewAccessorPair();
    2348             :   }
    2349             : 
    2350     1279175 :   pair->SetComponents(*getter, *setter);
    2351             : 
    2352             :   TransitionFlag flag = INSERT_TRANSITION;
    2353     1279175 :   Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
    2354     1279173 :   return Map::CopyInsertDescriptor(isolate, map, &d, flag);
    2355             : }
    2356             : 
    2357    18265604 : Handle<Map> Map::CopyAddDescriptor(Isolate* isolate, Handle<Map> map,
    2358             :                                    Descriptor* descriptor,
    2359             :                                    TransitionFlag flag) {
    2360             :   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
    2361             : 
    2362             :   // Share descriptors only if map owns descriptors and it not an initial map.
    2363    54749285 :   if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
    2364    60937452 :       !map->GetBackPointer()->IsUndefined(isolate) &&
    2365    24453560 :       TransitionsAccessor(isolate, map).CanHaveMoreTransitions()) {
    2366     6187954 :     return ShareDescriptor(isolate, map, descriptors, descriptor);
    2367             :   }
    2368             : 
    2369             :   int nof = map->NumberOfOwnDescriptors();
    2370             :   Handle<DescriptorArray> new_descriptors =
    2371    12077652 :       DescriptorArray::CopyUpTo(isolate, descriptors, nof, 1);
    2372    12077662 :   new_descriptors->Append(descriptor);
    2373             : 
    2374             :   Handle<LayoutDescriptor> new_layout_descriptor =
    2375             :       FLAG_unbox_double_fields
    2376    12077664 :           ? LayoutDescriptor::New(isolate, map, new_descriptors, nof + 1)
    2377    12077664 :           : handle(LayoutDescriptor::FastPointerLayout(), isolate);
    2378             : 
    2379             :   return CopyReplaceDescriptors(
    2380             :       isolate, map, new_descriptors, new_layout_descriptor, flag,
    2381    12077663 :       descriptor->GetKey(), "CopyAddDescriptor", SIMPLE_PROPERTY_TRANSITION);
    2382             : }
    2383             : 
    2384     1279207 : Handle<Map> Map::CopyInsertDescriptor(Isolate* isolate, Handle<Map> map,
    2385             :                                       Descriptor* descriptor,
    2386             :                                       TransitionFlag flag) {
    2387             :   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
    2388             : 
    2389             :   // We replace the key if it is already present.
    2390             :   int index =
    2391     2558418 :       old_descriptors->SearchWithCache(isolate, *descriptor->GetKey(), *map);
    2392     1279209 :   if (index != DescriptorArray::kNotFound) {
    2393             :     return CopyReplaceDescriptor(isolate, map, old_descriptors, descriptor,
    2394         192 :                                  index, flag);
    2395             :   }
    2396     1279017 :   return CopyAddDescriptor(isolate, map, descriptor, flag);
    2397             : }
    2398             : 
    2399         192 : Handle<Map> Map::CopyReplaceDescriptor(Isolate* isolate, Handle<Map> map,
    2400             :                                        Handle<DescriptorArray> descriptors,
    2401             :                                        Descriptor* descriptor,
    2402             :                                        int insertion_index,
    2403             :                                        TransitionFlag flag) {
    2404             :   Handle<Name> key = descriptor->GetKey();
    2405             :   DCHECK_EQ(*key, descriptors->GetKey(insertion_index));
    2406             :   // This function does not support replacing property fields as
    2407             :   // that would break property field counters.
    2408             :   DCHECK_NE(kField, descriptor->GetDetails().location());
    2409             :   DCHECK_NE(kField, descriptors->GetDetails(insertion_index).location());
    2410             : 
    2411             :   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
    2412         192 :       isolate, descriptors, map->NumberOfOwnDescriptors());
    2413             : 
    2414         192 :   new_descriptors->Replace(insertion_index, descriptor);
    2415             :   Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
    2416         192 :       isolate, map, new_descriptors, new_descriptors->number_of_descriptors());
    2417             : 
    2418             :   SimpleTransitionFlag simple_flag =
    2419         192 :       (insertion_index == descriptors->number_of_descriptors() - 1)
    2420             :           ? SIMPLE_PROPERTY_TRANSITION
    2421         192 :           : PROPERTY_TRANSITION;
    2422             :   return CopyReplaceDescriptors(isolate, map, new_descriptors,
    2423             :                                 new_layout_descriptor, flag, key,
    2424         192 :                                 "CopyReplaceDescriptor", simple_flag);
    2425             : }
    2426             : 
    2427      761963 : int Map::Hash() {
    2428             :   // For performance reasons we only hash the 3 most variable fields of a map:
    2429             :   // constructor, prototype and bit_field2. For predictability reasons we
    2430             :   // use objects' offsets in respective pages for hashing instead of raw
    2431             :   // addresses.
    2432             : 
    2433             :   // Shift away the tag.
    2434     1523926 :   int hash = ObjectAddressForHashing(GetConstructor().ptr()) >> 2;
    2435             : 
    2436             :   // XOR-ing the prototype and constructor directly yields too many zero bits
    2437             :   // when the two pointers are close (which is fairly common).
    2438             :   // To avoid this we shift the prototype bits relatively to the constructor.
    2439      761963 :   hash ^= ObjectAddressForHashing(prototype().ptr()) << (32 - kPageSizeBits);
    2440             : 
    2441     1523926 :   return hash ^ (hash >> 16) ^ bit_field2();
    2442             : }
    2443             : 
    2444             : namespace {
    2445             : 
    2446      526796 : bool CheckEquivalent(const Map first, const Map second) {
    2447     1547431 :   return first->GetConstructor() == second->GetConstructor() &&
    2448      478965 :          first->prototype() == second->prototype() &&
    2449      478965 :          first->instance_type() == second->instance_type() &&
    2450      478965 :          first->bit_field() == second->bit_field() &&
    2451      478965 :          first->is_extensible() == second->is_extensible() &&
    2452     1005752 :          first->new_target_is_base() == second->new_target_is_base() &&
    2453      526796 :          first->has_hidden_prototype() == second->has_hidden_prototype();
    2454             : }
    2455             : 
    2456             : }  // namespace
    2457             : 
    2458      426667 : bool Map::EquivalentToForTransition(const Map other) const {
    2459      853336 :   CHECK_EQ(GetConstructor(), other->GetConstructor());
    2460      426669 :   CHECK_EQ(instance_type(), other->instance_type());
    2461      426669 :   CHECK_EQ(has_hidden_prototype(), other->has_hidden_prototype());
    2462             : 
    2463      426669 :   if (bit_field() != other->bit_field()) return false;
    2464      426660 :   if (new_target_is_base() != other->new_target_is_base()) return false;
    2465      426651 :   if (prototype() != other->prototype()) return false;
    2466      426650 :   if (instance_type() == JS_FUNCTION_TYPE) {
    2467             :     // JSFunctions require more checks to ensure that sloppy function is
    2468             :     // not equivalent to strict function.
    2469             :     int nof = Min(NumberOfOwnDescriptors(), other->NumberOfOwnDescriptors());
    2470        9566 :     return instance_descriptors()->IsEqualUpTo(other->instance_descriptors(),
    2471        4783 :                                                nof);
    2472             :   }
    2473             :   return true;
    2474             : }
    2475             : 
    2476           0 : bool Map::EquivalentToForElementsKindTransition(const Map other) const {
    2477       32055 :   if (!EquivalentToForTransition(other)) return false;
    2478             : #ifdef DEBUG
    2479             :   // Ensure that we don't try to generate elements kind transitions from maps
    2480             :   // with fields that may be generalized in-place. This must already be handled
    2481             :   // during addition of a new field.
    2482             :   DescriptorArray descriptors = instance_descriptors();
    2483             :   int nof = NumberOfOwnDescriptors();
    2484             :   for (int i = 0; i < nof; i++) {
    2485             :     PropertyDetails details = descriptors->GetDetails(i);
    2486             :     if (details.location() == kField) {
    2487             :       DCHECK(IsMostGeneralFieldType(details.representation(),
    2488             :                                     descriptors->GetFieldType(i)));
    2489             :     }
    2490             :   }
    2491             : #endif
    2492           0 :   return true;
    2493             : }
    2494             : 
    2495      526796 : bool Map::EquivalentToForNormalization(const Map other,
    2496             :                                        PropertyNormalizationMode mode) const {
    2497             :   int properties =
    2498      526796 :       mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
    2499     1484500 :   return CheckEquivalent(*this, other) && bit_field2() == other->bit_field2() &&
    2500     1436667 :          GetInObjectProperties() == properties &&
    2501      431123 :          JSObject::GetEmbedderFieldCount(*this) ==
    2502      957919 :              JSObject::GetEmbedderFieldCount(other);
    2503             : }
    2504             : 
    2505      380542 : static void GetMinInobjectSlack(Map map, void* data) {
    2506      380542 :   int slack = map->UnusedPropertyFields();
    2507      380543 :   if (*reinterpret_cast<int*>(data) > slack) {
    2508       39312 :     *reinterpret_cast<int*>(data) = slack;
    2509             :   }
    2510      380543 : }
    2511             : 
    2512      135827 : int Map::ComputeMinObjectSlack(Isolate* isolate) {
    2513             :   DisallowHeapAllocation no_gc;
    2514             :   // Has to be an initial map.
    2515             :   DCHECK(GetBackPointer()->IsUndefined(isolate));
    2516             : 
    2517      135827 :   int slack = UnusedPropertyFields();
    2518             :   TransitionsAccessor transitions(isolate, *this, &no_gc);
    2519             :   transitions.TraverseTransitionTree(&GetMinInobjectSlack, &slack);
    2520      135828 :   return slack;
    2521             : }
    2522             : 
    2523      268092 : static void ShrinkInstanceSize(Map map, void* data) {
    2524      268092 :   int slack = *reinterpret_cast<int*>(data);
    2525             :   DCHECK_GE(slack, 0);
    2526             : #ifdef DEBUG
    2527             :   int old_visitor_id = Map::GetVisitorId(map);
    2528             :   int new_unused = map->UnusedPropertyFields() - slack;
    2529             : #endif
    2530      268092 :   map->set_instance_size(map->InstanceSizeFromSlack(slack));
    2531      268092 :   map->set_construction_counter(Map::kNoSlackTracking);
    2532             :   DCHECK_EQ(old_visitor_id, Map::GetVisitorId(map));
    2533             :   DCHECK_EQ(new_unused, map->UnusedPropertyFields());
    2534      268091 : }
    2535             : 
    2536       97977 : static void StopSlackTracking(Map map, void* data) {
    2537       97977 :   map->set_construction_counter(Map::kNoSlackTracking);
    2538       97977 : }
    2539             : 
    2540      129260 : void Map::CompleteInobjectSlackTracking(Isolate* isolate) {
    2541             :   DisallowHeapAllocation no_gc;
    2542             :   // Has to be an initial map.
    2543             :   DCHECK(GetBackPointer()->IsUndefined(isolate));
    2544             : 
    2545      129260 :   int slack = ComputeMinObjectSlack(isolate);
    2546             :   TransitionsAccessor transitions(isolate, *this, &no_gc);
    2547      129261 :   if (slack != 0) {
    2548             :     // Resize the initial map and all maps in its transition tree.
    2549             :     transitions.TraverseTransitionTree(&ShrinkInstanceSize, &slack);
    2550             :   } else {
    2551             :     transitions.TraverseTransitionTree(&StopSlackTracking, nullptr);
    2552             :   }
    2553      129260 : }
    2554             : 
    2555    84462962 : void Map::SetInstanceDescriptors(Isolate* isolate, DescriptorArray descriptors,
    2556             :                                  int number_of_own_descriptors) {
    2557    84462962 :   set_synchronized_instance_descriptors(descriptors);
    2558    84463004 :   SetNumberOfOwnDescriptors(number_of_own_descriptors);
    2559             :   MarkingBarrierForDescriptorArray(isolate->heap(), *this, descriptors,
    2560             :                                    number_of_own_descriptors);
    2561    84463009 : }
    2562             : 
    2563             : // static
    2564      626960 : Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
    2565             :                                                     Isolate* isolate) {
    2566             :   Object maybe_proto_info = prototype->map()->prototype_info();
    2567      626960 :   if (maybe_proto_info->IsPrototypeInfo()) {
    2568             :     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
    2569             :   }
    2570      136966 :   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
    2571      273932 :   prototype->map()->set_prototype_info(*proto_info);
    2572      136966 :   return proto_info;
    2573             : }
    2574             : 
    2575             : // static
    2576     4134384 : Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map,
    2577             :                                                     Isolate* isolate) {
    2578             :   Object maybe_proto_info = prototype_map->prototype_info();
    2579     4134384 :   if (maybe_proto_info->IsPrototypeInfo()) {
    2580             :     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
    2581             :   }
    2582      453861 :   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
    2583      907730 :   prototype_map->set_prototype_info(*proto_info);
    2584      453865 :   return proto_info;
    2585             : }
    2586             : 
    2587             : // static
    2588      551406 : void Map::SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
    2589             :                                       Isolate* isolate) {
    2590      551406 :   if (value == false && !map->prototype_info()->IsPrototypeInfo()) {
    2591             :     // "False" is the implicit default value, so there's nothing to do.
    2592             :     return;
    2593             :   }
    2594     1102812 :   GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
    2595             : }
    2596             : 
    2597             : // static
    2598     1672600 : Handle<Object> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
    2599             :                                                           Isolate* isolate) {
    2600             :   Handle<Object> maybe_prototype;
    2601     1672600 :   if (map->IsJSGlobalObjectMap()) {
    2602             :     DCHECK(map->is_prototype_map());
    2603             :     // Global object is prototype of a global proxy and therefore we can
    2604             :     // use its validity cell for guarding global object's prototype change.
    2605       43078 :     maybe_prototype = isolate->global_object();
    2606             :   } else {
    2607             :     maybe_prototype =
    2608     3259049 :         handle(map->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
    2609             :   }
    2610     1672604 :   if (!maybe_prototype->IsJSObject()) {
    2611       67682 :     return handle(Smi::FromInt(Map::kPrototypeChainValid), isolate);
    2612             :   }
    2613             :   Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
    2614             :   // Ensure the prototype is registered with its own prototypes so its cell
    2615             :   // will be invalidated when necessary.
    2616             :   JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
    2617     1604922 :                                       isolate);
    2618             : 
    2619             :   Object maybe_cell = prototype->map()->prototype_validity_cell();
    2620             :   // Return existing cell if it's still valid.
    2621     1604931 :   if (maybe_cell->IsCell()) {
    2622             :     Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
    2623     1604859 :     if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
    2624     1173647 :       return cell;
    2625             :     }
    2626             :   }
    2627             :   // Otherwise create a new cell.
    2628             :   Handle<Cell> cell = isolate->factory()->NewCell(
    2629      431294 :       handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
    2630      862582 :   prototype->map()->set_prototype_validity_cell(*cell);
    2631      431293 :   return cell;
    2632             : }
    2633             : 
    2634             : // static
    2635           0 : bool Map::IsPrototypeChainInvalidated(Map map) {
    2636             :   DCHECK(map->is_prototype_map());
    2637             :   Object maybe_cell = map->prototype_validity_cell();
    2638           0 :   if (maybe_cell->IsCell()) {
    2639             :     Cell cell = Cell::cast(maybe_cell);
    2640             :     return cell->value() != Smi::FromInt(Map::kPrototypeChainValid);
    2641             :   }
    2642             :   return true;
    2643             : }
    2644             : 
    2645             : // static
    2646    31639364 : void Map::SetPrototype(Isolate* isolate, Handle<Map> map,
    2647             :                        Handle<HeapObject> prototype,
    2648             :                        bool enable_prototype_setup_mode) {
    2649             :   RuntimeCallTimerScope stats_scope(isolate, *map,
    2650             :                                     RuntimeCallCounterId::kMap_SetPrototype);
    2651             : 
    2652             :   bool is_hidden = false;
    2653    31639378 :   if (prototype->IsJSObject()) {
    2654             :     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
    2655    26123281 :     JSObject::OptimizeAsPrototype(prototype_jsobj, enable_prototype_setup_mode);
    2656             : 
    2657    26123315 :     Object maybe_constructor = prototype_jsobj->map()->GetConstructor();
    2658    26123323 :     if (maybe_constructor->IsJSFunction()) {
    2659             :       JSFunction constructor = JSFunction::cast(maybe_constructor);
    2660             :       Object data = constructor->shared()->function_data();
    2661      238183 :       is_hidden = (data->IsFunctionTemplateInfo() &&
    2662    50495308 :                    FunctionTemplateInfo::cast(data)->hidden_prototype()) ||
    2663             :                   prototype->IsJSGlobalObject();
    2664      875671 :     } else if (maybe_constructor->IsFunctionTemplateInfo()) {
    2665             :       is_hidden =
    2666          36 :           FunctionTemplateInfo::cast(maybe_constructor)->hidden_prototype() ||
    2667             :           prototype->IsJSGlobalObject();
    2668             :     }
    2669             :   } else {
    2670             :     DCHECK(prototype->IsNull(isolate) || prototype->IsJSProxy());
    2671             :   }
    2672    63278840 :   map->set_has_hidden_prototype(is_hidden);
    2673             : 
    2674             :   WriteBarrierMode wb_mode =
    2675    31639432 :       prototype->IsNull(isolate) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
    2676    31639432 :   map->set_prototype(*prototype, wb_mode);
    2677    31639417 : }
    2678             : 
    2679      313595 : void Map::StartInobjectSlackTracking() {
    2680             :   DCHECK(!IsInobjectSlackTrackingInProgress());
    2681      313595 :   if (UnusedPropertyFields() == 0) return;
    2682      228731 :   set_construction_counter(Map::kSlackTrackingCounterStart);
    2683             : }
    2684             : 
    2685      185634 : Handle<Map> Map::TransitionToPrototype(Isolate* isolate, Handle<Map> map,
    2686             :                                        Handle<HeapObject> prototype) {
    2687             :   Handle<Map> new_map =
    2688      185634 :       TransitionsAccessor(isolate, map).GetPrototypeTransition(prototype);
    2689      185634 :   if (new_map.is_null()) {
    2690      169405 :     new_map = Copy(isolate, map, "TransitionToPrototype");
    2691             :     TransitionsAccessor(isolate, map)
    2692      169405 :         .PutPrototypeTransition(prototype, new_map);
    2693      169405 :     Map::SetPrototype(isolate, new_map, prototype);
    2694             :   }
    2695      185634 :   return new_map;
    2696             : }
    2697             : 
    2698         111 : Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
    2699             :   Handle<WeakFixedArray> array(
    2700         111 :       isolate->factory()->NewWeakFixedArray(kEntries, AllocationType::kOld));
    2701         111 :   return Handle<NormalizedMapCache>::cast(array);
    2702             : }
    2703             : 
    2704      596543 : MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
    2705             :                                          PropertyNormalizationMode mode) {
    2706             :   DisallowHeapAllocation no_gc;
    2707             :   MaybeObject value = WeakFixedArray::Get(GetIndex(fast_map));
    2708             :   HeapObject heap_object;
    2709      596543 :   if (!value->GetHeapObjectIfWeak(&heap_object)) {
    2710       69747 :     return MaybeHandle<Map>();
    2711             :   }
    2712             : 
    2713      526796 :   Map normalized_map = Map::cast(heap_object);
    2714      526796 :   if (!normalized_map->EquivalentToForNormalization(*fast_map, mode)) {
    2715       95673 :     return MaybeHandle<Map>();
    2716             :   }
    2717      431123 :   return handle(normalized_map, GetIsolate());
    2718             : }
    2719             : 
    2720      165420 : void NormalizedMapCache::Set(Handle<Map> fast_map, Handle<Map> normalized_map) {
    2721             :   DisallowHeapAllocation no_gc;
    2722             :   DCHECK(normalized_map->is_dictionary_map());
    2723      165420 :   WeakFixedArray::Set(GetIndex(fast_map),
    2724      330840 :                       HeapObjectReference::Weak(*normalized_map));
    2725      165420 : }
    2726             : 
    2727             : }  // namespace internal
    2728      122036 : }  // namespace v8

Generated by: LCOV version 1.10