LCOV - code coverage report
Current view: top level - src/objects - map-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 269 270 99.6 %
Date: 2019-04-19 Functions: 67 67 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             : OBJECT_CONSTRUCTORS_IMPL(Map, HeapObject)
      31             : CAST_ACCESSOR(Map)
      32             : 
      33      473390 : DescriptorArray Map::instance_descriptors() const {
      34   759815317 :   return DescriptorArray::cast(READ_FIELD(*this, kDescriptorsOffset));
      35             : }
      36             : 
      37             : DescriptorArray Map::synchronized_instance_descriptors() const {
      38    26434850 :   return DescriptorArray::cast(ACQUIRE_READ_FIELD(*this, kDescriptorsOffset));
      39             : }
      40             : 
      41    84462963 : void Map::set_synchronized_instance_descriptors(DescriptorArray value,
      42             :                                                 WriteBarrierMode mode) {
      43    84462963 :   RELEASE_WRITE_FIELD(*this, kDescriptorsOffset, value);
      44   168926007 :   CONDITIONAL_WRITE_BARRIER(*this, kDescriptorsOffset, value, mode);
      45    84462934 : }
      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   344048483 : SYNCHRONIZED_ACCESSORS_CHECKED(Map, layout_descriptor, LayoutDescriptor,
      52             :                                kLayoutDescriptorOffset,
      53             :                                FLAG_unbox_double_fields)
      54   294975169 : 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      799746 : BIT_FIELD_ACCESSORS(Map, relaxed_bit_field, has_non_instance_prototype,
      62             :                     Map::HasNonInstancePrototypeBit)
      63      262948 : 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      184303 : 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      138194 : BIT_FIELD_ACCESSORS(Map, bit_field2, is_extensible, Map::IsExtensibleBit)
      77     4617224 : BIT_FIELD_ACCESSORS(Map, bit_field2, is_prototype_map, Map::IsPrototypeMapBit)
      78       46713 : BIT_FIELD_ACCESSORS(Map, bit_field2, is_in_retained_map_list,
      79             :                     Map::IsInRetainedMapListBit)
      80             : 
      81             : // |bit_field3| fields.
      82    20820064 : BIT_FIELD_ACCESSORS(Map, bit_field3, owns_descriptors, Map::OwnsDescriptorsBit)
      83    63462404 : BIT_FIELD_ACCESSORS(Map, bit_field3, has_hidden_prototype,
      84             :                     Map::HasHiddenPrototypeBit)
      85       46702 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
      86      504658 : 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    62482814 : BIT_FIELD_ACCESSORS(Map, bit_field3, new_target_is_base,
      91             :                     Map::NewTargetIsBaseBit)
      92     3695944 : BIT_FIELD_ACCESSORS(Map, bit_field3, may_have_interesting_symbols,
      93             :                     Map::MayHaveInterestingSymbolsBit)
      94     2174564 : BIT_FIELD_ACCESSORS(Map, bit_field3, construction_counter,
      95             :                     Map::ConstructionCounterBits)
      96             : 
      97     1602577 : InterceptorInfo Map::GetNamedInterceptor() {
      98             :   DCHECK(has_named_interceptor());
      99     1602577 :   FunctionTemplateInfo info = GetFunctionTemplateInfo();
     100     1602577 :   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         650 :   return !representation.IsHeapObject() || field_type->IsAny();
     112             : }
     113             : 
     114             : bool Map::CanHaveFastTransitionableElementsKind(InstanceType instance_type) {
     115    17391678 :   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    17320266 : void Map::GeneralizeIfCanHaveTransitionableFastElementsKind(
     125             :     Isolate* isolate, InstanceType instance_type, PropertyConstness* constness,
     126             :     Representation* representation, Handle<FieldType>* field_type) {
     127    17320266 :   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      129698 :     if (representation->IsHeapObject()) {
     134             :       // The field type is either already Any or should become Any if it was
     135             :       // something else.
     136      108055 :       *field_type = FieldType::Any(isolate);
     137             :     }
     138             :   }
     139    17320266 : }
     140             : 
     141   102928977 : bool Map::IsUnboxedDoubleField(FieldIndex index) const {
     142             :   if (!FLAG_unbox_double_fields) return false;
     143   205857964 :   if (index.is_hidden_field() || !index.is_inobject()) return false;
     144    22623789 :   return !layout_descriptor()->IsTagged(index.property_index());
     145             : }
     146             : 
     147    18268943 : bool Map::TooManyFastProperties(StoreOrigin store_origin) const {
     148    18268943 :   if (UnusedPropertyFields() != 0) return false;
     149     3154924 :   if (is_prototype_map()) return false;
     150     2605159 :   if (store_origin == StoreOrigin::kNamed) {
     151     2558155 :     int limit = Max(kMaxFastProperties, GetInObjectProperties());
     152     2558154 :     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     2558154 :     int external = counts.mutable_count() - GetInObjectProperties();
     157     5116304 :     return external > limit || counts.GetTotal() > kMaxNumberOfDescriptors;
     158             :   } else {
     159       47004 :     int limit = Max(kFastPropertiesSoftLimit, GetInObjectProperties());
     160       47004 :     int external = NumberOfFields() - GetInObjectProperties();
     161       47004 :     return external > limit;
     162             :   }
     163             : }
     164             : 
     165    80540617 : PropertyDetails Map::GetLastDescriptorDetails() const {
     166    80540617 :   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   163581982 :   return number_of_own_descriptors - 1;
     173             : }
     174             : 
     175     1695753 : int Map::NumberOfOwnDescriptors() const {
     176     1695753 :   return NumberOfOwnDescriptorsBits::decode(bit_field3());
     177             : }
     178             : 
     179    84473330 : void Map::SetNumberOfOwnDescriptors(int number) {
     180             :   DCHECK_LE(number, instance_descriptors()->number_of_descriptors());
     181    84473330 :   CHECK_LE(static_cast<unsigned>(number),
     182             :            static_cast<unsigned>(kMaxNumberOfDescriptors));
     183             :   set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
     184    84473330 : }
     185             : 
     186             : int Map::EnumLength() const { return EnumLengthBits::decode(bit_field3()); }
     187             : 
     188       89636 : void Map::SetEnumLength(int length) {
     189       89636 :   if (length != kInvalidEnumCacheSentinel) {
     190             :     DCHECK_LE(length, NumberOfOwnDescriptors());
     191       61688 :     CHECK_LE(static_cast<unsigned>(length),
     192             :              static_cast<unsigned>(kMaxNumberOfDescriptors));
     193             :   }
     194             :   set_bit_field3(EnumLengthBits::update(bit_field3(), length));
     195       89636 : }
     196             : 
     197    38587446 : FixedArrayBase Map::GetInitialElements() const {
     198             :   FixedArrayBase result;
     199    38587446 :   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    38587446 :   return result;
     213             : }
     214             : 
     215             : VisitorId Map::visitor_id() const {
     216             :   return static_cast<VisitorId>(
     217  1671706369 :       RELAXED_READ_BYTE_FIELD(*this, kVisitorIdOffset));
     218             : }
     219             : 
     220    55718630 : void Map::set_visitor_id(VisitorId id) {
     221    55718630 :   CHECK_LT(static_cast<unsigned>(id), 256);
     222    55718630 :   RELAXED_WRITE_BYTE_FIELD(*this, kVisitorIdOffset, static_cast<byte>(id));
     223    55718630 : }
     224             : 
     225             : int Map::instance_size_in_words() const {
     226  5791585595 :   return RELAXED_READ_BYTE_FIELD(*this, kInstanceSizeInWordsOffset);
     227             : }
     228             : 
     229             : void Map::set_instance_size_in_words(int value) {
     230    31356815 :   RELAXED_WRITE_BYTE_FIELD(*this, kInstanceSizeInWordsOffset,
     231             :                            static_cast<byte>(value));
     232             : }
     233             : 
     234     4865567 : int Map::instance_size() const {
     235  2476104313 :   return instance_size_in_words() << kTaggedSizeLog2;
     236             : }
     237             : 
     238    31356815 : void Map::set_instance_size(int value) {
     239    31356815 :   CHECK(IsAligned(value, kTaggedSize));
     240    31356815 :   value >>= kTaggedSizeLog2;
     241    62713630 :   CHECK_LT(static_cast<unsigned>(value), 256);
     242             :   set_instance_size_in_words(value);
     243    31356815 : }
     244             : 
     245             : int Map::inobject_properties_start_or_constructor_function_index() const {
     246  1092033920 :   return RELAXED_READ_BYTE_FIELD(
     247             :       *this, kInObjectPropertiesStartOrConstructorFunctionIndexOffset);
     248             : }
     249             : 
     250    31090018 : void Map::set_inobject_properties_start_or_constructor_function_index(
     251             :     int value) {
     252    62180036 :   CHECK_LT(static_cast<unsigned>(value), 256);
     253    31090018 :   RELAXED_WRITE_BYTE_FIELD(
     254             :       *this, kInObjectPropertiesStartOrConstructorFunctionIndexOffset,
     255             :       static_cast<byte>(value));
     256    31090018 : }
     257             : 
     258             : int Map::GetInObjectPropertiesStartInWords() const {
     259             :   DCHECK(IsJSObjectMap());
     260             :   return inobject_properties_start_or_constructor_function_index();
     261             : }
     262             : 
     263    31079873 : void Map::SetInObjectPropertiesStartInWords(int value) {
     264    31079873 :   CHECK(IsJSObjectMap());
     265    31079873 :   set_inobject_properties_start_or_constructor_function_index(value);
     266    31079885 : }
     267             : 
     268   342165795 : int Map::GetInObjectProperties() const {
     269             :   DCHECK(IsJSObjectMap());
     270   342165795 :   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        1288 : void Map::SetConstructorFunctionIndex(int value) {
     279        1288 :   CHECK(IsPrimitiveMap());
     280        1288 :   set_inobject_properties_start_or_constructor_function_index(value);
     281        1288 : }
     282             : 
     283             : int Map::GetInObjectPropertyOffset(int index) const {
     284   165473133 :   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          65 :                                full_layout_descriptor);
     293             : }
     294             : 
     295     4540783 : InstanceType Map::instance_type() const {
     296             :   return static_cast<InstanceType>(
     297 22469706304 :       READ_UINT16_FIELD(*this, kInstanceTypeOffset));
     298             : }
     299             : 
     300             : void Map::set_instance_type(InstanceType value) {
     301    30938924 :   WRITE_UINT16_FIELD(*this, kInstanceTypeOffset, value);
     302             : }
     303             : 
     304   106308213 : int Map::UnusedPropertyFields() const {
     305             :   int value = used_or_unused_instance_size_in_words();
     306             :   DCHECK_IMPLIES(!IsJSObjectMap(), value == 0);
     307             :   int unused;
     308   106308213 :   if (value >= JSObject::kFieldsAdded) {
     309    58902754 :     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   106308213 :   return unused;
     316             : }
     317             : 
     318         369 : 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         369 :   if (value >= JSObject::kFieldsAdded) {
     324         324 :     return instance_size_in_words() - value;
     325             :   }
     326             :   return 0;
     327             : }
     328             : 
     329             : int Map::used_or_unused_instance_size_in_words() const {
     330   389514936 :   return RELAXED_READ_BYTE_FIELD(*this, kUsedOrUnusedInstanceSizeInWordsOffset);
     331             : }
     332             : 
     333    73933977 : void Map::set_used_or_unused_instance_size_in_words(int value) {
     334   147867954 :   CHECK_LE(static_cast<unsigned>(value), 255);
     335    73933977 :   RELAXED_WRITE_BYTE_FIELD(*this, kUsedOrUnusedInstanceSizeInWordsOffset,
     336             :                            static_cast<byte>(value));
     337    73933977 : }
     338             : 
     339    46620686 : int Map::UsedInstanceSize() const {
     340             :   int words = used_or_unused_instance_size_in_words();
     341    46620686 :   if (words < JSObject::kFieldsAdded) {
     342             :     // All in-object properties are used and the words is tracking the slack
     343             :     // in the property array.
     344     5083006 :     return instance_size();
     345             :   }
     346    41537680 :   return words * kTaggedSize;
     347             : }
     348             : 
     349    31884734 : void Map::SetInObjectUnusedPropertyFields(int value) {
     350             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     351    31884734 :   if (!IsJSObjectMap()) {
     352        8850 :     CHECK_EQ(0, value);
     353        8850 :     set_used_or_unused_instance_size_in_words(0);
     354             :     DCHECK_EQ(0, UnusedPropertyFields());
     355        8850 :     return;
     356             :   }
     357    31875884 :   CHECK_LE(0, value);
     358             :   DCHECK_LE(value, GetInObjectProperties());
     359    31875884 :   int used_inobject_properties = GetInObjectProperties() - value;
     360             :   set_used_or_unused_instance_size_in_words(
     361    31875882 :       GetInObjectPropertyOffset(used_inobject_properties) / kTaggedSize);
     362             :   DCHECK_EQ(value, UnusedPropertyFields());
     363             : }
     364             : 
     365      221099 : void Map::SetOutOfObjectUnusedPropertyFields(int value) {
     366             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     367      442198 :   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      221099 :   set_used_or_unused_instance_size_in_words(value);
     371             :   DCHECK_EQ(value, UnusedPropertyFields());
     372      221099 : }
     373             : 
     374    24806801 : void Map::CopyUnusedPropertyFields(Map map) {
     375             :   set_used_or_unused_instance_size_in_words(
     376    24806801 :       map->used_or_unused_instance_size_in_words());
     377             :   DCHECK_EQ(UnusedPropertyFields(), map->UnusedPropertyFields());
     378    24806804 : }
     379             : 
     380         324 : void Map::CopyUnusedPropertyFieldsAdjustedForInstanceSize(Map map) {
     381             :   int value = map->used_or_unused_instance_size_in_words();
     382         324 :   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         279 :     value += instance_size_in_words() - map->instance_size_in_words();
     386             :   }
     387         324 :   set_used_or_unused_instance_size_in_words(value);
     388             :   DCHECK_EQ(UnusedPropertyFields(), map->UnusedPropertyFields());
     389         324 : }
     390             : 
     391    17021075 : 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    17021075 :   if (value >= JSObject::kFieldsAdded) {
     400     9107573 :     if (value == instance_size_in_words()) {
     401      784634 :       AccountAddedOutOfObjectPropertyField(0);
     402             :     } else {
     403             :       // The property is added in-object, so simply increment the counter.
     404     8322939 :       set_used_or_unused_instance_size_in_words(value + 1);
     405             :     }
     406             :   } else {
     407     7913502 :     AccountAddedOutOfObjectPropertyField(value);
     408             :   }
     409             :   DCHECK_EQ(new_unused, UnusedPropertyFields());
     410    17021074 : }
     411             : 
     412     8698137 : void Map::AccountAddedOutOfObjectPropertyField(int unused_in_property_array) {
     413     8698137 :   unused_in_property_array--;
     414     8698137 :   if (unused_in_property_array < 0) {
     415     3134413 :     unused_in_property_array += JSObject::kFieldsAdded;
     416             :   }
     417    17396274 :   CHECK_LT(static_cast<unsigned>(unused_in_property_array),
     418             :            JSObject::kFieldsAdded);
     419     8698137 :   set_used_or_unused_instance_size_in_words(unused_in_property_array);
     420             :   DCHECK_EQ(unused_in_property_array, UnusedPropertyFields());
     421     8698136 : }
     422             : 
     423   294750397 : byte Map::bit_field() const { return READ_BYTE_FIELD(*this, kBitFieldOffset); }
     424             : 
     425             : void Map::set_bit_field(byte value) {
     426    56580272 :   WRITE_BYTE_FIELD(*this, kBitFieldOffset, value);
     427             : }
     428             : 
     429             : byte Map::relaxed_bit_field() const {
     430    58921012 :   return RELAXED_READ_BYTE_FIELD(*this, kBitFieldOffset);
     431             : }
     432             : 
     433             : void Map::set_relaxed_bit_field(byte value) {
     434      268247 :   RELAXED_WRITE_BYTE_FIELD(*this, kBitFieldOffset, value);
     435             : }
     436             : 
     437             : byte Map::bit_field2() const {
     438   730445019 :   return READ_BYTE_FIELD(*this, kBitField2Offset);
     439             : }
     440             : 
     441             : void Map::set_bit_field2(byte value) {
     442    92442338 :   WRITE_BYTE_FIELD(*this, kBitField2Offset, value);
     443             : }
     444             : 
     445      443094 : bool Map::is_abandoned_prototype_map() const {
     446      464524 :   return is_prototype_map() && !owns_descriptors();
     447             : }
     448             : 
     449    32170655 : bool Map::should_be_fast_prototype_map() const {
     450    32170643 :   if (!prototype_info()->IsPrototypeInfo()) return false;
     451             :   return PrototypeInfo::cast(prototype_info())->should_be_fast_map();
     452             : }
     453             : 
     454    31250979 : void Map::set_elements_kind(ElementsKind elements_kind) {
     455    31250979 :   CHECK_LT(static_cast<int>(elements_kind), kElementsKindCount);
     456    31250979 :   set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind));
     457    31250979 : }
     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             : bool Map::has_frozen_or_sealed_elements() const {
     504             :   return IsPackedFrozenOrSealedElementsKind(elements_kind());
     505             : }
     506             : 
     507             : bool Map::has_sealed_elements() const {
     508             :   return IsSealedElementsKind(elements_kind());
     509             : }
     510             : 
     511             : bool Map::has_frozen_elements() const {
     512             :   return IsFrozenElementsKind(elements_kind());
     513             : }
     514             : 
     515      773438 : void Map::set_is_dictionary_map(bool value) {
     516             :   uint32_t new_bit_field3 = IsDictionaryMapBit::update(bit_field3(), value);
     517             :   new_bit_field3 = IsUnstableBit::update(new_bit_field3, value);
     518             :   set_bit_field3(new_bit_field3);
     519      773438 : }
     520             : 
     521             : bool Map::is_dictionary_map() const {
     522             :   return IsDictionaryMapBit::decode(bit_field3());
     523             : }
     524             : 
     525    18802984 : void Map::mark_unstable() {
     526             :   set_bit_field3(IsUnstableBit::update(bit_field3(), true));
     527    18802984 : }
     528             : 
     529      549909 : bool Map::is_stable() const { return !IsUnstableBit::decode(bit_field3()); }
     530             : 
     531    25213831 : bool Map::CanBeDeprecated() const {
     532             :   int descriptor = LastAdded();
     533   150104603 :   for (int i = 0; i <= descriptor; i++) {
     534    70448119 :     PropertyDetails details = instance_descriptors()->GetDetails(i);
     535    70448068 :     if (details.representation().IsNone()) return true;
     536    70448756 :     if (details.representation().IsSmi()) return true;
     537    67632279 :     if (details.representation().IsDouble()) return true;
     538    67631543 :     if (details.representation().IsHeapObject()) return true;
     539    76068053 :     if (details.kind() == kData && details.location() == kDescriptor) {
     540             :       return true;
     541             :     }
     542             :   }
     543             :   return false;
     544             : }
     545             : 
     546    34894764 : void Map::NotifyLeafMapLayoutChange(Isolate* isolate) {
     547    34894764 :   if (is_stable()) {
     548    18802759 :     mark_unstable();
     549    37605523 :     dependent_code()->DeoptimizeDependentCodeGroup(
     550    18802761 :         isolate, DependentCode::kPrototypeCheckGroup);
     551             :   }
     552    34894767 : }
     553             : 
     554             : bool Map::CanTransition() const {
     555             :   // Only JSObject and subtypes have map transitions and back pointers.
     556             :   return InstanceTypeChecker::IsJSObject(instance_type());
     557             : }
     558             : 
     559             : #define DEF_TESTER(Type, ...)                              \
     560             :   bool Map::Is##Type##Map() const {                        \
     561             :     return InstanceTypeChecker::Is##Type(instance_type()); \
     562             :   }
     563             : INSTANCE_TYPE_CHECKERS(DEF_TESTER)
     564             : #undef DEF_TESTER
     565             : 
     566             : bool Map::IsBooleanMap() const {
     567             :   return *this == GetReadOnlyRoots().boolean_map();
     568             : }
     569             : 
     570             : bool Map::IsNullOrUndefinedMap() const {
     571        1143 :   return *this == GetReadOnlyRoots().null_map() ||
     572             :          *this == GetReadOnlyRoots().undefined_map();
     573             : }
     574             : 
     575             : bool Map::IsPrimitiveMap() const {
     576             :   return instance_type() <= LAST_PRIMITIVE_TYPE;
     577             : }
     578             : 
     579             : HeapObject Map::prototype() const {
     580   402372021 :   return HeapObject::cast(READ_FIELD(*this, kPrototypeOffset));
     581             : }
     582             : 
     583    31642519 : void Map::set_prototype(HeapObject value, WriteBarrierMode mode) {
     584             :   DCHECK(value->IsNull() || value->IsJSReceiver());
     585    62578042 :   WRITE_FIELD(*this, kPrototypeOffset, value);
     586    57771501 :   CONDITIONAL_WRITE_BARRIER(*this, kPrototypeOffset, value, mode);
     587    31642502 : }
     588             : 
     589             : LayoutDescriptor Map::layout_descriptor_gc_safe() const {
     590             :   DCHECK(FLAG_unbox_double_fields);
     591             :   // The loaded value can be dereferenced on background thread to load the
     592             :   // bitmap. We need acquire load in order to ensure that the bitmap
     593             :   // initializing stores are also visible to the background thread.
     594      179040 :   Object layout_desc = ACQUIRE_READ_FIELD(*this, kLayoutDescriptorOffset);
     595             :   return LayoutDescriptor::cast_gc_safe(layout_desc);
     596             : }
     597             : 
     598             : bool Map::HasFastPointerLayout() const {
     599             :   DCHECK(FLAG_unbox_double_fields);
     600             :   // The loaded value is used for SMI check only and is not dereferenced,
     601             :   // so relaxed load is safe.
     602   127833038 :   Object layout_desc = RELAXED_READ_FIELD(*this, kLayoutDescriptorOffset);
     603             :   return LayoutDescriptor::IsFastPointerLayout(layout_desc);
     604             : }
     605             : 
     606    28894774 : void Map::UpdateDescriptors(Isolate* isolate, DescriptorArray descriptors,
     607             :                             LayoutDescriptor layout_desc,
     608             :                             int number_of_own_descriptors) {
     609    28894774 :   SetInstanceDescriptors(isolate, descriptors, number_of_own_descriptors);
     610             :   if (FLAG_unbox_double_fields) {
     611    28894779 :     if (layout_descriptor()->IsSlowLayout()) {
     612        2806 :       set_layout_descriptor(layout_desc);
     613             :     }
     614             : #ifdef VERIFY_HEAP
     615             :     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
     616             :     if (FLAG_verify_heap) {
     617             :       CHECK(layout_descriptor()->IsConsistentWithMap(*this));
     618             :       CHECK_EQ(Map::GetVisitorId(*this), visitor_id());
     619             :     }
     620             : #else
     621             :     SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(*this));
     622             :     DCHECK(visitor_id() == Map::GetVisitorId(*this));
     623             : #endif
     624             :   }
     625    28894779 : }
     626             : 
     627    24598979 : void Map::InitializeDescriptors(Isolate* isolate, DescriptorArray descriptors,
     628             :                                 LayoutDescriptor layout_desc) {
     629    24598979 :   SetInstanceDescriptors(isolate, descriptors,
     630    24598979 :                          descriptors->number_of_descriptors());
     631             : 
     632             :   if (FLAG_unbox_double_fields) {
     633    24598992 :     set_layout_descriptor(layout_desc);
     634             : #ifdef VERIFY_HEAP
     635             :     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
     636             :     if (FLAG_verify_heap) {
     637             :       CHECK(layout_descriptor()->IsConsistentWithMap(*this));
     638             :     }
     639             : #else
     640             :     SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(*this));
     641             : #endif
     642    24598987 :     set_visitor_id(Map::GetVisitorId(*this));
     643             :   }
     644    24598983 : }
     645             : 
     646             : void Map::set_bit_field3(uint32_t bits) {
     647   237122326 :   RELAXED_WRITE_UINT32_FIELD(*this, kBitField3Offset, bits);
     648             : }
     649             : 
     650             : uint32_t Map::bit_field3() const {
     651  1760666108 :   return RELAXED_READ_UINT32_FIELD(*this, kBitField3Offset);
     652             : }
     653             : 
     654             : void Map::clear_padding() {
     655             :   if (FIELD_SIZE(kOptionalPaddingOffset) == 0) return;
     656             :   DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
     657    56389228 :   memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
     658             :          FIELD_SIZE(kOptionalPaddingOffset));
     659             : }
     660             : 
     661             : LayoutDescriptor Map::GetLayoutDescriptor() const {
     662             :   return FLAG_unbox_double_fields ? layout_descriptor()
     663             :                                   : LayoutDescriptor::FastPointerLayout();
     664             : }
     665             : 
     666       10328 : void Map::AppendDescriptor(Isolate* isolate, Descriptor* desc) {
     667       10328 :   DescriptorArray descriptors = instance_descriptors();
     668             :   int number_of_own_descriptors = NumberOfOwnDescriptors();
     669             :   DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
     670             :   {
     671             :     // The following two operations need to happen before the marking write
     672             :     // barrier.
     673       10328 :     descriptors->Append(desc);
     674       10328 :     SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
     675             :     MarkingBarrierForDescriptorArray(isolate->heap(), *this, descriptors,
     676             :                                      number_of_own_descriptors + 1);
     677             :   }
     678             :   // Properly mark the map if the {desc} is an "interesting symbol".
     679       10328 :   if (desc->GetKey()->IsInterestingSymbol()) {
     680         111 :     set_may_have_interesting_symbols(true);
     681             :   }
     682             :   PropertyDetails details = desc->GetDetails();
     683       10328 :   if (details.location() == kField) {
     684             :     DCHECK_GT(UnusedPropertyFields(), 0);
     685        3219 :     AccountAddedPropertyField();
     686             :   }
     687             : 
     688             : // This function does not support appending double field descriptors and
     689             : // it should never try to (otherwise, layout descriptor must be updated too).
     690             : #ifdef DEBUG
     691             :   DCHECK(details.location() != kField || !details.representation().IsDouble());
     692             : #endif
     693       10328 : }
     694             : 
     695   127807471 : HeapObject Map::GetBackPointer() const {
     696             :   Object object = constructor_or_backpointer();
     697   127807481 :   if (object->IsMap()) {
     698    76415814 :     return Map::cast(object);
     699             :   }
     700    51391667 :   return GetReadOnlyRoots().undefined_value();
     701             : }
     702             : 
     703     8282237 : Map Map::ElementsTransitionMap() {
     704             :   DisallowHeapAllocation no_gc;
     705             :   // TODO(delphick): While it's safe to pass nullptr for Isolate* here as
     706             :   // SearchSpecial doesn't need it, this is really ugly. Perhaps factor out a
     707             :   // base class for methods not requiring an Isolate?
     708             :   return TransitionsAccessor(nullptr, *this, &no_gc)
     709     8282247 :       .SearchSpecial(GetReadOnlyRoots().elements_transition_symbol());
     710             : }
     711             : 
     712             : Object Map::prototype_info() const {
     713             :   DCHECK(is_prototype_map());
     714    90628350 :   return READ_FIELD(*this, Map::kTransitionsOrPrototypeInfoOffset);
     715             : }
     716             : 
     717     9446889 : void Map::set_prototype_info(Object value, WriteBarrierMode mode) {
     718     9446889 :   CHECK(is_prototype_map());
     719     9446889 :   WRITE_FIELD(*this, Map::kTransitionsOrPrototypeInfoOffset, value);
     720    18893781 :   CONDITIONAL_WRITE_BARRIER(*this, Map::kTransitionsOrPrototypeInfoOffset,
     721             :                             value, mode);
     722     9446891 : }
     723             : 
     724     7340217 : void Map::SetBackPointer(Object value, WriteBarrierMode mode) {
     725     7340217 :   CHECK_GE(instance_type(), FIRST_JS_RECEIVER_TYPE);
     726     7340217 :   CHECK(value->IsMap());
     727    14680442 :   CHECK(GetBackPointer()->IsUndefined());
     728    22020664 :   CHECK_IMPLIES(value->IsMap(), Map::cast(value)->GetConstructor() ==
     729             :                                     constructor_or_backpointer());
     730     7340222 :   set_constructor_or_backpointer(value, mode);
     731     7340220 : }
     732             : 
     733    51090725 : ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
     734   181236787 : ACCESSORS(Map, prototype_validity_cell, Object, kPrototypeValidityCellOffset)
     735  1358889054 : ACCESSORS(Map, constructor_or_backpointer, Object,
     736             :           kConstructorOrBackPointerOffset)
     737             : 
     738             : bool Map::IsPrototypeValidityCellValid() const {
     739             :   Object validity_cell = prototype_validity_cell();
     740             :   Object value = validity_cell->IsSmi() ? Smi::cast(validity_cell)
     741     1376690 :                                         : Cell::cast(validity_cell)->value();
     742             :   return value == Smi::FromInt(Map::kPrototypeChainValid);
     743             : }
     744             : 
     745    87636675 : Object Map::GetConstructor() const {
     746             :   Object maybe_constructor = constructor_or_backpointer();
     747             :   // Follow any back pointers.
     748  1851981615 :   while (maybe_constructor->IsMap()) {
     749             :     maybe_constructor =
     750             :         Map::cast(maybe_constructor)->constructor_or_backpointer();
     751             :   }
     752    87636703 :   return maybe_constructor;
     753             : }
     754             : 
     755     2270993 : FunctionTemplateInfo Map::GetFunctionTemplateInfo() const {
     756     2270993 :   Object constructor = GetConstructor();
     757     2270993 :   if (constructor->IsJSFunction()) {
     758             :     DCHECK(JSFunction::cast(constructor)->shared()->IsApiFunction());
     759             :     return JSFunction::cast(constructor)->shared()->get_api_func_data();
     760             :   }
     761             :   DCHECK(constructor->IsFunctionTemplateInfo());
     762             :   return FunctionTemplateInfo::cast(constructor);
     763             : }
     764             : 
     765     9660308 : void Map::SetConstructor(Object constructor, WriteBarrierMode mode) {
     766             :   // Never overwrite a back pointer with a constructor.
     767     9660308 :   CHECK(!constructor_or_backpointer()->IsMap());
     768     9660308 :   set_constructor_or_backpointer(constructor, mode);
     769     9660307 : }
     770             : 
     771      416383 : Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map) {
     772             :   return CopyInitialMap(isolate, map, map->instance_size(),
     773             :                         map->GetInObjectProperties(),
     774     1249149 :                         map->UnusedPropertyFields());
     775             : }
     776             : 
     777             : bool Map::IsInobjectSlackTrackingInProgress() const {
     778        6410 :   return construction_counter() != Map::kNoSlackTracking;
     779             : }
     780             : 
     781      231241 : void Map::InobjectSlackTrackingStep(Isolate* isolate) {
     782             :   // Slack tracking should only be performed on an initial map.
     783             :   DCHECK(GetBackPointer()->IsUndefined());
     784      231241 :   if (!IsInobjectSlackTrackingInProgress()) return;
     785             :   int counter = construction_counter();
     786      231241 :   set_construction_counter(counter - 1);
     787      231241 :   if (counter == kSlackTrackingCounterEnd) {
     788         294 :     CompleteInobjectSlackTracking(isolate);
     789             :   }
     790             : }
     791             : 
     792     2390160 : int Map::SlackForArraySize(int old_size, int size_limit) {
     793     2390160 :   const int max_slack = size_limit - old_size;
     794     2390160 :   CHECK_LE(0, max_slack);
     795     2390160 :   if (old_size < 4) {
     796             :     DCHECK_LE(1, max_slack);
     797             :     return 1;
     798             :   }
     799     2536040 :   return Min(max_slack, old_size / 4);
     800             : }
     801             : 
     802             : int Map::InstanceSizeFromSlack(int slack) const {
     803      274659 :   return instance_size() - slack * kTaggedSize;
     804             : }
     805             : 
     806             : OBJECT_CONSTRUCTORS_IMPL(NormalizedMapCache, WeakFixedArray)
     807             : CAST_ACCESSOR(NormalizedMapCache)
     808             : NEVER_READ_ONLY_SPACE_IMPL(NormalizedMapCache)
     809             : 
     810             : int NormalizedMapCache::GetIndex(Handle<Map> map) {
     811      761963 :   return map->Hash() % NormalizedMapCache::kEntries;
     812             : }
     813             : 
     814             : bool HeapObject::IsNormalizedMapCache() const {
     815             :   if (!IsWeakFixedArray()) return false;
     816             :   if (WeakFixedArray::cast(*this)->length() != NormalizedMapCache::kEntries) {
     817             :     return false;
     818             :   }
     819             :   return true;
     820             : }
     821             : 
     822             : }  // namespace internal
     823             : }  // namespace v8
     824             : 
     825             : #include "src/objects/object-macros-undef.h"
     826             : 
     827             : #endif  // V8_OBJECTS_MAP_INL_H_

Generated by: LCOV version 1.10