LCOV - code coverage report
Current view: top level - src/objects - map-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 322 324 99.4 %
Date: 2019-02-19 Functions: 111 111 100.0 %

          Line data    Source code
       1             : // Copyright 2017 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             : #ifndef V8_OBJECTS_MAP_INL_H_
       6             : #define V8_OBJECTS_MAP_INL_H_
       7             : 
       8             : #include "src/objects/map.h"
       9             : 
      10             : #include "src/field-type.h"
      11             : #include "src/heap/heap-write-barrier-inl.h"
      12             : #include "src/layout-descriptor-inl.h"
      13             : #include "src/objects-inl.h"
      14             : #include "src/objects/api-callbacks-inl.h"
      15             : #include "src/objects/cell-inl.h"
      16             : #include "src/objects/descriptor-array-inl.h"
      17             : #include "src/objects/instance-type-inl.h"
      18             : #include "src/objects/prototype-info-inl.h"
      19             : #include "src/objects/shared-function-info.h"
      20             : #include "src/objects/templates-inl.h"
      21             : #include "src/property.h"
      22             : #include "src/transitions.h"
      23             : 
      24             : // Has to be the last include (doesn't have include guards):
      25             : #include "src/objects/object-macros.h"
      26             : 
      27             : namespace v8 {
      28             : namespace internal {
      29             : 
      30  3866267432 : OBJECT_CONSTRUCTORS_IMPL(Map, HeapObject)
      31  1935020386 : CAST_ACCESSOR(Map)
      32             : 
      33   765989711 : DescriptorArray Map::instance_descriptors() const {
      34  1531979436 :   return DescriptorArray::cast(READ_FIELD(*this, kDescriptorsOffset));
      35             : }
      36             : 
      37    28443310 : DescriptorArray Map::synchronized_instance_descriptors() const {
      38    56907107 :   return DescriptorArray::cast(ACQUIRE_READ_FIELD(*this, kDescriptorsOffset));
      39             : }
      40             : 
      41    79226050 : void Map::set_synchronized_instance_descriptors(DescriptorArray value,
      42             :                                                 WriteBarrierMode mode) {
      43    79226050 :   RELEASE_WRITE_FIELD(*this, kDescriptorsOffset, value);
      44   237678165 :   CONDITIONAL_WRITE_BARRIER(*this, kDescriptorsOffset, value, mode);
      45    79226061 : }
      46             : 
      47             : // A freshly allocated layout descriptor can be set on an existing map.
      48             : // We need to use release-store and acquire-load accessor pairs to ensure
      49             : // that the concurrent marking thread observes initializing stores of the
      50             : // layout descriptor.
      51   439047457 : SYNCHRONIZED_ACCESSORS_CHECKED(Map, layout_descriptor, LayoutDescriptor,
      52             :                                kLayoutDescriptorOffset,
      53             :                                FLAG_unbox_double_fields)
      54   278788974 : WEAK_ACCESSORS(Map, raw_transitions, kTransitionsOrPrototypeInfoOffset)
      55             : 
      56             : // |bit_field| fields.
      57      168327 : BIT_FIELD_ACCESSORS(Map, bit_field, has_non_instance_prototype,
      58             :                     Map::HasNonInstancePrototypeBit)
      59    27680596 : BIT_FIELD_ACCESSORS(Map, bit_field, is_callable, Map::IsCallableBit)
      60         336 : BIT_FIELD_ACCESSORS(Map, bit_field, has_named_interceptor,
      61             :                     Map::HasNamedInterceptorBit)
      62         252 : BIT_FIELD_ACCESSORS(Map, bit_field, has_indexed_interceptor,
      63             :                     Map::HasIndexedInterceptorBit)
      64   175869632 : BIT_FIELD_ACCESSORS(Map, bit_field, is_undetectable, Map::IsUndetectableBit)
      65    71244566 : BIT_FIELD_ACCESSORS(Map, bit_field, is_access_check_needed,
      66             :                     Map::IsAccessCheckNeededBit)
      67    12804813 : BIT_FIELD_ACCESSORS(Map, bit_field, is_constructor, Map::IsConstructorBit)
      68        1554 : BIT_FIELD_ACCESSORS(Map, bit_field, has_prototype_slot,
      69             :                     Map::HasPrototypeSlotBit)
      70             : 
      71             : // |bit_field2| fields.
      72      136329 : BIT_FIELD_ACCESSORS(Map, bit_field2, is_extensible, Map::IsExtensibleBit)
      73             : BIT_FIELD_ACCESSORS(Map, bit_field2, is_prototype_map, Map::IsPrototypeMapBit)
      74             : BIT_FIELD_ACCESSORS(Map, bit_field2, is_in_retained_map_list,
      75             :                     Map::IsInRetainedMapListBit)
      76             : 
      77             : // |bit_field3| fields.
      78    50795392 : BIT_FIELD_ACCESSORS(Map, bit_field3, owns_descriptors, Map::OwnsDescriptorsBit)
      79   164181178 : BIT_FIELD_ACCESSORS(Map, bit_field3, has_hidden_prototype,
      80             :                     Map::HasHiddenPrototypeBit)
      81    70422248 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
      82      720960 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_migration_target,
      83             :                     Map::IsMigrationTargetBit)
      84      370174 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_immutable_proto,
      85             :                     Map::IsImmutablePrototypeBit)
      86    68896006 : BIT_FIELD_ACCESSORS(Map, bit_field3, new_target_is_base,
      87             :                     Map::NewTargetIsBaseBit)
      88     3586170 : BIT_FIELD_ACCESSORS(Map, bit_field3, may_have_interesting_symbols,
      89             :                     Map::MayHaveInterestingSymbolsBit)
      90     2167130 : BIT_FIELD_ACCESSORS(Map, bit_field3, construction_counter,
      91             :                     Map::ConstructionCounterBits)
      92             : 
      93     1530911 : InterceptorInfo Map::GetNamedInterceptor() {
      94             :   DCHECK(has_named_interceptor());
      95     1530911 :   FunctionTemplateInfo info = GetFunctionTemplateInfo();
      96     3061822 :   return InterceptorInfo::cast(info->GetNamedPropertyHandler());
      97             : }
      98             : 
      99      621270 : InterceptorInfo Map::GetIndexedInterceptor() {
     100             :   DCHECK(has_indexed_interceptor());
     101      621270 :   FunctionTemplateInfo info = GetFunctionTemplateInfo();
     102     1242540 :   return InterceptorInfo::cast(info->GetIndexedPropertyHandler());
     103             : }
     104             : 
     105             : bool Map::IsMostGeneralFieldType(Representation representation,
     106             :                                  FieldType field_type) {
     107         671 :   return !representation.IsHeapObject() || field_type->IsAny();
     108             : }
     109             : 
     110             : bool Map::CanHaveFastTransitionableElementsKind(InstanceType instance_type) {
     111    16334154 :   return instance_type == JS_ARRAY_TYPE || instance_type == JS_VALUE_TYPE ||
     112             :          instance_type == JS_ARGUMENTS_TYPE;
     113             : }
     114             : 
     115             : bool Map::CanHaveFastTransitionableElementsKind() const {
     116             :   return CanHaveFastTransitionableElementsKind(instance_type());
     117             : }
     118             : 
     119             : // static
     120    16262067 : void Map::GeneralizeIfCanHaveTransitionableFastElementsKind(
     121             :     Isolate* isolate, InstanceType instance_type, PropertyConstness* constness,
     122             :     Representation* representation, Handle<FieldType>* field_type) {
     123    16262067 :   if (CanHaveFastTransitionableElementsKind(instance_type)) {
     124             :     // We don't support propagation of field generalization through elements
     125             :     // kind transitions because they are inserted into the transition tree
     126             :     // before field transitions. In order to avoid complexity of handling
     127             :     // such a case we ensure that all maps with transitionable elements kinds
     128             :     // have the most general field type.
     129      128241 :     if (representation->IsHeapObject()) {
     130             :       // The field type is either already Any or should become Any if it was
     131             :       // something else.
     132      120135 :       *field_type = FieldType::Any(isolate);
     133             :     }
     134             :   }
     135    16262067 : }
     136             : 
     137   101721198 : bool Map::IsUnboxedDoubleField(FieldIndex index) const {
     138             :   if (!FLAG_unbox_double_fields) return false;
     139   203442397 :   if (index.is_hidden_field() || !index.is_inobject()) return false;
     140    38090096 :   return !layout_descriptor()->IsTagged(index.property_index());
     141             : }
     142             : 
     143    16261575 : bool Map::TooManyFastProperties(StoreOrigin store_origin) const {
     144    16261575 :   if (UnusedPropertyFields() != 0) return false;
     145     2947524 :   if (is_prototype_map()) return false;
     146     2497467 :   if (store_origin == StoreOrigin::kNamed) {
     147     2448057 :     int limit = Max(kMaxFastProperties, GetInObjectProperties());
     148     2448057 :     FieldCounts counts = GetFieldCounts();
     149             :     // Only count mutable fields so that objects with large numbers of
     150             :     // constant functions do not go to dictionary mode. That would be bad
     151             :     // because such objects have often been used as modules.
     152     2448057 :     int external = counts.mutable_count() - GetInObjectProperties();
     153     4896110 :     return external > limit || counts.GetTotal() > kMaxNumberOfDescriptors;
     154             :   } else {
     155       49410 :     int limit = Max(kFastPropertiesSoftLimit, GetInObjectProperties());
     156       49410 :     int external = NumberOfFields() - GetInObjectProperties();
     157       49410 :     return external > limit;
     158             :   }
     159             : }
     160             : 
     161    79138120 : PropertyDetails Map::GetLastDescriptorDetails() const {
     162    79138120 :   return instance_descriptors()->GetDetails(LastAdded());
     163             : }
     164             : 
     165   161599701 : int Map::LastAdded() const {
     166             :   int number_of_own_descriptors = NumberOfOwnDescriptors();
     167             :   DCHECK_GT(number_of_own_descriptors, 0);
     168   161599701 :   return number_of_own_descriptors - 1;
     169             : }
     170             : 
     171   123427067 : int Map::NumberOfOwnDescriptors() const {
     172   123427067 :   return NumberOfOwnDescriptorsBits::decode(bit_field3());
     173             : }
     174             : 
     175    79236386 : void Map::SetNumberOfOwnDescriptors(int number) {
     176             :   DCHECK_LE(number, instance_descriptors()->number_of_descriptors());
     177    79236386 :   CHECK_LE(static_cast<unsigned>(number),
     178             :            static_cast<unsigned>(kMaxNumberOfDescriptors));
     179    79236386 :   set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
     180    79236384 : }
     181             : 
     182             : int Map::EnumLength() const { return EnumLengthBits::decode(bit_field3()); }
     183             : 
     184       95606 : void Map::SetEnumLength(int length) {
     185       95606 :   if (length != kInvalidEnumCacheSentinel) {
     186             :     DCHECK_LE(length, NumberOfOwnDescriptors());
     187       61372 :     CHECK_LE(static_cast<unsigned>(length),
     188             :              static_cast<unsigned>(kMaxNumberOfDescriptors));
     189             :   }
     190       95606 :   set_bit_field3(EnumLengthBits::update(bit_field3(), length));
     191       95606 : }
     192             : 
     193    37820767 : FixedArrayBase Map::GetInitialElements() const {
     194             :   FixedArrayBase result;
     195    37820767 :   if (has_fast_elements() || has_fast_string_wrapper_elements()) {
     196    75626545 :     result = GetReadOnlyRoots().empty_fixed_array();
     197        7502 :   } else if (has_fast_sloppy_arguments_elements()) {
     198           0 :     result = GetReadOnlyRoots().empty_sloppy_arguments_elements();
     199        7502 :   } else if (has_fixed_typed_array_elements()) {
     200             :     result =
     201        8362 :         GetReadOnlyRoots().EmptyFixedTypedArrayForTypedArray(elements_kind());
     202        3321 :   } else if (has_dictionary_elements()) {
     203        6642 :     result = GetReadOnlyRoots().empty_slow_element_dictionary();
     204             :   } else {
     205           0 :     UNREACHABLE();
     206             :   }
     207             :   DCHECK(!ObjectInYoungGeneration(result));
     208    37820782 :   return result;
     209             : }
     210             : 
     211   864989661 : VisitorId Map::visitor_id() const {
     212             :   return static_cast<VisitorId>(
     213  1800209340 :       RELAXED_READ_BYTE_FIELD(*this, kVisitorIdOffset));
     214             : }
     215             : 
     216    50875415 : void Map::set_visitor_id(VisitorId id) {
     217    50875415 :   CHECK_LT(static_cast<unsigned>(id), 256);
     218   101747918 :   RELAXED_WRITE_BYTE_FIELD(*this, kVisitorIdOffset, static_cast<byte>(id));
     219    50875415 : }
     220             : 
     221     1070117 : int Map::instance_size_in_words() const {
     222  6261323148 :   return RELAXED_READ_BYTE_FIELD(*this, kInstanceSizeInWordsOffset);
     223             : }
     224             : 
     225        2912 : void Map::set_instance_size_in_words(int value) {
     226    28778223 :   RELAXED_WRITE_BYTE_FIELD(*this, kInstanceSizeInWordsOffset,
     227             :                            static_cast<byte>(value));
     228        2912 : }
     229             : 
     230    38782099 : int Map::instance_size() const {
     231  2740635146 :   return instance_size_in_words() << kTaggedSizeLog2;
     232             : }
     233             : 
     234    28778223 : void Map::set_instance_size(int value) {
     235    28778223 :   CHECK(IsAligned(value, kTaggedSize));
     236    28778223 :   value >>= kTaggedSizeLog2;
     237    28781135 :   CHECK_LT(static_cast<unsigned>(value), 256);
     238        2912 :   set_instance_size_in_words(value);
     239    28778223 : }
     240             : 
     241       11421 : int Map::inobject_properties_start_or_constructor_function_index() const {
     242  1028118417 :   return RELAXED_READ_BYTE_FIELD(
     243             :       *this, kInObjectPropertiesStartOrConstructorFunctionIndexOffset);
     244             : }
     245             : 
     246    28517870 : void Map::set_inobject_properties_start_or_constructor_function_index(
     247             :     int value) {
     248    28522294 :   CHECK_LT(static_cast<unsigned>(value), 256);
     249    57031316 :   RELAXED_WRITE_BYTE_FIELD(
     250             :       *this, kInObjectPropertiesStartOrConstructorFunctionIndexOffset,
     251             :       static_cast<byte>(value));
     252    28517870 : }
     253             : 
     254       11421 : int Map::GetInObjectPropertiesStartInWords() const {
     255             :   DCHECK(IsJSObjectMap());
     256       11421 :   return inobject_properties_start_or_constructor_function_index();
     257             : }
     258             : 
     259    28507336 : void Map::SetInObjectPropertiesStartInWords(int value) {
     260    28507336 :   CHECK(IsJSObjectMap());
     261    28507336 :   set_inobject_properties_start_or_constructor_function_index(value);
     262    28507346 : }
     263             : 
     264   327187937 : int Map::GetInObjectProperties() const {
     265             :   DCHECK(IsJSObjectMap());
     266   327187937 :   return instance_size_in_words() - GetInObjectPropertiesStartInWords();
     267             : }
     268             : 
     269             : int Map::GetConstructorFunctionIndex() const {
     270             :   DCHECK(IsPrimitiveMap());
     271             :   return inobject_properties_start_or_constructor_function_index();
     272             : }
     273             : 
     274        1512 : void Map::SetConstructorFunctionIndex(int value) {
     275        1512 :   CHECK(IsPrimitiveMap());
     276        1512 :   set_inobject_properties_start_or_constructor_function_index(value);
     277        1512 : }
     278             : 
     279       11421 : int Map::GetInObjectPropertyOffset(int index) const {
     280   149133048 :   return (GetInObjectPropertiesStartInWords() + index) * kTaggedSize;
     281             : }
     282             : 
     283             : Handle<Map> Map::AddMissingTransitionsForTesting(
     284             :     Isolate* isolate, Handle<Map> split_map,
     285             :     Handle<DescriptorArray> descriptors,
     286             :     Handle<LayoutDescriptor> full_layout_descriptor) {
     287             :   return AddMissingTransitions(isolate, split_map, descriptors,
     288          65 :                                full_layout_descriptor);
     289             : }
     290             : 
     291 11162844132 : InstanceType Map::instance_type() const {
     292             :   return static_cast<InstanceType>(
     293 21385426433 :       READ_UINT16_FIELD(*this, kInstanceTypeOffset));
     294             : }
     295             : 
     296        2912 : void Map::set_instance_type(InstanceType value) {
     297    28370564 :   WRITE_UINT16_FIELD(*this, kInstanceTypeOffset, value);
     298        2912 : }
     299             : 
     300   102590872 : int Map::UnusedPropertyFields() const {
     301             :   int value = used_or_unused_instance_size_in_words();
     302             :   DCHECK_IMPLIES(!IsJSObjectMap(), value == 0);
     303             :   int unused;
     304   102590872 :   if (value >= JSObject::kFieldsAdded) {
     305    55151821 :     unused = instance_size_in_words() - value;
     306             :   } else {
     307             :     // For out of object properties "used_or_unused_instance_size_in_words"
     308             :     // byte encodes the slack in the property array.
     309             :     unused = value;
     310             :   }
     311   102590872 :   return unused;
     312             : }
     313             : 
     314         351 : int Map::UnusedInObjectProperties() const {
     315             :   // Like Map::UnusedPropertyFields(), but returns 0 for out of object
     316             :   // properties.
     317             :   int value = used_or_unused_instance_size_in_words();
     318             :   DCHECK_IMPLIES(!IsJSObjectMap(), value == 0);
     319         351 :   if (value >= JSObject::kFieldsAdded) {
     320         306 :     return instance_size_in_words() - value;
     321             :   }
     322             :   return 0;
     323             : }
     324             : 
     325             : int Map::used_or_unused_instance_size_in_words() const {
     326   385951020 :   return RELAXED_READ_BYTE_FIELD(*this, kUsedOrUnusedInstanceSizeInWordsOffset);
     327             : }
     328             : 
     329    68030216 : void Map::set_used_or_unused_instance_size_in_words(int value) {
     330    68044497 :   CHECK_LE(static_cast<unsigned>(value), 255);
     331   136046151 :   RELAXED_WRITE_BYTE_FIELD(*this, kUsedOrUnusedInstanceSizeInWordsOffset,
     332             :                            static_cast<byte>(value));
     333    68030216 : }
     334             : 
     335    51886463 : int Map::UsedInstanceSize() const {
     336             :   int words = used_or_unused_instance_size_in_words();
     337    51886463 :   if (words < JSObject::kFieldsAdded) {
     338             :     // All in-object properties are used and the words is tracking the slack
     339             :     // in the property array.
     340     5555476 :     return instance_size();
     341             :   }
     342    46330987 :   return words * kTaggedSize;
     343             : }
     344             : 
     345    29313143 : void Map::SetInObjectUnusedPropertyFields(int value) {
     346             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     347    29313143 :   if (!IsJSObjectMap()) {
     348        9018 :     CHECK_EQ(0, value);
     349        9018 :     set_used_or_unused_instance_size_in_words(0);
     350             :     DCHECK_EQ(0, UnusedPropertyFields());
     351    29322165 :     return;
     352             :   }
     353    29304125 :   CHECK_LE(0, value);
     354             :   DCHECK_LE(value, GetInObjectProperties());
     355    29304125 :   int used_inobject_properties = GetInObjectProperties() - value;
     356             :   set_used_or_unused_instance_size_in_words(
     357    29304129 :       GetInObjectPropertyOffset(used_inobject_properties) / kTaggedSize);
     358             :   DCHECK_EQ(value, UnusedPropertyFields());
     359             : }
     360             : 
     361      219256 : void Map::SetOutOfObjectUnusedPropertyFields(int value) {
     362             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     363      219256 :   CHECK_LT(static_cast<unsigned>(value), JSObject::kFieldsAdded);
     364             :   // For out of object properties "used_instance_size_in_words" byte encodes
     365             :   // the slack in the property array.
     366      219256 :   set_used_or_unused_instance_size_in_words(value);
     367             :   DCHECK_EQ(value, UnusedPropertyFields());
     368      219256 : }
     369             : 
     370    22535417 : void Map::CopyUnusedPropertyFields(Map map) {
     371             :   set_used_or_unused_instance_size_in_words(
     372    22535417 :       map->used_or_unused_instance_size_in_words());
     373             :   DCHECK_EQ(UnusedPropertyFields(), map->UnusedPropertyFields());
     374    22535415 : }
     375             : 
     376         306 : void Map::CopyUnusedPropertyFieldsAdjustedForInstanceSize(Map map) {
     377             :   int value = map->used_or_unused_instance_size_in_words();
     378         306 :   if (value >= JSValue::kFieldsAdded) {
     379             :     // Unused in-object fields. Adjust the offset from the object’s start
     380             :     // so it matches the distance to the object’s end.
     381         261 :     value += instance_size_in_words() - map->instance_size_in_words();
     382             :   }
     383         306 :   set_used_or_unused_instance_size_in_words(value);
     384             :   DCHECK_EQ(UnusedPropertyFields(), map->UnusedPropertyFields());
     385         306 : }
     386             : 
     387    15962101 : void Map::AccountAddedPropertyField() {
     388             :   // Update used instance size and unused property fields number.
     389             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     390             : #ifdef DEBUG
     391             :   int new_unused = UnusedPropertyFields() - 1;
     392             :   if (new_unused < 0) new_unused += JSObject::kFieldsAdded;
     393             : #endif
     394             :   int value = used_or_unused_instance_size_in_words();
     395    15962101 :   if (value >= JSObject::kFieldsAdded) {
     396     8221031 :     if (value == instance_size_in_words()) {
     397      609211 :       AccountAddedOutOfObjectPropertyField(0);
     398             :     } else {
     399             :       // The property is added in-object, so simply increment the counter.
     400     7611820 :       set_used_or_unused_instance_size_in_words(value + 1);
     401             :     }
     402             :   } else {
     403     7741070 :     AccountAddedOutOfObjectPropertyField(value);
     404             :   }
     405             :   DCHECK_EQ(new_unused, UnusedPropertyFields());
     406    15962101 : }
     407             : 
     408     8350281 : void Map::AccountAddedOutOfObjectPropertyField(int unused_in_property_array) {
     409     8350281 :   unused_in_property_array--;
     410     8350281 :   if (unused_in_property_array < 0) {
     411     2928341 :     unused_in_property_array += JSObject::kFieldsAdded;
     412             :   }
     413     8350281 :   CHECK_LT(static_cast<unsigned>(unused_in_property_array),
     414             :            JSObject::kFieldsAdded);
     415     8350281 :   set_used_or_unused_instance_size_in_words(unused_in_property_array);
     416             :   DCHECK_EQ(unused_in_property_array, UnusedPropertyFields());
     417     8350281 : }
     418             : 
     419   351052314 : byte Map::bit_field() const { return READ_BYTE_FIELD(*this, kBitFieldOffset); }
     420             : 
     421        3024 : void Map::set_bit_field(byte value) {
     422    51985486 :   WRITE_BYTE_FIELD(*this, kBitFieldOffset, value);
     423        3024 : }
     424             : 
     425        3091 : byte Map::bit_field2() const {
     426   736233620 :   return READ_BYTE_FIELD(*this, kBitField2Offset);
     427             : }
     428             : 
     429        6003 : void Map::set_bit_field2(byte value) {
     430    84748245 :   WRITE_BYTE_FIELD(*this, kBitField2Offset, value);
     431        6003 : }
     432             : 
     433      440292 : bool Map::is_abandoned_prototype_map() const {
     434      440292 :   return is_prototype_map() && !owns_descriptors();
     435             : }
     436             : 
     437    28196174 : bool Map::should_be_fast_prototype_map() const {
     438    56392367 :   if (!prototype_info()->IsPrototypeInfo()) return false;
     439    24741933 :   return PrototypeInfo::cast(prototype_info())->should_be_fast_map();
     440             : }
     441             : 
     442    28699550 : void Map::set_elements_kind(ElementsKind elements_kind) {
     443    28702585 :   CHECK_LT(static_cast<int>(elements_kind), kElementsKindCount);
     444    28699550 :   set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind));
     445    28699550 : }
     446             : 
     447      465883 : ElementsKind Map::elements_kind() const {
     448      465883 :   return Map::ElementsKindBits::decode(bit_field2());
     449             : }
     450             : 
     451             : bool Map::has_fast_smi_elements() const {
     452             :   return IsSmiElementsKind(elements_kind());
     453             : }
     454             : 
     455             : bool Map::has_fast_object_elements() const {
     456             :   return IsObjectElementsKind(elements_kind());
     457             : }
     458             : 
     459             : bool Map::has_fast_smi_or_object_elements() const {
     460             :   return IsSmiOrObjectElementsKind(elements_kind());
     461             : }
     462             : 
     463             : bool Map::has_fast_double_elements() const {
     464             :   return IsDoubleElementsKind(elements_kind());
     465             : }
     466             : 
     467             : bool Map::has_fast_elements() const {
     468             :   return IsFastElementsKind(elements_kind());
     469             : }
     470             : 
     471             : bool Map::has_sloppy_arguments_elements() const {
     472             :   return IsSloppyArgumentsElementsKind(elements_kind());
     473             : }
     474             : 
     475             : bool Map::has_fast_sloppy_arguments_elements() const {
     476             :   return elements_kind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
     477             : }
     478             : 
     479             : bool Map::has_fast_string_wrapper_elements() const {
     480             :   return elements_kind() == FAST_STRING_WRAPPER_ELEMENTS;
     481             : }
     482             : 
     483             : bool Map::has_fixed_typed_array_elements() const {
     484             :   return IsFixedTypedArrayElementsKind(elements_kind());
     485             : }
     486             : 
     487             : bool Map::has_dictionary_elements() const {
     488             :   return IsDictionaryElementsKind(elements_kind());
     489             : }
     490             : 
     491      759580 : void Map::set_is_dictionary_map(bool value) {
     492             :   uint32_t new_bit_field3 = IsDictionaryMapBit::update(bit_field3(), value);
     493             :   new_bit_field3 = IsUnstableBit::update(new_bit_field3, value);
     494      759580 :   set_bit_field3(new_bit_field3);
     495      759580 : }
     496             : 
     497   412652630 : bool Map::is_dictionary_map() const {
     498   412652630 :   return IsDictionaryMapBit::decode(bit_field3());
     499             : }
     500             : 
     501    16901823 : void Map::mark_unstable() {
     502    16901823 :   set_bit_field3(IsUnstableBit::update(bit_field3(), true));
     503    16901824 : }
     504             : 
     505    89732296 : bool Map::is_stable() const { return !IsUnstableBit::decode(bit_field3()); }
     506             : 
     507    24793945 : bool Map::CanBeDeprecated() const {
     508    24793945 :   int descriptor = LastAdded();
     509    86264676 :   for (int i = 0; i <= descriptor; i++) {
     510    69328224 :     PropertyDetails details = instance_descriptors()->GetDetails(i);
     511    69328008 :     if (details.representation().IsNone()) return true;
     512    69328696 :     if (details.representation().IsSmi()) return true;
     513    66570949 :     if (details.representation().IsDouble()) return true;
     514    66570215 :     if (details.representation().IsHeapObject()) return true;
     515    74923126 :     if (details.kind() == kData && details.location() == kDescriptor) {
     516             :       return true;
     517             :     }
     518             :   }
     519             :   return false;
     520             : }
     521             : 
     522    32638526 : void Map::NotifyLeafMapLayoutChange(Isolate* isolate) {
     523    32638526 :   if (is_stable()) {
     524    16901543 :     mark_unstable();
     525             :     dependent_code()->DeoptimizeDependentCodeGroup(
     526    16901544 :         isolate, DependentCode::kPrototypeCheckGroup);
     527             :   }
     528    32638525 : }
     529             : 
     530    10808952 : bool Map::CanTransition() const {
     531             :   // Only JSObject and subtypes have map transitions and back pointers.
     532    10808952 :   return InstanceTypeChecker::IsJSObject(instance_type());
     533             : }
     534             : 
     535             : #define DEF_TESTER(Type, ...)                              \
     536             :   bool Map::Is##Type##Map() const {                        \
     537             :     return InstanceTypeChecker::Is##Type(instance_type()); \
     538             :   }
     539       28562 : INSTANCE_TYPE_CHECKERS(DEF_TESTER)
     540             : #undef DEF_TESTER
     541             : 
     542      258695 : bool Map::IsBooleanMap() const {
     543      517390 :   return *this == GetReadOnlyRoots().boolean_map();
     544             : }
     545             : 
     546         558 : bool Map::IsNullOrUndefinedMap() const {
     547        2223 :   return *this == GetReadOnlyRoots().null_map() ||
     548        1665 :          *this == GetReadOnlyRoots().undefined_map();
     549             : }
     550             : 
     551     5444934 : bool Map::IsPrimitiveMap() const {
     552     5444934 :   return instance_type() <= LAST_PRIMITIVE_TYPE;
     553             : }
     554             : 
     555   630984107 : Object Map::prototype() const { return READ_FIELD(*this, kPrototypeOffset); }
     556             : 
     557    57419013 : void Map::set_prototype(Object value, WriteBarrierMode mode) {
     558             :   DCHECK(value->IsNull() || value->IsJSReceiver());
     559        2912 :   WRITE_FIELD(*this, kPrototypeOffset, value);
     560   104597226 :   CONDITIONAL_WRITE_BARRIER(*this, kPrototypeOffset, value, mode);
     561    57419017 : }
     562             : 
     563             : LayoutDescriptor Map::layout_descriptor_gc_safe() const {
     564             :   DCHECK(FLAG_unbox_double_fields);
     565             :   // The loaded value can be dereferenced on background thread to load the
     566             :   // bitmap. We need acquire load in order to ensure that the bitmap
     567             :   // initializing stores are also visible to the background thread.
     568      187552 :   Object layout_desc = ACQUIRE_READ_FIELD(*this, kLayoutDescriptorOffset);
     569             :   return LayoutDescriptor::cast_gc_safe(layout_desc);
     570             : }
     571             : 
     572   129546409 : bool Map::HasFastPointerLayout() const {
     573             :   DCHECK(FLAG_unbox_double_fields);
     574             :   // The loaded value is used for SMI check only and is not dereferenced,
     575             :   // so relaxed load is safe.
     576   129546409 :   Object layout_desc = RELAXED_READ_FIELD(*this, kLayoutDescriptorOffset);
     577   129548602 :   return LayoutDescriptor::IsFastPointerLayout(layout_desc);
     578             : }
     579             : 
     580    28496929 : void Map::UpdateDescriptors(Isolate* isolate, DescriptorArray descriptors,
     581             :                             LayoutDescriptor layout_desc,
     582             :                             int number_of_own_descriptors) {
     583    28496929 :   SetInstanceDescriptors(isolate, descriptors, number_of_own_descriptors);
     584             :   if (FLAG_unbox_double_fields) {
     585    56993857 :     if (layout_descriptor()->IsSlowLayout()) {
     586        2806 :       set_layout_descriptor(layout_desc);
     587             :     }
     588             : #ifdef VERIFY_HEAP
     589             :     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
     590             :     if (FLAG_verify_heap) {
     591             :       CHECK(layout_descriptor()->IsConsistentWithMap(*this));
     592             :       CHECK_EQ(Map::GetVisitorId(*this), visitor_id());
     593             :     }
     594             : #else
     595             :     SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(*this));
     596             :     DCHECK(visitor_id() == Map::GetVisitorId(*this));
     597             : #endif
     598             :   }
     599    28496929 : }
     600             : 
     601    22318323 : void Map::InitializeDescriptors(Isolate* isolate, DescriptorArray descriptors,
     602             :                                 LayoutDescriptor layout_desc) {
     603             :   SetInstanceDescriptors(isolate, descriptors,
     604    22318323 :                          descriptors->number_of_descriptors());
     605             : 
     606             :   if (FLAG_unbox_double_fields) {
     607    22318324 :     set_layout_descriptor(layout_desc);
     608             : #ifdef VERIFY_HEAP
     609             :     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
     610             :     if (FLAG_verify_heap) {
     611             :       CHECK(layout_descriptor()->IsConsistentWithMap(*this));
     612             :     }
     613             : #else
     614             :     SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(*this));
     615             : #endif
     616    22318324 :     set_visitor_id(Map::GetVisitorId(*this));
     617             :   }
     618    22318322 : }
     619             : 
     620   218454419 : void Map::set_bit_field3(uint32_t bits) {
     621             :   if (kInt32Size != kTaggedSize) {
     622   218454419 :     RELAXED_WRITE_UINT32_FIELD(*this, kBitField3Offset + kInt32Size, 0);
     623             :   }
     624   218454419 :   RELAXED_WRITE_UINT32_FIELD(*this, kBitField3Offset, bits);
     625   218454419 : }
     626             : 
     627         280 : uint32_t Map::bit_field3() const {
     628  1803845048 :   return RELAXED_READ_UINT32_FIELD(*this, kBitField3Offset);
     629             : }
     630             : 
     631             : LayoutDescriptor Map::GetLayoutDescriptor() const {
     632             :   return FLAG_unbox_double_fields ? layout_descriptor()
     633    14045820 :                                   : LayoutDescriptor::FastPointerLayout();
     634             : }
     635             : 
     636       10328 : void Map::AppendDescriptor(Isolate* isolate, Descriptor* desc) {
     637       10328 :   DescriptorArray descriptors = instance_descriptors();
     638             :   int number_of_own_descriptors = NumberOfOwnDescriptors();
     639             :   DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
     640             :   {
     641             :     // The following two operations need to happen before the marking write
     642             :     // barrier.
     643       10328 :     descriptors->Append(desc);
     644       10328 :     SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
     645             :     MarkingBarrierForDescriptorArray(isolate->heap(), *this, descriptors,
     646       10328 :                                      number_of_own_descriptors + 1);
     647             :   }
     648             :   // Properly mark the map if the {desc} is an "interesting symbol".
     649       10328 :   if (desc->GetKey()->IsInterestingSymbol()) {
     650         111 :     set_may_have_interesting_symbols(true);
     651             :   }
     652             :   PropertyDetails details = desc->GetDetails();
     653       10328 :   if (details.location() == kField) {
     654             :     DCHECK_GT(UnusedPropertyFields(), 0);
     655        3219 :     AccountAddedPropertyField();
     656             :   }
     657             : 
     658             : // This function does not support appending double field descriptors and
     659             : // it should never try to (otherwise, layout descriptor must be updated too).
     660             : #ifdef DEBUG
     661             :   DCHECK(details.location() != kField || !details.representation().IsDouble());
     662             : #endif
     663       10328 : }
     664             : 
     665   120899259 : Object Map::GetBackPointer() const {
     666   120899259 :   Object object = constructor_or_backpointer();
     667   120899276 :   if (object->IsMap()) {
     668    75737342 :     return object;
     669             :   }
     670    90323870 :   return GetReadOnlyRoots().undefined_value();
     671             : }
     672             : 
     673     8137382 : Map Map::ElementsTransitionMap() {
     674             :   DisallowHeapAllocation no_gc;
     675             :   // TODO(delphick): While it's safe to pass nullptr for Isolate* here as
     676             :   // SearchSpecial doesn't need it, this is really ugly. Perhaps factor out a
     677             :   // base class for methods not requiring an Isolate?
     678             :   return TransitionsAccessor(nullptr, *this, &no_gc)
     679    16274772 :       .SearchSpecial(GetReadOnlyRoots().elements_transition_symbol());
     680             : }
     681             : 
     682             : Object Map::prototype_info() const {
     683             :   DCHECK(is_prototype_map());
     684    77180162 :   return READ_FIELD(*this, Map::kTransitionsOrPrototypeInfoOffset);
     685             : }
     686             : 
     687     6675022 : void Map::set_prototype_info(Object value, WriteBarrierMode mode) {
     688     6675022 :   CHECK(is_prototype_map());
     689     6675022 :   WRITE_FIELD(*this, Map::kTransitionsOrPrototypeInfoOffset, value);
     690    20025066 :   CONDITIONAL_WRITE_BARRIER(*this, Map::kTransitionsOrPrototypeInfoOffset,
     691             :                             value, mode);
     692     6675023 : }
     693             : 
     694     7258354 : void Map::SetBackPointer(Object value, WriteBarrierMode mode) {
     695     7258354 :   CHECK_GE(instance_type(), FIRST_JS_RECEIVER_TYPE);
     696     7258356 :   CHECK(value->IsMap());
     697    14516714 :   CHECK(GetBackPointer()->IsUndefined());
     698    21775068 :   CHECK_IMPLIES(value->IsMap(), Map::cast(value)->GetConstructor() ==
     699             :                                     constructor_or_backpointer());
     700     7258357 :   set_constructor_or_backpointer(value, mode);
     701     7258357 : }
     702             : 
     703   139039811 : ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
     704   166394480 : ACCESSORS(Map, prototype_validity_cell, Object, kPrototypeValidityCellOffset)
     705  1379464100 : ACCESSORS(Map, constructor_or_backpointer, Object,
     706             :           kConstructorOrBackPointerOffset)
     707             : 
     708     1339686 : bool Map::IsPrototypeValidityCellValid() const {
     709     1339686 :   Object validity_cell = prototype_validity_cell();
     710             :   Object value = validity_cell->IsSmi() ? Smi::cast(validity_cell)
     711     1339687 :                                         : Cell::cast(validity_cell)->value();
     712     1339688 :   return value == Smi::FromInt(Map::kPrototypeChainValid);
     713             : }
     714             : 
     715    81784113 : Object Map::GetConstructor() const {
     716    81784113 :   Object maybe_constructor = constructor_or_backpointer();
     717             :   // Follow any back pointers.
     718  1040303905 :   while (maybe_constructor->IsMap()) {
     719             :     maybe_constructor =
     720   876735669 :         Map::cast(maybe_constructor)->constructor_or_backpointer();
     721             :   }
     722    81784121 :   return maybe_constructor;
     723             : }
     724             : 
     725     2152181 : FunctionTemplateInfo Map::GetFunctionTemplateInfo() const {
     726     2152181 :   Object constructor = GetConstructor();
     727     2152181 :   if (constructor->IsJSFunction()) {
     728             :     DCHECK(JSFunction::cast(constructor)->shared()->IsApiFunction());
     729     2152181 :     return JSFunction::cast(constructor)->shared()->get_api_func_data();
     730             :   }
     731             :   DCHECK(constructor->IsFunctionTemplateInfo());
     732             :   return FunctionTemplateInfo::cast(constructor);
     733             : }
     734             : 
     735     9084637 : void Map::SetConstructor(Object constructor, WriteBarrierMode mode) {
     736             :   // Never overwrite a back pointer with a constructor.
     737    18169274 :   CHECK(!constructor_or_backpointer()->IsMap());
     738     9084637 :   set_constructor_or_backpointer(constructor, mode);
     739     9084637 : }
     740             : 
     741      415587 : Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map) {
     742             :   return CopyInitialMap(isolate, map, map->instance_size(),
     743             :                         map->GetInObjectProperties(),
     744     1246761 :                         map->UnusedPropertyFields());
     745             : }
     746             : 
     747             : bool Map::IsInobjectSlackTrackingInProgress() const {
     748    20755265 :   return construction_counter() != Map::kNoSlackTracking;
     749             : }
     750             : 
     751      240572 : void Map::InobjectSlackTrackingStep(Isolate* isolate) {
     752             :   // Slack tracking should only be performed on an initial map.
     753             :   DCHECK(GetBackPointer()->IsUndefined());
     754      481144 :   if (!IsInobjectSlackTrackingInProgress()) return;
     755             :   int counter = construction_counter();
     756      240572 :   set_construction_counter(counter - 1);
     757      240572 :   if (counter == kSlackTrackingCounterEnd) {
     758        2023 :     CompleteInobjectSlackTracking(isolate);
     759             :   }
     760             : }
     761             : 
     762     2350382 : int Map::SlackForArraySize(int old_size, int size_limit) {
     763     2350382 :   const int max_slack = size_limit - old_size;
     764     2350382 :   CHECK_LE(0, max_slack);
     765     2350382 :   if (old_size < 4) {
     766             :     DCHECK_LE(1, max_slack);
     767             :     return 1;
     768             :   }
     769     2489234 :   return Min(max_slack, old_size / 4);
     770             : }
     771             : 
     772             : int Map::InstanceSizeFromSlack(int slack) const {
     773      267961 :   return instance_size() - slack * kTaggedSize;
     774             : }
     775             : 
     776     1184722 : OBJECT_CONSTRUCTORS_IMPL(NormalizedMapCache, WeakFixedArray)
     777      592361 : CAST_ACCESSOR(NormalizedMapCache)
     778             : NEVER_READ_ONLY_SPACE_IMPL(NormalizedMapCache)
     779             : 
     780      752667 : int NormalizedMapCache::GetIndex(Handle<Map> map) {
     781      752667 :   return map->Hash() % NormalizedMapCache::kEntries;
     782             : }
     783             : 
     784             : bool HeapObject::IsNormalizedMapCache() const {
     785             :   if (!IsWeakFixedArray()) return false;
     786             :   if (WeakFixedArray::cast(*this)->length() != NormalizedMapCache::kEntries) {
     787             :     return false;
     788             :   }
     789             :   return true;
     790             : }
     791             : 
     792             : }  // namespace internal
     793             : }  // namespace v8
     794             : 
     795             : #include "src/objects/object-macros-undef.h"
     796             : 
     797             : #endif  // V8_OBJECTS_MAP_INL_H_

Generated by: LCOV version 1.10