LCOV - code coverage report
Current view: top level - src/objects - map-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 302 304 99.3 %
Date: 2019-01-20 Functions: 98 98 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-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.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  3427425400 : OBJECT_CONSTRUCTORS_IMPL(Map, HeapObject)
      31  1717965485 : CAST_ACCESSOR(Map)
      32             : 
      33   722469533 : DescriptorArray Map::instance_descriptors() const {
      34  1444939240 :   return DescriptorArray::cast(READ_FIELD(*this, kDescriptorsOffset));
      35             : }
      36             : 
      37    29231776 : DescriptorArray Map::synchronized_instance_descriptors() const {
      38    58493332 :   return DescriptorArray::cast(ACQUIRE_READ_FIELD(*this, kDescriptorsOffset));
      39             : }
      40             : 
      41    80195629 : void Map::set_synchronized_instance_descriptors(DescriptorArray value,
      42             :                                                 WriteBarrierMode mode) {
      43    80195629 :   RELEASE_WRITE_FIELD(*this, kDescriptorsOffset, value);
      44   240586923 :   CONDITIONAL_WRITE_BARRIER(*this, kDescriptorsOffset, value, mode);
      45    80195612 : }
      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   411655200 : SYNCHRONIZED_ACCESSORS_CHECKED(Map, layout_descriptor, LayoutDescriptor,
      52             :                                kLayoutDescriptorOffset,
      53             :                                FLAG_unbox_double_fields)
      54   286239192 : WEAK_ACCESSORS(Map, raw_transitions, kTransitionsOrPrototypeInfoOffset)
      55             : 
      56             : // |bit_field| fields.
      57      180420 : BIT_FIELD_ACCESSORS(Map, bit_field, has_non_instance_prototype,
      58             :                     Map::HasNonInstancePrototypeBit)
      59    27657374 : BIT_FIELD_ACCESSORS(Map, bit_field, is_callable, Map::IsCallableBit)
      60         336 : BIT_FIELD_ACCESSORS(Map, bit_field, has_named_interceptor,
      61             :                     Map::HasNamedInterceptorBit)
      62         252 : BIT_FIELD_ACCESSORS(Map, bit_field, has_indexed_interceptor,
      63             :                     Map::HasIndexedInterceptorBit)
      64   175468896 : BIT_FIELD_ACCESSORS(Map, bit_field, is_undetectable, Map::IsUndetectableBit)
      65    71858026 : BIT_FIELD_ACCESSORS(Map, bit_field, is_access_check_needed,
      66             :                     Map::IsAccessCheckNeededBit)
      67    13398037 : BIT_FIELD_ACCESSORS(Map, bit_field, is_constructor, Map::IsConstructorBit)
      68        1554 : BIT_FIELD_ACCESSORS(Map, bit_field, has_prototype_slot,
      69             :                     Map::HasPrototypeSlotBit)
      70             : 
      71             : // |bit_field2| fields.
      72      151712 : BIT_FIELD_ACCESSORS(Map, bit_field2, is_extensible, Map::IsExtensibleBit)
      73             : BIT_FIELD_ACCESSORS(Map, bit_field2, is_prototype_map, Map::IsPrototypeMapBit)
      74             : BIT_FIELD_ACCESSORS(Map, bit_field2, is_in_retained_map_list,
      75             :                     Map::IsInRetainedMapListBit)
      76             : 
      77             : // |bit_field3| fields.
      78    54120384 : BIT_FIELD_ACCESSORS(Map, bit_field3, owns_descriptors, Map::OwnsDescriptorsBit)
      79   174130542 : BIT_FIELD_ACCESSORS(Map, bit_field3, has_hidden_prototype,
      80             :                     Map::HasHiddenPrototypeBit)
      81    70836578 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
      82      721542 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_migration_target,
      83             :                     Map::IsMigrationTargetBit)
      84      370902 : BIT_FIELD_ACCESSORS(Map, bit_field3, is_immutable_proto,
      85             :                     Map::IsImmutablePrototypeBit)
      86    73299036 : BIT_FIELD_ACCESSORS(Map, bit_field3, new_target_is_base,
      87             :                     Map::NewTargetIsBaseBit)
      88     4176984 : BIT_FIELD_ACCESSORS(Map, bit_field3, may_have_interesting_symbols,
      89             :                     Map::MayHaveInterestingSymbolsBit)
      90     2175064 : BIT_FIELD_ACCESSORS(Map, bit_field3, construction_counter,
      91             :                     Map::ConstructionCounterBits)
      92             : 
      93     1538689 : InterceptorInfo Map::GetNamedInterceptor() {
      94             :   DCHECK(has_named_interceptor());
      95     1538689 :   FunctionTemplateInfo info = GetFunctionTemplateInfo();
      96     3077378 :   return InterceptorInfo::cast(info->GetNamedPropertyHandler());
      97             : }
      98             : 
      99      621280 : InterceptorInfo Map::GetIndexedInterceptor() {
     100             :   DCHECK(has_indexed_interceptor());
     101      621280 :   FunctionTemplateInfo info = GetFunctionTemplateInfo();
     102     1242560 :   return InterceptorInfo::cast(info->GetIndexedPropertyHandler());
     103             : }
     104             : 
     105             : bool Map::IsInplaceGeneralizableField(PropertyConstness constness,
     106             :                                       Representation representation,
     107             :                                       FieldType field_type) {
     108             :   if (FLAG_track_constant_fields && FLAG_modify_map_inplace &&
     109             :       (constness == PropertyConstness::kConst)) {
     110             :     // VariableMode::kConst -> PropertyConstness::kMutable field generalization
     111             :     // may happen in-place.
     112             :     return true;
     113             :   }
     114        1294 :   if (representation.IsHeapObject() && !field_type->IsAny()) {
     115             :     return true;
     116             :   }
     117             :   return false;
     118             : }
     119             : 
     120             : bool Map::CanHaveFastTransitionableElementsKind(InstanceType instance_type) {
     121     7650642 :   return instance_type == JS_ARRAY_TYPE || instance_type == JS_VALUE_TYPE ||
     122             :          instance_type == JS_ARGUMENTS_TYPE;
     123             : }
     124             : 
     125             : bool Map::CanHaveFastTransitionableElementsKind() const {
     126             :   return CanHaveFastTransitionableElementsKind(instance_type());
     127             : }
     128             : 
     129             : // static
     130     7650154 : void Map::GeneralizeIfCanHaveTransitionableFastElementsKind(
     131             :     Isolate* isolate, InstanceType instance_type, PropertyConstness* constness,
     132             :     Representation* representation, Handle<FieldType>* field_type) {
     133     7650154 :   if (CanHaveFastTransitionableElementsKind(instance_type)) {
     134             :     // We don't support propagation of field generalization through elements
     135             :     // kind transitions because they are inserted into the transition tree
     136             :     // before field transitions. In order to avoid complexity of handling
     137             :     // such a case we ensure that all maps with transitionable elements kinds
     138             :     // do not have fields that can be generalized in-place (without creation
     139             :     // of a new map).
     140             :     if (FLAG_track_constant_fields && FLAG_modify_map_inplace) {
     141             :       // The constness is either already PropertyConstness::kMutable or should
     142             :       // become PropertyConstness::kMutable if it was VariableMode::kConst.
     143             :       *constness = PropertyConstness::kMutable;
     144             :     }
     145       22352 :     if (representation->IsHeapObject()) {
     146             :       // The field type is either already Any or should become Any if it was
     147             :       // something else.
     148       16036 :       *field_type = FieldType::Any(isolate);
     149             :     }
     150             :   }
     151     7650154 : }
     152             : 
     153    54918283 : bool Map::IsUnboxedDoubleField(FieldIndex index) const {
     154             :   if (!FLAG_unbox_double_fields) return false;
     155   109836574 :   if (index.is_hidden_field() || !index.is_inobject()) return false;
     156    13501477 :   return !layout_descriptor()->IsTagged(index.property_index());
     157             : }
     158             : 
     159    17564353 : bool Map::TooManyFastProperties(StoreOrigin store_origin) const {
     160    17564353 :   if (UnusedPropertyFields() != 0) return false;
     161     3363322 :   if (is_prototype_map()) return false;
     162     2651061 :   if (store_origin == StoreOrigin::kNamed) {
     163     2602154 :     int limit = Max(kMaxFastProperties, GetInObjectProperties());
     164     2602154 :     FieldCounts counts = GetFieldCounts();
     165             :     // Only count mutable fields so that objects with large numbers of
     166             :     // constant functions do not go to dictionary mode. That would be bad
     167             :     // because such objects have often been used as modules.
     168     2602154 :     int external = counts.mutable_count() - GetInObjectProperties();
     169     5198968 :     return external > limit || counts.GetTotal() > kMaxNumberOfDescriptors;
     170             :   } else {
     171       48907 :     int limit = Max(kFastPropertiesSoftLimit, GetInObjectProperties());
     172       48907 :     int external = NumberOfFields() - GetInObjectProperties();
     173       48907 :     return external > limit;
     174             :   }
     175             : }
     176             : 
     177    78520049 : PropertyDetails Map::GetLastDescriptorDetails() const {
     178    78520049 :   return instance_descriptors()->GetDetails(LastAdded());
     179             : }
     180             : 
     181   159783951 : int Map::LastAdded() const {
     182             :   int number_of_own_descriptors = NumberOfOwnDescriptors();
     183             :   DCHECK_GT(number_of_own_descriptors, 0);
     184   159783951 :   return number_of_own_descriptors - 1;
     185             : }
     186             : 
     187   127247444 : int Map::NumberOfOwnDescriptors() const {
     188   127247444 :   return NumberOfOwnDescriptorsBits::decode(bit_field3());
     189             : }
     190             : 
     191    80205928 : void Map::SetNumberOfOwnDescriptors(int number) {
     192             :   DCHECK_LE(number, instance_descriptors()->number_of_descriptors());
     193    80205928 :   CHECK_LE(static_cast<unsigned>(number),
     194             :            static_cast<unsigned>(kMaxNumberOfDescriptors));
     195    80205928 :   set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
     196    80205931 : }
     197             : 
     198             : int Map::EnumLength() const { return EnumLengthBits::decode(bit_field3()); }
     199             : 
     200      104752 : void Map::SetEnumLength(int length) {
     201      104752 :   if (length != kInvalidEnumCacheSentinel) {
     202             :     DCHECK_LE(length, NumberOfOwnDescriptors());
     203       61920 :     CHECK_LE(static_cast<unsigned>(length),
     204             :              static_cast<unsigned>(kMaxNumberOfDescriptors));
     205             :   }
     206      104752 :   set_bit_field3(EnumLengthBits::update(bit_field3(), length));
     207      104752 : }
     208             : 
     209    41584061 : FixedArrayBase Map::GetInitialElements() const {
     210             :   FixedArrayBase result;
     211    41584061 :   if (has_fast_elements() || has_fast_string_wrapper_elements()) {
     212    83153124 :     result = GetReadOnlyRoots().empty_fixed_array();
     213        7503 :   } else if (has_fast_sloppy_arguments_elements()) {
     214           0 :     result = GetReadOnlyRoots().empty_sloppy_arguments_elements();
     215        7503 :   } else if (has_fixed_typed_array_elements()) {
     216        8364 :     result = GetReadOnlyRoots().EmptyFixedTypedArrayForMap(*this);
     217        3321 :   } else if (has_dictionary_elements()) {
     218        6642 :     result = GetReadOnlyRoots().empty_slow_element_dictionary();
     219             :   } else {
     220           0 :     UNREACHABLE();
     221             :   }
     222             :   DCHECK(!Heap::InNewSpace(result));
     223    41584069 :   return result;
     224             : }
     225             : 
     226   969241684 : VisitorId Map::visitor_id() const {
     227             :   return static_cast<VisitorId>(
     228  2013109286 :       RELAXED_READ_BYTE_FIELD(this, kVisitorIdOffset));
     229             : }
     230             : 
     231    54733813 : void Map::set_visitor_id(VisitorId id) {
     232    54733813 :   CHECK_LT(static_cast<unsigned>(id), 256);
     233   109467626 :   RELAXED_WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
     234    54733813 : }
     235             : 
     236             : int Map::instance_size_in_words() const {
     237  6605275973 :   return RELAXED_READ_BYTE_FIELD(this, kInstanceSizeInWordsOffset);
     238             : }
     239             : 
     240             : void Map::set_instance_size_in_words(int value) {
     241    30936611 :   RELAXED_WRITE_BYTE_FIELD(this, kInstanceSizeInWordsOffset,
     242             :                            static_cast<byte>(value));
     243             : }
     244             : 
     245    48376000 : int Map::instance_size() const {
     246  2943817361 :   return instance_size_in_words() << kTaggedSizeLog2;
     247             : }
     248             : 
     249    30936611 : void Map::set_instance_size(int value) {
     250    30936611 :   CHECK(IsAligned(value, kTaggedSize));
     251    30936611 :   value >>= kTaggedSizeLog2;
     252    30936611 :   CHECK_LT(static_cast<unsigned>(value), 256);
     253             :   set_instance_size_in_words(value);
     254    30936611 : }
     255             : 
     256             : int Map::inobject_properties_start_or_constructor_function_index() const {
     257   881321654 :   return RELAXED_READ_BYTE_FIELD(
     258             :       this, kInObjectPropertiesStartOrConstructorFunctionIndexOffset);
     259             : }
     260             : 
     261    30674677 : void Map::set_inobject_properties_start_or_constructor_function_index(
     262             :     int value) {
     263    30674677 :   CHECK_LT(static_cast<unsigned>(value), 256);
     264    61349354 :   RELAXED_WRITE_BYTE_FIELD(
     265             :       this, kInObjectPropertiesStartOrConstructorFunctionIndexOffset,
     266             :       static_cast<byte>(value));
     267    30674677 : }
     268             : 
     269             : int Map::GetInObjectPropertiesStartInWords() const {
     270             :   DCHECK(IsJSObjectMap());
     271             :   return inobject_properties_start_or_constructor_function_index();
     272             : }
     273             : 
     274    30664297 : void Map::SetInObjectPropertiesStartInWords(int value) {
     275    30664297 :   CHECK(IsJSObjectMap());
     276    30664297 :   set_inobject_properties_start_or_constructor_function_index(value);
     277    30664321 : }
     278             : 
     279   288285142 : int Map::GetInObjectProperties() const {
     280             :   DCHECK(IsJSObjectMap());
     281   288285142 :   return instance_size_in_words() - GetInObjectPropertiesStartInWords();
     282             : }
     283             : 
     284             : int Map::GetConstructorFunctionIndex() const {
     285             :   DCHECK(IsPrimitiveMap());
     286             :   return inobject_properties_start_or_constructor_function_index();
     287             : }
     288             : 
     289        1512 : void Map::SetConstructorFunctionIndex(int value) {
     290        1512 :   CHECK(IsPrimitiveMap());
     291        1512 :   set_inobject_properties_start_or_constructor_function_index(value);
     292        1512 : }
     293             : 
     294             : int Map::GetInObjectPropertyOffset(int index) const {
     295   114484598 :   return (GetInObjectPropertiesStartInWords() + index) * kTaggedSize;
     296             : }
     297             : 
     298             : Handle<Map> Map::AddMissingTransitionsForTesting(
     299             :     Isolate* isolate, Handle<Map> split_map,
     300             :     Handle<DescriptorArray> descriptors,
     301             :     Handle<LayoutDescriptor> full_layout_descriptor) {
     302             :   return AddMissingTransitions(isolate, split_map, descriptors,
     303          65 :                                full_layout_descriptor);
     304             : }
     305             : 
     306 11002791644 : InstanceType Map::instance_type() const {
     307             :   return static_cast<InstanceType>(
     308 21335522896 :       READ_UINT16_FIELD(this, kInstanceTypeOffset));
     309             : }
     310             : 
     311             : void Map::set_instance_type(InstanceType value) {
     312    30579344 :   WRITE_UINT16_FIELD(this, kInstanceTypeOffset, value);
     313             : }
     314             : 
     315   104883484 : int Map::UnusedPropertyFields() const {
     316             :   int value = used_or_unused_instance_size_in_words();
     317             :   DCHECK_IMPLIES(!IsJSObjectMap(), value == 0);
     318             :   int unused;
     319   104883484 :   if (value >= JSObject::kFieldsAdded) {
     320    67153760 :     unused = instance_size_in_words() - value;
     321             :   } else {
     322             :     // For out of object properties "used_or_unused_instance_size_in_words"
     323             :     // byte encodes the slack in the property array.
     324             :     unused = value;
     325             :   }
     326   104883484 :   return unused;
     327             : }
     328             : 
     329         306 : int Map::UnusedInObjectProperties() const {
     330             :   // Like Map::UnusedPropertyFields(), but returns 0 for out of object
     331             :   // properties.
     332             :   int value = used_or_unused_instance_size_in_words();
     333             :   DCHECK_IMPLIES(!IsJSObjectMap(), value == 0);
     334         306 :   if (value >= JSObject::kFieldsAdded) {
     335         270 :     return instance_size_in_words() - value;
     336             :   }
     337             :   return 0;
     338             : }
     339             : 
     340             : int Map::used_or_unused_instance_size_in_words() const {
     341   385458214 :   return RELAXED_READ_BYTE_FIELD(this, kUsedOrUnusedInstanceSizeInWordsOffset);
     342             : }
     343             : 
     344    63340720 : void Map::set_used_or_unused_instance_size_in_words(int value) {
     345    63340720 :   CHECK_LE(static_cast<unsigned>(value), 255);
     346   126681440 :   RELAXED_WRITE_BYTE_FIELD(this, kUsedOrUnusedInstanceSizeInWordsOffset,
     347             :                            static_cast<byte>(value));
     348    63340720 : }
     349             : 
     350    56239049 : int Map::UsedInstanceSize() const {
     351             :   int words = used_or_unused_instance_size_in_words();
     352    56239049 :   if (words < JSObject::kFieldsAdded) {
     353             :     // All in-object properties are used and the words is tracking the slack
     354             :     // in the property array.
     355     3433983 :     return instance_size();
     356             :   }
     357    52805066 :   return words * kTaggedSize;
     358             : }
     359             : 
     360    31706201 : void Map::SetInObjectUnusedPropertyFields(int value) {
     361             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     362    31706201 :   if (!IsJSObjectMap()) {
     363        8850 :     CHECK_EQ(0, value);
     364        8850 :     set_used_or_unused_instance_size_in_words(0);
     365             :     DCHECK_EQ(0, UnusedPropertyFields());
     366    31715061 :     return;
     367             :   }
     368    31697351 :   CHECK_LE(0, value);
     369             :   DCHECK_LE(value, GetInObjectProperties());
     370    31697351 :   int used_inobject_properties = GetInObjectProperties() - value;
     371             :   set_used_or_unused_instance_size_in_words(
     372    31697353 :       GetInObjectPropertyOffset(used_inobject_properties) / kTaggedSize);
     373             :   DCHECK_EQ(value, UnusedPropertyFields());
     374             : }
     375             : 
     376       28255 : void Map::SetOutOfObjectUnusedPropertyFields(int value) {
     377             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     378       28255 :   CHECK_LT(static_cast<unsigned>(value), JSObject::kFieldsAdded);
     379             :   // For out of object properties "used_instance_size_in_words" byte encodes
     380             :   // the slack in the property array.
     381       28255 :   set_used_or_unused_instance_size_in_words(value);
     382             :   DCHECK_EQ(value, UnusedPropertyFields());
     383       28255 : }
     384             : 
     385    24241144 : void Map::CopyUnusedPropertyFields(Map map) {
     386             :   set_used_or_unused_instance_size_in_words(
     387    24241144 :       map->used_or_unused_instance_size_in_words());
     388             :   DCHECK_EQ(UnusedPropertyFields(), map->UnusedPropertyFields());
     389    24241138 : }
     390             : 
     391         261 : void Map::CopyUnusedPropertyFieldsAdjustedForInstanceSize(Map map) {
     392             :   int value = map->used_or_unused_instance_size_in_words();
     393         261 :   if (value >= JSValue::kFieldsAdded) {
     394             :     // Unused in-object fields. Adjust the offset from the object’s start
     395             :     // so it matches the distance to the object’s end.
     396         225 :     value += instance_size_in_words() - map->instance_size_in_words();
     397             :   }
     398         261 :   set_used_or_unused_instance_size_in_words(value);
     399             :   DCHECK_EQ(UnusedPropertyFields(), map->UnusedPropertyFields());
     400         261 : }
     401             : 
     402     7364863 : void Map::AccountAddedPropertyField() {
     403             :   // Update used instance size and unused property fields number.
     404             :   STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kTaggedSize);
     405             : #ifdef DEBUG
     406             :   int new_unused = UnusedPropertyFields() - 1;
     407             :   if (new_unused < 0) new_unused += JSObject::kFieldsAdded;
     408             : #endif
     409             :   int value = used_or_unused_instance_size_in_words();
     410     7364863 :   if (value >= JSObject::kFieldsAdded) {
     411     3381116 :     if (value == instance_size_in_words()) {
     412      346465 :       AccountAddedOutOfObjectPropertyField(0);
     413             :     } else {
     414             :       // The property is added in-object, so simply increment the counter.
     415     3034651 :       set_used_or_unused_instance_size_in_words(value + 1);
     416             :     }
     417             :   } else {
     418     3983747 :     AccountAddedOutOfObjectPropertyField(value);
     419             :   }
     420             :   DCHECK_EQ(new_unused, UnusedPropertyFields());
     421     7364866 : }
     422             : 
     423     4330212 : void Map::AccountAddedOutOfObjectPropertyField(int unused_in_property_array) {
     424     4330212 :   unused_in_property_array--;
     425     4330212 :   if (unused_in_property_array < 0) {
     426     1642773 :     unused_in_property_array += JSObject::kFieldsAdded;
     427             :   }
     428     4330212 :   CHECK_LT(static_cast<unsigned>(unused_in_property_array),
     429             :            JSObject::kFieldsAdded);
     430     4330212 :   set_used_or_unused_instance_size_in_words(unused_in_property_array);
     431             :   DCHECK_EQ(unused_in_property_array, UnusedPropertyFields());
     432     4330212 : }
     433             : 
     434   365162105 : byte Map::bit_field() const { return READ_BYTE_FIELD(this, kBitFieldOffset); }
     435             : 
     436             : void Map::set_bit_field(byte value) {
     437    55942055 :   WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
     438             : }
     439             : 
     440   769634732 : byte Map::bit_field2() const { return READ_BYTE_FIELD(this, kBitField2Offset); }
     441             : 
     442             : void Map::set_bit_field2(byte value) {
     443    91333669 :   WRITE_BYTE_FIELD(this, kBitField2Offset, value);
     444             : }
     445             : 
     446      446121 : bool Map::is_abandoned_prototype_map() const {
     447      446121 :   return is_prototype_map() && !owns_descriptors();
     448             : }
     449             : 
     450    32317135 : bool Map::should_be_fast_prototype_map() const {
     451    64634315 :   if (!prototype_info()->IsPrototypeInfo()) return false;
     452    28634031 :   return PrototypeInfo::cast(prototype_info())->should_be_fast_map();
     453             : }
     454             : 
     455    30927122 : void Map::set_elements_kind(ElementsKind elements_kind) {
     456    30927122 :   CHECK_LT(static_cast<int>(elements_kind), kElementsKindCount);
     457    30927122 :   set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind));
     458    30927122 : }
     459             : 
     460      449347 : ElementsKind Map::elements_kind() const {
     461      449347 :   return Map::ElementsKindBits::decode(bit_field2());
     462             : }
     463             : 
     464             : bool Map::has_fast_smi_elements() const {
     465             :   return IsSmiElementsKind(elements_kind());
     466             : }
     467             : 
     468             : bool Map::has_fast_object_elements() const {
     469             :   return IsObjectElementsKind(elements_kind());
     470             : }
     471             : 
     472             : bool Map::has_fast_smi_or_object_elements() const {
     473             :   return IsSmiOrObjectElementsKind(elements_kind());
     474             : }
     475             : 
     476             : bool Map::has_fast_double_elements() const {
     477             :   return IsDoubleElementsKind(elements_kind());
     478             : }
     479             : 
     480             : bool Map::has_fast_elements() const {
     481             :   return IsFastElementsKind(elements_kind());
     482             : }
     483             : 
     484             : bool Map::has_sloppy_arguments_elements() const {
     485             :   return IsSloppyArgumentsElementsKind(elements_kind());
     486             : }
     487             : 
     488             : bool Map::has_fast_sloppy_arguments_elements() const {
     489             :   return elements_kind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
     490             : }
     491             : 
     492             : bool Map::has_fast_string_wrapper_elements() const {
     493             :   return elements_kind() == FAST_STRING_WRAPPER_ELEMENTS;
     494             : }
     495             : 
     496             : bool Map::has_fixed_typed_array_elements() const {
     497             :   return IsFixedTypedArrayElementsKind(elements_kind());
     498             : }
     499             : 
     500             : bool Map::has_dictionary_elements() const {
     501             :   return IsDictionaryElementsKind(elements_kind());
     502             : }
     503             : 
     504      766230 : void Map::set_is_dictionary_map(bool value) {
     505             :   uint32_t new_bit_field3 = IsDictionaryMapBit::update(bit_field3(), value);
     506             :   new_bit_field3 = IsUnstableBit::update(new_bit_field3, value);
     507      766230 :   set_bit_field3(new_bit_field3);
     508      766230 : }
     509             : 
     510   437730224 : bool Map::is_dictionary_map() const {
     511   437730224 :   return IsDictionaryMapBit::decode(bit_field3());
     512             : }
     513             : 
     514    18004059 : void Map::mark_unstable() {
     515    18004059 :   set_bit_field3(IsUnstableBit::update(bit_field3(), true));
     516    18004061 : }
     517             : 
     518    76403472 : bool Map::is_stable() const { return !IsUnstableBit::decode(bit_field3()); }
     519             : 
     520    24836780 : bool Map::CanBeDeprecated() const {
     521    24836780 :   int descriptor = LastAdded();
     522    84322202 :   for (int i = 0; i <= descriptor; i++) {
     523    67418098 :     PropertyDetails details = instance_descriptors()->GetDetails(i);
     524    67417579 :     if (details.representation().IsNone()) return true;
     525    67418925 :     if (details.representation().IsSmi()) return true;
     526    64650955 :     if (details.representation().IsDouble()) return true;
     527    64650168 :     if (details.representation().IsHeapObject()) return true;
     528    74690371 :     if (details.kind() == kData && details.location() == kDescriptor) {
     529             :       return true;
     530             :     }
     531             :   }
     532             :   return false;
     533             : }
     534             : 
     535    34369218 : void Map::NotifyLeafMapLayoutChange(Isolate* isolate) {
     536    34369218 :   if (is_stable()) {
     537    18003779 :     mark_unstable();
     538             :     dependent_code()->DeoptimizeDependentCodeGroup(
     539    18003780 :         isolate, DependentCode::kPrototypeCheckGroup);
     540             :   }
     541    34369216 : }
     542             : 
     543    11632700 : bool Map::CanTransition() const {
     544             :   // Only JSObject and subtypes have map transitions and back pointers.
     545    11632700 :   return InstanceTypeChecker::IsJSObject(instance_type());
     546             : }
     547             : 
     548             : #define DEF_TESTER(Type, ...)                              \
     549             :   bool Map::Is##Type##Map() const {                        \
     550             :     return InstanceTypeChecker::Is##Type(instance_type()); \
     551             :   }
     552             : INSTANCE_TYPE_CHECKERS(DEF_TESTER)
     553             : #undef DEF_TESTER
     554             : 
     555      252561 : bool Map::IsBooleanMap() const {
     556      505123 :   return *this == GetReadOnlyRoots().boolean_map();
     557             : }
     558             : 
     559         513 : bool Map::IsNullOrUndefinedMap() const {
     560        2043 :   return *this == GetReadOnlyRoots().null_map() ||
     561        1530 :          *this == GetReadOnlyRoots().undefined_map();
     562             : }
     563             : 
     564     5420092 : bool Map::IsPrimitiveMap() const {
     565     5420092 :   return instance_type() <= LAST_PRIMITIVE_TYPE;
     566             : }
     567             : 
     568   642292694 : Object Map::prototype() const { return READ_FIELD(this, kPrototypeOffset); }
     569             : 
     570    61884189 : void Map::set_prototype(Object value, WriteBarrierMode mode) {
     571             :   DCHECK(value->IsNull() || value->IsJSReceiver());
     572    61884189 :   WRITE_FIELD(*this, kPrototypeOffset, value);
     573   115048312 :   CONDITIONAL_WRITE_BARRIER(*this, kPrototypeOffset, value, mode);
     574    61884196 : }
     575             : 
     576             : LayoutDescriptor Map::layout_descriptor_gc_safe() const {
     577             :   DCHECK(FLAG_unbox_double_fields);
     578             :   // The loaded value can be dereferenced on background thread to load the
     579             :   // bitmap. We need acquire load in order to ensure that the bitmap
     580             :   // initializing stores are also visible to the background thread.
     581      271217 :   Object layout_desc = ACQUIRE_READ_FIELD(*this, kLayoutDescriptorOffset);
     582             :   return LayoutDescriptor::cast_gc_safe(layout_desc);
     583             : }
     584             : 
     585    73021095 : bool Map::HasFastPointerLayout() const {
     586             :   DCHECK(FLAG_unbox_double_fields);
     587             :   // The loaded value is used for SMI check only and is not dereferenced,
     588             :   // so relaxed load is safe.
     589    73021095 :   Object layout_desc = RELAXED_READ_FIELD(*this, kLayoutDescriptorOffset);
     590    73007304 :   return LayoutDescriptor::IsFastPointerLayout(layout_desc);
     591             : }
     592             : 
     593    25556093 : void Map::UpdateDescriptors(Isolate* isolate, DescriptorArray descriptors,
     594             :                             LayoutDescriptor layout_desc,
     595             :                             int number_of_own_descriptors) {
     596    25556093 :   SetInstanceDescriptors(isolate, descriptors, number_of_own_descriptors);
     597             :   if (FLAG_unbox_double_fields) {
     598    51112156 :     if (layout_descriptor()->IsSlowLayout()) {
     599        2809 :       set_layout_descriptor(layout_desc);
     600             :     }
     601             : #ifdef VERIFY_HEAP
     602             :     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
     603             :     if (FLAG_verify_heap) {
     604             :       CHECK(layout_descriptor()->IsConsistentWithMap(*this));
     605             :       CHECK_EQ(Map::GetVisitorId(*this), visitor_id());
     606             :     }
     607             : #else
     608             :     SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(*this));
     609             :     DCHECK(visitor_id() == Map::GetVisitorId(*this));
     610             : #endif
     611             :   }
     612    25556078 : }
     613             : 
     614    24009195 : void Map::InitializeDescriptors(Isolate* isolate, DescriptorArray descriptors,
     615             :                                 LayoutDescriptor layout_desc) {
     616             :   SetInstanceDescriptors(isolate, descriptors,
     617    24009195 :                          descriptors->number_of_descriptors());
     618             : 
     619             :   if (FLAG_unbox_double_fields) {
     620    24009188 :     set_layout_descriptor(layout_desc);
     621             : #ifdef VERIFY_HEAP
     622             :     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
     623             :     if (FLAG_verify_heap) {
     624             :       CHECK(layout_descriptor()->IsConsistentWithMap(*this));
     625             :     }
     626             : #else
     627             :     SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(*this));
     628             : #endif
     629    24009197 :     set_visitor_id(Map::GetVisitorId(*this));
     630             :   }
     631    24009203 : }
     632             : 
     633   229652424 : void Map::set_bit_field3(uint32_t bits) {
     634             :   if (kInt32Size != kTaggedSize) {
     635   229652424 :     RELAXED_WRITE_UINT32_FIELD(this, kBitField3Offset + kInt32Size, 0);
     636             :   }
     637   229652424 :   RELAXED_WRITE_UINT32_FIELD(this, kBitField3Offset, bits);
     638   229652424 : }
     639             : 
     640             : uint32_t Map::bit_field3() const {
     641  1790731984 :   return RELAXED_READ_UINT32_FIELD(this, kBitField3Offset);
     642             : }
     643             : 
     644             : LayoutDescriptor Map::GetLayoutDescriptor() const {
     645             :   return FLAG_unbox_double_fields ? layout_descriptor()
     646    13609600 :                                   : LayoutDescriptor::FastPointerLayout();
     647             : }
     648             : 
     649       10328 : void Map::AppendDescriptor(Isolate* isolate, Descriptor* desc) {
     650       10328 :   DescriptorArray descriptors = instance_descriptors();
     651             :   int number_of_own_descriptors = NumberOfOwnDescriptors();
     652             :   DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
     653             :   {
     654             :     // The following two operations need to happen before the marking write
     655             :     // barrier.
     656       10328 :     descriptors->Append(desc);
     657       10328 :     SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
     658             :     MarkingBarrierForDescriptorArray(isolate->heap(), *this, descriptors,
     659       10328 :                                      number_of_own_descriptors + 1);
     660             :   }
     661             :   // Properly mark the map if the {desc} is an "interesting symbol".
     662       10328 :   if (desc->GetKey()->IsInterestingSymbol()) {
     663         111 :     set_may_have_interesting_symbols(true);
     664             :   }
     665             :   PropertyDetails details = desc->GetDetails();
     666       10328 :   if (details.location() == kField) {
     667             :     DCHECK_GT(UnusedPropertyFields(), 0);
     668        3219 :     AccountAddedPropertyField();
     669             :   }
     670             : 
     671             : // This function does not support appending double field descriptors and
     672             : // it should never try to (otherwise, layout descriptor must be updated too).
     673             : #ifdef DEBUG
     674             :   DCHECK(details.location() != kField || !details.representation().IsDouble());
     675             : #endif
     676       10328 : }
     677             : 
     678   121226550 : Object Map::GetBackPointer() const {
     679   121226550 :   Object object = constructor_or_backpointer();
     680   121226678 :   if (object->IsMap()) {
     681    69326246 :     return object;
     682             :   }
     683   103800852 :   return GetReadOnlyRoots().undefined_value();
     684             : }
     685             : 
     686     8273601 : Map Map::ElementsTransitionMap() {
     687             :   DisallowHeapAllocation no_gc;
     688             :   // TODO(delphick): While it's safe to pass nullptr for Isolate* here as
     689             :   // SearchSpecial doesn't need it, this is really ugly. Perhaps factor out a
     690             :   // base class for methods not requiring an Isolate?
     691             :   return TransitionsAccessor(nullptr, *this, &no_gc)
     692    16547218 :       .SearchSpecial(GetReadOnlyRoots().elements_transition_symbol());
     693             : }
     694             : 
     695             : Object Map::prototype_info() const {
     696             :   DCHECK(is_prototype_map());
     697    90020009 :   return READ_FIELD(this, Map::kTransitionsOrPrototypeInfoOffset);
     698             : }
     699             : 
     700     9187185 : void Map::set_prototype_info(Object value, WriteBarrierMode mode) {
     701     9187185 :   CHECK(is_prototype_map());
     702     9187185 :   WRITE_FIELD(*this, Map::kTransitionsOrPrototypeInfoOffset, value);
     703    27561553 :   CONDITIONAL_WRITE_BARRIER(*this, Map::kTransitionsOrPrototypeInfoOffset,
     704             :                             value, mode);
     705     9187188 : }
     706             : 
     707     6488294 : void Map::SetBackPointer(Object value, WriteBarrierMode mode) {
     708     6488294 :   CHECK_GE(instance_type(), FIRST_JS_RECEIVER_TYPE);
     709     6488314 :   CHECK(value->IsMap());
     710    12976630 :   CHECK(GetBackPointer()->IsUndefined());
     711    19464958 :   CHECK_IMPLIES(value->IsMap(), Map::cast(value)->GetConstructor() ==
     712             :                                     constructor_or_backpointer());
     713     6488325 :   set_constructor_or_backpointer(value, mode);
     714     6488319 : }
     715             : 
     716   149031773 : ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
     717   216961102 : ACCESSORS(Map, prototype_validity_cell, Object, kPrototypeValidityCellOffset)
     718  2403881069 : ACCESSORS(Map, constructor_or_backpointer, Object,
     719             :           kConstructorOrBackPointerOffset)
     720             : 
     721     1301766 : bool Map::IsPrototypeValidityCellValid() const {
     722     1301766 :   Object validity_cell = prototype_validity_cell();
     723             :   Object value = validity_cell->IsSmi() ? Smi::cast(validity_cell)
     724     2603448 :                                         : Cell::cast(validity_cell)->value();
     725     1301767 :   return value == Smi::FromInt(Map::kPrototypeChainValid);
     726             : }
     727             : 
     728    86210304 : Object Map::GetConstructor() const {
     729    86210304 :   Object maybe_constructor = constructor_or_backpointer();
     730             :   // Follow any back pointers.
     731   649120378 :   while (maybe_constructor->IsMap()) {
     732             :     maybe_constructor =
     733   476699672 :         Map::cast(maybe_constructor)->constructor_or_backpointer();
     734             :   }
     735    86210373 :   return maybe_constructor;
     736             : }
     737             : 
     738     2159969 : FunctionTemplateInfo Map::GetFunctionTemplateInfo() const {
     739     2159969 :   Object constructor = GetConstructor();
     740     2159969 :   if (constructor->IsJSFunction()) {
     741             :     DCHECK(JSFunction::cast(constructor)->shared()->IsApiFunction());
     742     2159969 :     return JSFunction::cast(constructor)->shared()->get_api_func_data();
     743             :   }
     744             :   DCHECK(constructor->IsFunctionTemplateInfo());
     745             :   return FunctionTemplateInfo::cast(constructor);
     746             : }
     747             : 
     748     9999754 : void Map::SetConstructor(Object constructor, WriteBarrierMode mode) {
     749             :   // Never overwrite a back pointer with a constructor.
     750    19999526 :   CHECK(!constructor_or_backpointer()->IsMap());
     751     9999772 :   set_constructor_or_backpointer(constructor, mode);
     752     9999770 : }
     753             : 
     754      449596 : Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map) {
     755             :   return CopyInitialMap(isolate, map, map->instance_size(),
     756             :                         map->GetInObjectProperties(),
     757     1348795 :                         map->UnusedPropertyFields());
     758             : }
     759             : 
     760             : bool Map::IsInobjectSlackTrackingInProgress() const {
     761    23087387 :   return construction_counter() != Map::kNoSlackTracking;
     762             : }
     763             : 
     764      242385 : void Map::InobjectSlackTrackingStep(Isolate* isolate) {
     765             :   // Slack tracking should only be performed on an initial map.
     766             :   DCHECK(GetBackPointer()->IsUndefined());
     767      484769 :   if (!IsInobjectSlackTrackingInProgress()) return;
     768             :   int counter = construction_counter();
     769      242385 :   set_construction_counter(counter - 1);
     770      242383 :   if (counter == kSlackTrackingCounterEnd) {
     771        2191 :     CompleteInobjectSlackTracking(isolate);
     772             :   }
     773             : }
     774             : 
     775     2343798 : int Map::SlackForArraySize(int old_size, int size_limit) {
     776     2343798 :   const int max_slack = size_limit - old_size;
     777     2343798 :   CHECK_LE(0, max_slack);
     778     2343798 :   if (old_size < 4) {
     779             :     DCHECK_LE(1, max_slack);
     780             :     return 1;
     781             :   }
     782     2470480 :   return Min(max_slack, old_size / 4);
     783             : }
     784             : 
     785             : NEVER_READ_ONLY_SPACE_IMPL(NormalizedMapCache)
     786             : 
     787      758848 : int NormalizedMapCache::GetIndex(Handle<Map> map) {
     788      758848 :   return map->Hash() % NormalizedMapCache::kEntries;
     789             : }
     790             : 
     791             : bool NormalizedMapCache::IsNormalizedMapCache(const HeapObject obj) {
     792             :   if (!obj->IsWeakFixedArray()) return false;
     793             :   if (WeakFixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) {
     794             :     return false;
     795             :   }
     796             : #ifdef VERIFY_HEAP
     797             :   if (FLAG_verify_heap) {
     798             :     NormalizedMapCache cache = NormalizedMapCache::cast(obj);
     799             :     cache->NormalizedMapCacheVerify(cache->GetIsolate());
     800             :   }
     801             : #endif
     802             :   return true;
     803             : }
     804             : 
     805             : }  // namespace internal
     806             : }  // namespace v8
     807             : 
     808             : #include "src/objects/object-macros-undef.h"
     809             : 
     810             : #endif  // V8_OBJECTS_MAP_INL_H_

Generated by: LCOV version 1.10