LCOV - code coverage report
Current view: top level - src/objects - map.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 803 918 87.5 %
Date: 2019-03-21 Functions: 87 97 89.7 %

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

Generated by: LCOV version 1.10