LCOV - code coverage report
Current view: top level - src/objects - map.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 850 970 87.6 %
Date: 2019-02-19 Functions: 89 99 89.9 %

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

Generated by: LCOV version 1.10