LCOV - code coverage report
Current view: top level - src/objects - map-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 282 284 99.3 %
Date: 2019-03-21 Functions: 85 85 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       16632 : OBJECT_CONSTRUCTORS_IMPL(Map, HeapObject)
      31       16632 : CAST_ACCESSOR(Map)
      32             : 
      33      473488 : DescriptorArray Map::instance_descriptors() const {
      34   775061229 :   return DescriptorArray::cast(READ_FIELD(*this, kDescriptorsOffset));
      35             : }
      36             : 
      37             : DescriptorArray Map::synchronized_instance_descriptors() const {
      38    53682122 :   return DescriptorArray::cast(ACQUIRE_READ_FIELD(*this, kDescriptorsOffset));
      39             : }
      40             : 
      41    84392189 : void Map::set_synchronized_instance_descriptors(DescriptorArray value,
      42             :                                                 WriteBarrierMode mode) {
      43    84392189 :   RELEASE_WRITE_FIELD(*this, kDescriptorsOffset, value);
      44   168784420 :   CONDITIONAL_WRITE_BARRIER(*this, kDescriptorsOffset, value, mode);
      45    84392107 : }
      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           0 : SYNCHRONIZED_ACCESSORS_CHECKED(Map, layout_descriptor, LayoutDescriptor,
      52             :                                kLayoutDescriptorOffset,
      53             :                                FLAG_unbox_double_fields)
      54   295720721 : WEAK_ACCESSORS(Map, raw_transitions, kTransitionsOrPrototypeInfoOffset)
      55             : 
      56             : // |bit_field| fields.
      57             : // Concurrent access to |has_prototype_slot| and |has_non_instance_prototype|
      58             : // is explicitly whitelisted here. The former is never modified after the map
      59             : // is setup but it's being read by concurrent marker when pointer compression
      60             : // is enabled. The latter bit can be modified on a live objects.
      61      792036 : BIT_FIELD_ACCESSORS(Map, relaxed_bit_field, has_non_instance_prototype,
      62             :                     Map::HasNonInstancePrototypeBit)
      63      263128 : BIT_FIELD_ACCESSORS(Map, bit_field, is_callable, Map::IsCallableBit)
      64        1096 : BIT_FIELD_ACCESSORS(Map, bit_field, has_named_interceptor,
      65             :                     Map::HasNamedInterceptorBit)
      66         217 : BIT_FIELD_ACCESSORS(Map, bit_field, has_indexed_interceptor,
      67             :                     Map::HasIndexedInterceptorBit)
      68         261 : BIT_FIELD_ACCESSORS(Map, bit_field, is_undetectable, Map::IsUndetectableBit)
      69      181719 : BIT_FIELD_ACCESSORS(Map, bit_field, is_access_check_needed,
      70             :                     Map::IsAccessCheckNeededBit)
      71        3083 : BIT_FIELD_ACCESSORS(Map, bit_field, is_constructor, Map::IsConstructorBit)
      72        4995 : BIT_FIELD_ACCESSORS(Map, relaxed_bit_field, has_prototype_slot,
      73             :                     Map::HasPrototypeSlotBit)
      74             : 
      75             : // |bit_field2| fields.
      76      137075 : BIT_FIELD_ACCESSORS(Map, bit_field2, is_extensible, Map::IsExtensibleBit)
      77     4510401 : BIT_FIELD_ACCESSORS(Map, bit_field2, is_prototype_map, Map::IsPrototypeMapBit)
      78       45629 : BIT_FIELD_ACCESSORS(Map, bit_field2, is_in_retained_map_list,
      79             :                     Map::IsInRetainedMapListBit)
      80             : 
      81             : // |bit_field3| fields.
      82    20740574 : BIT_FIELD_ACCESSORS(Map, bit_field3, owns_descriptors, Map::OwnsDescriptorsBit)
      83    62650604 : BIT_FIELD_ACCESSORS(Map, bit_field3, has_hidden_prototype,
      84             :                     Map::HasHiddenPrototypeBit)
      85       71614 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
      86      501768 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_migration_target,
      87             :                     Map::IsMigrationTargetBit)
      88         270 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_immutable_proto,
      89             :                     Map::IsImmutablePrototypeBit)
      90    62892002 : BIT_FIELD_ACCESSORS(Map, bit_field3, new_target_is_base,
      91             :                     Map::NewTargetIsBaseBit)
      92     3680966 : BIT_FIELD_ACCESSORS(Map, bit_field3, may_have_interesting_symbols,
      93             :                     Map::MayHaveInterestingSymbolsBit)
      94     2191922 : BIT_FIELD_ACCESSORS(Map, bit_field3, construction_counter,
      95             :                     Map::ConstructionCounterBits)
      96             : 
      97     1626139 : InterceptorInfo Map::GetNamedInterceptor() {
      98             :   DCHECK(has_named_interceptor());
      99     1626139 :   FunctionTemplateInfo info = GetFunctionTemplateInfo();
     100     1626139 :   return InterceptorInfo::cast(info->GetNamedPropertyHandler());
     101             : }
     102             : 
     103      668416 : InterceptorInfo Map::GetIndexedInterceptor() {
     104             :   DCHECK(has_indexed_interceptor());
     105      668416 :   FunctionTemplateInfo info = GetFunctionTemplateInfo();
     106      668416 :   return InterceptorInfo::cast(info->GetIndexedPropertyHandler());
     107             : }
     108             : 
     109             : bool Map::IsMostGeneralFieldType(Representation representation,
     110             :                                  FieldType field_type) {
     111         637 :   return !representation.IsHeapObject() || field_type->IsAny();
     112             : }
     113             : 
     114             : bool Map::CanHaveFastTransitionableElementsKind(InstanceType instance_type) {
     115    17245341 :   return instance_type == JS_ARRAY_TYPE || instance_type == JS_VALUE_TYPE ||
     116             :          instance_type == JS_ARGUMENTS_TYPE;
     117             : }
     118             : 
     119             : bool Map::CanHaveFastTransitionableElementsKind() const {
     120             :   return CanHaveFastTransitionableElementsKind(instance_type());
     121             : }
     122             : 
     123             : // static
     124    17175971 : void Map::GeneralizeIfCanHaveTransitionableFastElementsKind(
     125             :     Isolate* isolate, InstanceType instance_type, PropertyConstness* constness,
     126             :     Representation* representation, Handle<FieldType>* field_type) {
     127    17175971 :   if (CanHaveFastTransitionableElementsKind(instance_type)) {
     128             :     // We don't support propagation of field generalization through elements
     129             :     // kind transitions because they are inserted into the transition tree
     130             :     // before field transitions. In order to avoid complexity of handling
     131             :     // such a case we ensure that all maps with transitionable elements kinds
     132             :     // have the most general field type.
     133      128461 :     if (representation->IsHeapObject()) {
     134             :       // The field type is either already Any or should become Any if it was
     135             :       // something else.
     136      106857 :       *field_type = FieldType::Any(isolate);
     137             :     }
     138             :   }
     139    17175972 : }
     140             : 
     141             : bool Map::IsUnboxedDoubleField(FieldIndex index) const {
     142             :   if (!FLAG_unbox_double_fields) return false;
     143             :   if (index.is_hidden_field() || !index.is_inobject()) return false;
     144             :   return !layout_descriptor()->IsTagged(index.property_index());
     145             : }
     146             : 
     147    18080042 : bool Map::TooManyFastProperties(StoreOrigin store_origin) const {
     148    18080042 :   if (UnusedPropertyFields() != 0) return false;
     149     3160552 :   if (is_prototype_map()) return false;
     150     2616577 :   if (store_origin == StoreOrigin::kNamed) {
     151     2567062 :     int limit = Max(kMaxFastProperties, GetInObjectProperties());
     152     2567061 :     FieldCounts counts = GetFieldCounts();
     153             :     // Only count mutable fields so that objects with large numbers of
     154             :     // constant functions do not go to dictionary mode. That would be bad
     155             :     // because such objects have often been used as modules.
     156     2567063 :     int external = counts.mutable_count() - GetInObjectProperties();
     157     5134124 :     return external > limit || counts.GetTotal() > kMaxNumberOfDescriptors;
     158             :   } else {
     159       49515 :     int limit = Max(kFastPropertiesSoftLimit, GetInObjectProperties());
     160       49515 :     int external = NumberOfFields() - GetInObjectProperties();
     161       49515 :     return external > limit;
     162             :   }
     163             : }
     164             : 
     165    80371224 : PropertyDetails Map::GetLastDescriptorDetails() const {
     166    80371224 :   return instance_descriptors()->GetDetails(LastAdded());
     167             : }
     168             : 
     169             : int Map::LastAdded() const {
     170             :   int number_of_own_descriptors = NumberOfOwnDescriptors();
     171             :   DCHECK_GT(number_of_own_descriptors, 0);
     172   163449451 :   return number_of_own_descriptors - 1;
     173             : }
     174             : 
     175     2107659 : int Map::NumberOfOwnDescriptors() const {
     176     2107659 :   return NumberOfOwnDescriptorsBits::decode(bit_field3());
     177             : }
     178             : 
     179    84402455 : void Map::SetNumberOfOwnDescriptors(int number) {
     180             :   DCHECK_LE(number, instance_descriptors()->number_of_descriptors());
     181    84402455 :   CHECK_LE(static_cast<unsigned>(number),
     182             :            static_cast<unsigned>(kMaxNumberOfDescriptors));
     183             :   set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
     184    84402455 : }
     185             : 
     186             : int Map::EnumLength() const { return EnumLengthBits::decode(bit_field3()); }
     187             : 
     188       95537 : void Map::SetEnumLength(int length) {
     189       95537 :   if (length != kInvalidEnumCacheSentinel) {
     190             :     DCHECK_LE(length, NumberOfOwnDescriptors());
     191       61897 :     CHECK_LE(static_cast<unsigned>(length),
     192             :              static_cast<unsigned>(kMaxNumberOfDescriptors));
     193             :   }
     194             :   set_bit_field3(EnumLengthBits::update(bit_field3(), length));
     195       95537 : }
     196             : 
     197    39512908 : FixedArrayBase Map::GetInitialElements() const {
     198             :   FixedArrayBase result;
     199    39512908 :   if (has_fast_elements() || has_fast_string_wrapper_elements()) {
     200             :     result = GetReadOnlyRoots().empty_fixed_array();
     201        7540 :   } else if (has_fast_sloppy_arguments_elements()) {
     202             :     result = GetReadOnlyRoots().empty_sloppy_arguments_elements();
     203        7540 :   } else if (has_fixed_typed_array_elements()) {
     204             :     result =
     205             :         GetReadOnlyRoots().EmptyFixedTypedArrayForTypedArray(elements_kind());
     206        3321 :   } else if (has_dictionary_elements()) {
     207             :     result = GetReadOnlyRoots().empty_slow_element_dictionary();
     208             :   } else {
     209           0 :     UNREACHABLE();
     210             :   }
     211             :   DCHECK(!ObjectInYoungGeneration(result));
     212    39512908 :   return result;
     213             : }
     214             : 
     215             : VisitorId Map::visitor_id() const {
     216             :   return static_cast<VisitorId>(
     217  1648127383 :       RELAXED_READ_BYTE_FIELD(*this, kVisitorIdOffset));
     218             : }
     219             : 
     220    31289350 : void Map::set_visitor_id(VisitorId id) {
     221    31289350 :   CHECK_LT(static_cast<unsigned>(id), 256);
     222    31289350 :   RELAXED_WRITE_BYTE_FIELD(*this, kVisitorIdOffset, static_cast<byte>(id));
     223    31289350 : }
     224             : 
     225     2632956 : int Map::instance_size_in_words() const {
     226  6067742009 :   return RELAXED_READ_BYTE_FIELD(*this, kInstanceSizeInWordsOffset);
     227             : }
     228             : 
     229        2912 : void Map::set_instance_size_in_words(int value) {
     230    31544746 :   RELAXED_WRITE_BYTE_FIELD(*this, kInstanceSizeInWordsOffset,
     231             :                            static_cast<byte>(value));
     232        2912 : }
     233             : 
     234     5166203 : int Map::instance_size() const {
     235  2587924500 :   return instance_size_in_words() << kTaggedSizeLog2;
     236             : }
     237             : 
     238    31544746 : void Map::set_instance_size(int value) {
     239    31544746 :   CHECK(IsAligned(value, kTaggedSize));
     240    31544746 :   value >>= kTaggedSizeLog2;
     241    63089492 :   CHECK_LT(static_cast<unsigned>(value), 256);
     242        2912 :   set_instance_size_in_words(value);
     243    31544746 : }
     244             : 
     245       24736 : int Map::inobject_properties_start_or_constructor_function_index() const {
     246  1429382932 :   return RELAXED_READ_BYTE_FIELD(
     247             :       *this, kInObjectPropertiesStartOrConstructorFunctionIndexOffset);
     248             : }
     249             : 
     250    31290708 : void Map::set_inobject_properties_start_or_constructor_function_index(
     251             :     int value) {
     252    62581416 :   CHECK_LT(static_cast<unsigned>(value), 256);
     253    31290708 :   RELAXED_WRITE_BYTE_FIELD(
     254             :       *this, kInObjectPropertiesStartOrConstructorFunctionIndexOffset,
     255             :       static_cast<byte>(value));
     256    31290708 : }
     257             : 
     258       24736 : int Map::GetInObjectPropertiesStartInWords() const {
     259             :   DCHECK(IsJSObjectMap());
     260       24736 :   return inobject_properties_start_or_constructor_function_index();
     261             : }
     262             : 
     263    31280554 : void Map::SetInObjectPropertiesStartInWords(int value) {
     264    31280554 :   CHECK(IsJSObjectMap());
     265    31280554 :   set_inobject_properties_start_or_constructor_function_index(value);
     266    31280578 : }
     267             : 
     268   370172340 : int Map::GetInObjectProperties() const {
     269             :   DCHECK(IsJSObjectMap());
     270   370172340 :   return instance_size_in_words() - GetInObjectPropertiesStartInWords();
     271             : }
     272             : 
     273             : int Map::GetConstructorFunctionIndex() const {
     274             :   DCHECK(IsPrimitiveMap());
     275             :   return inobject_properties_start_or_constructor_function_index();
     276             : }
     277             : 
     278        1344 : void Map::SetConstructorFunctionIndex(int value) {
     279        1344 :   CHECK(IsPrimitiveMap());
     280        1344 :   set_inobject_properties_start_or_constructor_function_index(value);
     281        1344 : }
     282             : 
     283       24736 : int Map::GetInObjectPropertyOffset(int index) const {
     284   305929372 :   return (GetInObjectPropertiesStartInWords() + index) * kTaggedSize;
     285             : }
     286             : 
     287             : Handle<Map> Map::AddMissingTransitionsForTesting(
     288             :     Isolate* isolate, Handle<Map> split_map,
     289             :     Handle<DescriptorArray> descriptors,
     290             :     Handle<LayoutDescriptor> full_layout_descriptor) {
     291             :   return AddMissingTransitions(isolate, split_map, descriptors,
     292             :                                full_layout_descriptor);
     293             : }
     294             : 
     295     5137717 : InstanceType Map::instance_type() const {
     296             :   return static_cast<InstanceType>(
     297 21777657643 :       READ_UINT16_FIELD(*this, kInstanceTypeOffset));
     298             : }
     299             : 
     300        2912 : void Map::set_instance_type(InstanceType value) {
     301    31141715 :   WRITE_UINT16_FIELD(*this, kInstanceTypeOffset, value);
     302        2912 : }
     303             : 
     304   107491812 : int Map::UnusedPropertyFields() const {
     305             :   int value = used_or_unused_instance_size_in_words();
     306             :   DCHECK_IMPLIES(!IsJSObjectMap(), value == 0);
     307             :   int unused;
     308   107491812 :   if (value >= JSObject::kFieldsAdded) {
     309    56842270 :     unused = instance_size_in_words() - value;
     310             :   } else {
     311             :     // For out of object properties "used_or_unused_instance_size_in_words"
     312             :     // byte encodes the slack in the property array.
     313             :     unused = value;
     314             :   }
     315   107491812 :   return unused;
     316             : }
     317             : 
     318         360 : int Map::UnusedInObjectProperties() const {
     319             :   // Like Map::UnusedPropertyFields(), but returns 0 for out of object
     320             :   // properties.
     321             :   int value = used_or_unused_instance_size_in_words();
     322             :   DCHECK_IMPLIES(!IsJSObjectMap(), value == 0);
     323         360 :   if (value >= JSObject::kFieldsAdded) {
     324         315 :     return instance_size_in_words() - value;
     325             :   }
     326             :   return 0;
     327             : }
     328             : 
     329             : int Map::used_or_unused_instance_size_in_words() const {
     330   391786018 :   return RELAXED_READ_BYTE_FIELD(*this, kUsedOrUnusedInstanceSizeInWordsOffset);
     331             : }
     332             : 
     333    73699385 : void Map::set_used_or_unused_instance_size_in_words(int value) {
     334   147398770 :   CHECK_LE(static_cast<unsigned>(value), 255);
     335    73699385 :   RELAXED_WRITE_BYTE_FIELD(*this, kUsedOrUnusedInstanceSizeInWordsOffset,
     336             :                            static_cast<byte>(value));
     337    73699385 : }
     338             : 
     339    47012551 : int Map::UsedInstanceSize() const {
     340             :   int words = used_or_unused_instance_size_in_words();
     341    47012551 :   if (words < JSObject::kFieldsAdded) {
     342             :     // All in-object properties are used and the words is tracking the slack
     343             :     // in the property array.
     344     5123731 :     return instance_size();
     345             :   }
     346    41888820 :   return words * kTaggedSize;
     347             : }
     348             : 
     349    32090867 : void Map::SetInObjectUnusedPropertyFields(int value) {
     350             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     351    32090867 :   if (!IsJSObjectMap()) {
     352        8794 :     CHECK_EQ(0, value);
     353        8794 :     set_used_or_unused_instance_size_in_words(0);
     354             :     DCHECK_EQ(0, UnusedPropertyFields());
     355        8794 :     return;
     356             :   }
     357    32082073 :   CHECK_LE(0, value);
     358             :   DCHECK_LE(value, GetInObjectProperties());
     359    32082073 :   int used_inobject_properties = GetInObjectProperties() - value;
     360       24736 :   set_used_or_unused_instance_size_in_words(
     361    32106814 :       GetInObjectPropertyOffset(used_inobject_properties) / kTaggedSize);
     362             :   DCHECK_EQ(value, UnusedPropertyFields());
     363             : }
     364             : 
     365      220282 : void Map::SetOutOfObjectUnusedPropertyFields(int value) {
     366             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     367      440564 :   CHECK_LT(static_cast<unsigned>(value), JSObject::kFieldsAdded);
     368             :   // For out of object properties "used_instance_size_in_words" byte encodes
     369             :   // the slack in the property array.
     370      220282 :   set_used_or_unused_instance_size_in_words(value);
     371             :   DCHECK_EQ(value, UnusedPropertyFields());
     372      220282 : }
     373             : 
     374    24521399 : void Map::CopyUnusedPropertyFields(Map map) {
     375             :   set_used_or_unused_instance_size_in_words(
     376    24521399 :       map->used_or_unused_instance_size_in_words());
     377             :   DCHECK_EQ(UnusedPropertyFields(), map->UnusedPropertyFields());
     378    24521403 : }
     379             : 
     380         315 : void Map::CopyUnusedPropertyFieldsAdjustedForInstanceSize(Map map) {
     381             :   int value = map->used_or_unused_instance_size_in_words();
     382         315 :   if (value >= JSValue::kFieldsAdded) {
     383             :     // Unused in-object fields. Adjust the offset from the object’s start
     384             :     // so it matches the distance to the object’s end.
     385         270 :     value += instance_size_in_words() - map->instance_size_in_words();
     386             :   }
     387         315 :   set_used_or_unused_instance_size_in_words(value);
     388             :   DCHECK_EQ(UnusedPropertyFields(), map->UnusedPropertyFields());
     389         315 : }
     390             : 
     391    16866572 : void Map::AccountAddedPropertyField() {
     392             :   // Update used instance size and unused property fields number.
     393             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     394             : #ifdef DEBUG
     395             :   int new_unused = UnusedPropertyFields() - 1;
     396             :   if (new_unused < 0) new_unused += JSObject::kFieldsAdded;
     397             : #endif
     398             :   int value = used_or_unused_instance_size_in_words();
     399    16866572 :   if (value >= JSObject::kFieldsAdded) {
     400     8953236 :     if (value == instance_size_in_words()) {
     401      794985 :       AccountAddedOutOfObjectPropertyField(0);
     402             :     } else {
     403             :       // The property is added in-object, so simply increment the counter.
     404     8158251 :       set_used_or_unused_instance_size_in_words(value + 1);
     405             :     }
     406             :   } else {
     407     7913336 :     AccountAddedOutOfObjectPropertyField(value);
     408             :   }
     409             :   DCHECK_EQ(new_unused, UnusedPropertyFields());
     410    16866579 : }
     411             : 
     412     8708319 : void Map::AccountAddedOutOfObjectPropertyField(int unused_in_property_array) {
     413     8708319 :   unused_in_property_array--;
     414     8708319 :   if (unused_in_property_array < 0) {
     415     3139761 :     unused_in_property_array += JSObject::kFieldsAdded;
     416             :   }
     417    17416638 :   CHECK_LT(static_cast<unsigned>(unused_in_property_array),
     418             :            JSObject::kFieldsAdded);
     419     8708319 :   set_used_or_unused_instance_size_in_words(unused_in_property_array);
     420             :   DCHECK_EQ(unused_in_property_array, UnusedPropertyFields());
     421     8708321 : }
     422             : 
     423   294253624 : byte Map::bit_field() const { return READ_BYTE_FIELD(*this, kBitFieldOffset); }
     424             : 
     425        3024 : void Map::set_bit_field(byte value) {
     426    56491024 :   WRITE_BYTE_FIELD(*this, kBitFieldOffset, value);
     427        3024 : }
     428             : 
     429             : byte Map::relaxed_bit_field() const {
     430   135960754 :   return RELAXED_READ_BYTE_FIELD(*this, kBitFieldOffset);
     431             : }
     432             : 
     433             : void Map::set_relaxed_bit_field(byte value) {
     434      265677 :   RELAXED_WRITE_BYTE_FIELD(*this, kBitFieldOffset, value);
     435             : }
     436             : 
     437        3091 : byte Map::bit_field2() const {
     438   760924928 :   return READ_BYTE_FIELD(*this, kBitField2Offset);
     439             : }
     440             : 
     441        6003 : void Map::set_bit_field2(byte value) {
     442    92464317 :   WRITE_BYTE_FIELD(*this, kBitField2Offset, value);
     443        6003 : }
     444             : 
     445      442815 : bool Map::is_abandoned_prototype_map() const {
     446      464145 :   return is_prototype_map() && !owns_descriptors();
     447             : }
     448             : 
     449    31827246 : bool Map::should_be_fast_prototype_map() const {
     450    31827229 :   if (!prototype_info()->IsPrototypeInfo()) return false;
     451             :   return PrototypeInfo::cast(prototype_info())->should_be_fast_map();
     452             : }
     453             : 
     454    31468648 : void Map::set_elements_kind(ElementsKind elements_kind) {
     455    31471683 :   CHECK_LT(static_cast<int>(elements_kind), kElementsKindCount);
     456    31468648 :   set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind));
     457    31468648 : }
     458             : 
     459             : ElementsKind Map::elements_kind() const {
     460             :   return Map::ElementsKindBits::decode(bit_field2());
     461             : }
     462             : 
     463             : bool Map::has_fast_smi_elements() const {
     464             :   return IsSmiElementsKind(elements_kind());
     465             : }
     466             : 
     467             : bool Map::has_fast_object_elements() const {
     468             :   return IsObjectElementsKind(elements_kind());
     469             : }
     470             : 
     471             : bool Map::has_fast_smi_or_object_elements() const {
     472             :   return IsSmiOrObjectElementsKind(elements_kind());
     473             : }
     474             : 
     475             : bool Map::has_fast_double_elements() const {
     476             :   return IsDoubleElementsKind(elements_kind());
     477             : }
     478             : 
     479             : bool Map::has_fast_elements() const {
     480             :   return IsFastElementsKind(elements_kind());
     481             : }
     482             : 
     483             : bool Map::has_sloppy_arguments_elements() const {
     484             :   return IsSloppyArgumentsElementsKind(elements_kind());
     485             : }
     486             : 
     487             : bool Map::has_fast_sloppy_arguments_elements() const {
     488             :   return elements_kind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
     489             : }
     490             : 
     491             : bool Map::has_fast_string_wrapper_elements() const {
     492             :   return elements_kind() == FAST_STRING_WRAPPER_ELEMENTS;
     493             : }
     494             : 
     495             : bool Map::has_fixed_typed_array_elements() const {
     496             :   return IsFixedTypedArrayElementsKind(elements_kind());
     497             : }
     498             : 
     499             : bool Map::has_dictionary_elements() const {
     500             :   return IsDictionaryElementsKind(elements_kind());
     501             : }
     502             : 
     503      766379 : void Map::set_is_dictionary_map(bool value) {
     504             :   uint32_t new_bit_field3 = IsDictionaryMapBit::update(bit_field3(), value);
     505             :   new_bit_field3 = IsUnstableBit::update(new_bit_field3, value);
     506             :   set_bit_field3(new_bit_field3);
     507      766379 : }
     508             : 
     509             : bool Map::is_dictionary_map() const {
     510             :   return IsDictionaryMapBit::decode(bit_field3());
     511             : }
     512             : 
     513    18618303 : void Map::mark_unstable() {
     514         224 :   set_bit_field3(IsUnstableBit::update(bit_field3(), true));
     515    18618303 : }
     516             : 
     517      529163 : bool Map::is_stable() const { return !IsUnstableBit::decode(bit_field3()); }
     518             : 
     519    25177498 : bool Map::CanBeDeprecated() const {
     520             :   int descriptor = LastAdded();
     521   149921334 :   for (int i = 0; i <= descriptor; i++) {
     522    70362230 :     PropertyDetails details = instance_descriptors()->GetDetails(i);
     523    70362224 :     if (details.representation().IsNone()) return true;
     524    70362925 :     if (details.representation().IsSmi()) return true;
     525    67550379 :     if (details.representation().IsDouble()) return true;
     526    67549635 :     if (details.representation().IsHeapObject()) return true;
     527    75987583 :     if (details.kind() == kData && details.location() == kDescriptor) {
     528             :       return true;
     529             :     }
     530             :   }
     531             :   return false;
     532             : }
     533             : 
     534    34630141 : void Map::NotifyLeafMapLayoutChange(Isolate* isolate) {
     535    34630141 :   if (is_stable()) {
     536    18618083 :     mark_unstable();
     537    37236141 :     dependent_code()->DeoptimizeDependentCodeGroup(
     538    18618080 :         isolate, DependentCode::kPrototypeCheckGroup);
     539             :   }
     540    34630119 : }
     541             : 
     542             : bool Map::CanTransition() const {
     543             :   // Only JSObject and subtypes have map transitions and back pointers.
     544             :   return InstanceTypeChecker::IsJSObject(instance_type());
     545             : }
     546             : 
     547             : #define DEF_TESTER(Type, ...)                              \
     548             :   bool Map::Is##Type##Map() const {                        \
     549             :     return InstanceTypeChecker::Is##Type(instance_type()); \
     550             :   }
     551       55192 : INSTANCE_TYPE_CHECKERS(DEF_TESTER)
     552             : #undef DEF_TESTER
     553             : 
     554             : bool Map::IsBooleanMap() const {
     555             :   return *this == GetReadOnlyRoots().boolean_map();
     556             : }
     557             : 
     558             : bool Map::IsNullOrUndefinedMap() const {
     559        1125 :   return *this == GetReadOnlyRoots().null_map() ||
     560             :          *this == GetReadOnlyRoots().undefined_map();
     561             : }
     562             : 
     563        1344 : bool Map::IsPrimitiveMap() const {
     564        1344 :   return instance_type() <= LAST_PRIMITIVE_TYPE;
     565             : }
     566             : 
     567   401366135 : Object Map::prototype() const { return READ_FIELD(*this, kPrototypeOffset); }
     568             : 
     569    31237858 : void Map::set_prototype(Object value, WriteBarrierMode mode) {
     570             :   DCHECK(value->IsNull() || value->IsJSReceiver());
     571    62376228 :   WRITE_FIELD(*this, kPrototypeOffset, value);
     572    56960455 :   CONDITIONAL_WRITE_BARRIER(*this, kPrototypeOffset, value, mode);
     573    31237839 : }
     574             : 
     575             : LayoutDescriptor Map::layout_descriptor_gc_safe() const {
     576             :   DCHECK(FLAG_unbox_double_fields);
     577             :   // The loaded value can be dereferenced on background thread to load the
     578             :   // bitmap. We need acquire load in order to ensure that the bitmap
     579             :   // initializing stores are also visible to the background thread.
     580             :   Object layout_desc = ACQUIRE_READ_FIELD(*this, kLayoutDescriptorOffset);
     581             :   return LayoutDescriptor::cast_gc_safe(layout_desc);
     582             : }
     583             : 
     584             : bool Map::HasFastPointerLayout() const {
     585             :   DCHECK(FLAG_unbox_double_fields);
     586             :   // The loaded value is used for SMI check only and is not dereferenced,
     587             :   // so relaxed load is safe.
     588             :   Object layout_desc = RELAXED_READ_FIELD(*this, kLayoutDescriptorOffset);
     589             :   return LayoutDescriptor::IsFastPointerLayout(layout_desc);
     590             : }
     591             : 
     592             : void Map::UpdateDescriptors(Isolate* isolate, DescriptorArray descriptors,
     593             :                             LayoutDescriptor layout_desc,
     594             :                             int number_of_own_descriptors) {
     595    28907038 :   SetInstanceDescriptors(isolate, descriptors, number_of_own_descriptors);
     596             :   if (FLAG_unbox_double_fields) {
     597             :     if (layout_descriptor()->IsSlowLayout()) {
     598             :       set_layout_descriptor(layout_desc);
     599             :     }
     600             : #ifdef VERIFY_HEAP
     601             :     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
     602             :     if (FLAG_verify_heap) {
     603             :       CHECK(layout_descriptor()->IsConsistentWithMap(*this));
     604             :       CHECK_EQ(Map::GetVisitorId(*this), visitor_id());
     605             :     }
     606             : #else
     607             :     SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(*this));
     608             :     DCHECK(visitor_id() == Map::GetVisitorId(*this));
     609             : #endif
     610             :   }
     611             : }
     612             : 
     613    24310368 : void Map::InitializeDescriptors(Isolate* isolate, DescriptorArray descriptors,
     614             :                                 LayoutDescriptor layout_desc) {
     615    24310368 :   SetInstanceDescriptors(isolate, descriptors,
     616    24310368 :                          descriptors->number_of_descriptors());
     617             : 
     618             :   if (FLAG_unbox_double_fields) {
     619             :     set_layout_descriptor(layout_desc);
     620             : #ifdef VERIFY_HEAP
     621             :     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
     622             :     if (FLAG_verify_heap) {
     623             :       CHECK(layout_descriptor()->IsConsistentWithMap(*this));
     624             :     }
     625             : #else
     626             :     SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(*this));
     627             : #endif
     628             :     set_visitor_id(Map::GetVisitorId(*this));
     629             :   }
     630    24310336 : }
     631             : 
     632        3136 : void Map::set_bit_field3(uint32_t bits) {
     633   236550098 :   RELAXED_WRITE_UINT32_FIELD(*this, kBitField3Offset, bits);
     634        3136 : }
     635             : 
     636         224 : uint32_t Map::bit_field3() const {
     637  1797056520 :   return RELAXED_READ_UINT32_FIELD(*this, kBitField3Offset);
     638             : }
     639             : 
     640             : void Map::clear_padding() {
     641             :   if (FIELD_SIZE(kOptionalPaddingOffset) == 0) return;
     642             :   DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
     643             :   memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
     644             :          FIELD_SIZE(kOptionalPaddingOffset));
     645             : }
     646             : 
     647             : LayoutDescriptor Map::GetLayoutDescriptor() const {
     648             :   return FLAG_unbox_double_fields ? layout_descriptor()
     649             :                                   : LayoutDescriptor::FastPointerLayout();
     650             : }
     651             : 
     652       10328 : void Map::AppendDescriptor(Isolate* isolate, Descriptor* desc) {
     653       10328 :   DescriptorArray descriptors = instance_descriptors();
     654             :   int number_of_own_descriptors = NumberOfOwnDescriptors();
     655             :   DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
     656             :   {
     657             :     // The following two operations need to happen before the marking write
     658             :     // barrier.
     659       10328 :     descriptors->Append(desc);
     660       10328 :     SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
     661             :     MarkingBarrierForDescriptorArray(isolate->heap(), *this, descriptors,
     662             :                                      number_of_own_descriptors + 1);
     663             :   }
     664             :   // Properly mark the map if the {desc} is an "interesting symbol".
     665       10328 :   if (desc->GetKey()->IsInterestingSymbol()) {
     666         111 :     set_may_have_interesting_symbols(true);
     667             :   }
     668             :   PropertyDetails details = desc->GetDetails();
     669       10328 :   if (details.location() == kField) {
     670             :     DCHECK_GT(UnusedPropertyFields(), 0);
     671        3219 :     AccountAddedPropertyField();
     672             :   }
     673             : 
     674             : // This function does not support appending double field descriptors and
     675             : // it should never try to (otherwise, layout descriptor must be updated too).
     676             : #ifdef DEBUG
     677             :   DCHECK(details.location() != kField || !details.representation().IsDouble());
     678             : #endif
     679       10328 : }
     680             : 
     681   127051545 : Object Map::GetBackPointer() const {
     682             :   Object object = constructor_or_backpointer();
     683   127051564 :   if (object->IsMap()) {
     684    76447456 :     return object;
     685             :   }
     686    50604108 :   return GetReadOnlyRoots().undefined_value();
     687             : }
     688             : 
     689     8264899 : Map Map::ElementsTransitionMap() {
     690             :   DisallowHeapAllocation no_gc;
     691             :   // TODO(delphick): While it's safe to pass nullptr for Isolate* here as
     692             :   // SearchSpecial doesn't need it, this is really ugly. Perhaps factor out a
     693             :   // base class for methods not requiring an Isolate?
     694             :   return TransitionsAccessor(nullptr, *this, &no_gc)
     695     8264915 :       .SearchSpecial(GetReadOnlyRoots().elements_transition_symbol());
     696             : }
     697             : 
     698             : Object Map::prototype_info() const {
     699             :   DCHECK(is_prototype_map());
     700    89710424 :   return READ_FIELD(*this, Map::kTransitionsOrPrototypeInfoOffset);
     701             : }
     702             : 
     703     9340827 : void Map::set_prototype_info(Object value, WriteBarrierMode mode) {
     704     9340827 :   CHECK(is_prototype_map());
     705     9340827 :   WRITE_FIELD(*this, Map::kTransitionsOrPrototypeInfoOffset, value);
     706    18681658 :   CONDITIONAL_WRITE_BARRIER(*this, Map::kTransitionsOrPrototypeInfoOffset,
     707             :                             value, mode);
     708     9340833 : }
     709             : 
     710     7344098 : void Map::SetBackPointer(Object value, WriteBarrierMode mode) {
     711     7344098 :   CHECK_GE(instance_type(), FIRST_JS_RECEIVER_TYPE);
     712     7344098 :   CHECK(value->IsMap());
     713    14688202 :   CHECK(GetBackPointer()->IsUndefined());
     714    22032307 :   CHECK_IMPLIES(value->IsMap(), Map::cast(value)->GetConstructor() ==
     715             :                                     constructor_or_backpointer());
     716     7344103 :   set_constructor_or_backpointer(value, mode);
     717     7344105 : }
     718             : 
     719    50927201 : ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
     720   182209644 : ACCESSORS(Map, prototype_validity_cell, Object, kPrototypeValidityCellOffset)
     721  1356930218 : ACCESSORS(Map, constructor_or_backpointer, Object,
     722             :           kConstructorOrBackPointerOffset)
     723             : 
     724     1418185 : bool Map::IsPrototypeValidityCellValid() const {
     725             :   Object validity_cell = prototype_validity_cell();
     726             :   Object value = validity_cell->IsSmi() ? Smi::cast(validity_cell)
     727     1418185 :                                         : Cell::cast(validity_cell)->value();
     728     1418185 :   return value == Smi::FromInt(Map::kPrototypeChainValid);
     729             : }
     730             : 
     731    86413611 : Object Map::GetConstructor() const {
     732             :   Object maybe_constructor = constructor_or_backpointer();
     733             :   // Follow any back pointers.
     734  1855824255 :   while (maybe_constructor->IsMap()) {
     735             :     maybe_constructor =
     736             :         Map::cast(maybe_constructor)->constructor_or_backpointer();
     737             :   }
     738    86413559 :   return maybe_constructor;
     739             : }
     740             : 
     741     2294555 : FunctionTemplateInfo Map::GetFunctionTemplateInfo() const {
     742     2294555 :   Object constructor = GetConstructor();
     743     2294555 :   if (constructor->IsJSFunction()) {
     744             :     DCHECK(JSFunction::cast(constructor)->shared()->IsApiFunction());
     745             :     return JSFunction::cast(constructor)->shared()->get_api_func_data();
     746             :   }
     747             :   DCHECK(constructor->IsFunctionTemplateInfo());
     748             :   return FunctionTemplateInfo::cast(constructor);
     749             : }
     750             : 
     751     9444996 : void Map::SetConstructor(Object constructor, WriteBarrierMode mode) {
     752             :   // Never overwrite a back pointer with a constructor.
     753     9444996 :   CHECK(!constructor_or_backpointer()->IsMap());
     754     9444996 :   set_constructor_or_backpointer(constructor, mode);
     755     9445001 : }
     756             : 
     757      418264 : Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map) {
     758             :   return CopyInitialMap(isolate, map, map->instance_size(),
     759             :                         map->GetInObjectProperties(),
     760     1254792 :                         map->UnusedPropertyFields());
     761             : }
     762             : 
     763             : bool Map::IsInobjectSlackTrackingInProgress() const {
     764        6415 :   return construction_counter() != Map::kNoSlackTracking;
     765             : }
     766             : 
     767      230087 : void Map::InobjectSlackTrackingStep(Isolate* isolate) {
     768             :   // Slack tracking should only be performed on an initial map.
     769             :   DCHECK(GetBackPointer()->IsUndefined());
     770      230087 :   if (!IsInobjectSlackTrackingInProgress()) return;
     771             :   int counter = construction_counter();
     772      230087 :   set_construction_counter(counter - 1);
     773      230087 :   if (counter == kSlackTrackingCounterEnd) {
     774         288 :     CompleteInobjectSlackTracking(isolate);
     775             :   }
     776             : }
     777             : 
     778     2381246 : int Map::SlackForArraySize(int old_size, int size_limit) {
     779     2381246 :   const int max_slack = size_limit - old_size;
     780     2381246 :   CHECK_LE(0, max_slack);
     781     2381246 :   if (old_size < 4) {
     782             :     DCHECK_LE(1, max_slack);
     783             :     return 1;
     784             :   }
     785     2527030 :   return Min(max_slack, old_size / 4);
     786             : }
     787             : 
     788             : int Map::InstanceSizeFromSlack(int slack) const {
     789      261858 :   return instance_size() - slack * kTaggedSize;
     790             : }
     791             : 
     792             : OBJECT_CONSTRUCTORS_IMPL(NormalizedMapCache, WeakFixedArray)
     793             : CAST_ACCESSOR(NormalizedMapCache)
     794             : NEVER_READ_ONLY_SPACE_IMPL(NormalizedMapCache)
     795             : 
     796             : int NormalizedMapCache::GetIndex(Handle<Map> map) {
     797      756903 :   return map->Hash() % NormalizedMapCache::kEntries;
     798             : }
     799             : 
     800             : bool HeapObject::IsNormalizedMapCache() const {
     801             :   if (!IsWeakFixedArray()) return false;
     802             :   if (WeakFixedArray::cast(*this)->length() != NormalizedMapCache::kEntries) {
     803             :     return false;
     804             :   }
     805             :   return true;
     806             : }
     807             : 
     808             : }  // namespace internal
     809             : }  // namespace v8
     810             : 
     811             : #include "src/objects/object-macros-undef.h"
     812             : 
     813             : #endif  // V8_OBJECTS_MAP_INL_H_

Generated by: LCOV version 1.10