11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_OBJECTS_DESCRIPTOR_ARRAY_H_ 61cb0ef41Sopenharmony_ci#define V8_OBJECTS_DESCRIPTOR_ARRAY_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/common/globals.h" 91cb0ef41Sopenharmony_ci#include "src/objects/fixed-array.h" 101cb0ef41Sopenharmony_ci// TODO(jkummerow): Consider forward-declaring instead. 111cb0ef41Sopenharmony_ci#include "src/base/bit-field.h" 121cb0ef41Sopenharmony_ci#include "src/objects/internal-index.h" 131cb0ef41Sopenharmony_ci#include "src/objects/objects.h" 141cb0ef41Sopenharmony_ci#include "src/objects/struct.h" 151cb0ef41Sopenharmony_ci#include "src/utils/utils.h" 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ci// Has to be the last include (doesn't have include guards): 181cb0ef41Sopenharmony_ci#include "src/objects/object-macros.h" 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_cinamespace v8 { 211cb0ef41Sopenharmony_cinamespace internal { 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_citemplate <typename T> 241cb0ef41Sopenharmony_ciclass Handle; 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ciclass Isolate; 271cb0ef41Sopenharmony_ciclass StructBodyDescriptor; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci#include "torque-generated/src/objects/descriptor-array-tq.inc" 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci// An EnumCache is a pair used to hold keys and indices caches. 321cb0ef41Sopenharmony_ciclass EnumCache : public TorqueGeneratedEnumCache<EnumCache, Struct> { 331cb0ef41Sopenharmony_ci public: 341cb0ef41Sopenharmony_ci DECL_VERIFIER(EnumCache) 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci using BodyDescriptor = StructBodyDescriptor; 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci TQ_OBJECT_CONSTRUCTORS(EnumCache) 391cb0ef41Sopenharmony_ci}; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci// A DescriptorArray is a custom array that holds instance descriptors. 421cb0ef41Sopenharmony_ci// It has the following layout: 431cb0ef41Sopenharmony_ci// Header: 441cb0ef41Sopenharmony_ci// [16:0 bits]: number_of_all_descriptors (including slack) 451cb0ef41Sopenharmony_ci// [32:16 bits]: number_of_descriptors 461cb0ef41Sopenharmony_ci// [48:32 bits]: raw_number_of_marked_descriptors (used by GC) 471cb0ef41Sopenharmony_ci// [64:48 bits]: alignment filler 481cb0ef41Sopenharmony_ci// [kEnumCacheOffset]: enum cache 491cb0ef41Sopenharmony_ci// Elements: 501cb0ef41Sopenharmony_ci// [kHeaderSize + 0]: first key (and internalized String) 511cb0ef41Sopenharmony_ci// [kHeaderSize + 1]: first descriptor details (see PropertyDetails) 521cb0ef41Sopenharmony_ci// [kHeaderSize + 2]: first value for constants / Smi(1) when not used 531cb0ef41Sopenharmony_ci// Slack: 541cb0ef41Sopenharmony_ci// [kHeaderSize + number of descriptors * 3]: start of slack 551cb0ef41Sopenharmony_ci// The "value" fields store either values or field types. A field type is either 561cb0ef41Sopenharmony_ci// FieldType::None(), FieldType::Any() or a weak reference to a Map. All other 571cb0ef41Sopenharmony_ci// references are strong. 581cb0ef41Sopenharmony_ciclass DescriptorArray 591cb0ef41Sopenharmony_ci : public TorqueGeneratedDescriptorArray<DescriptorArray, HeapObject> { 601cb0ef41Sopenharmony_ci public: 611cb0ef41Sopenharmony_ci DECL_INT16_ACCESSORS(number_of_all_descriptors) 621cb0ef41Sopenharmony_ci DECL_INT16_ACCESSORS(number_of_descriptors) 631cb0ef41Sopenharmony_ci inline int16_t number_of_slack_descriptors() const; 641cb0ef41Sopenharmony_ci inline int number_of_entries() const; 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci void ClearEnumCache(); 671cb0ef41Sopenharmony_ci inline void CopyEnumCacheFrom(DescriptorArray array); 681cb0ef41Sopenharmony_ci static void InitializeOrChangeEnumCache(Handle<DescriptorArray> descriptors, 691cb0ef41Sopenharmony_ci Isolate* isolate, 701cb0ef41Sopenharmony_ci Handle<FixedArray> keys, 711cb0ef41Sopenharmony_ci Handle<FixedArray> indices); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci // Accessors for fetching instance descriptor at descriptor number. 741cb0ef41Sopenharmony_ci inline Name GetKey(InternalIndex descriptor_number) const; 751cb0ef41Sopenharmony_ci inline Name GetKey(PtrComprCageBase cage_base, 761cb0ef41Sopenharmony_ci InternalIndex descriptor_number) const; 771cb0ef41Sopenharmony_ci inline Object GetStrongValue(InternalIndex descriptor_number); 781cb0ef41Sopenharmony_ci inline Object GetStrongValue(PtrComprCageBase cage_base, 791cb0ef41Sopenharmony_ci InternalIndex descriptor_number); 801cb0ef41Sopenharmony_ci inline MaybeObject GetValue(InternalIndex descriptor_number); 811cb0ef41Sopenharmony_ci inline MaybeObject GetValue(PtrComprCageBase cage_base, 821cb0ef41Sopenharmony_ci InternalIndex descriptor_number); 831cb0ef41Sopenharmony_ci inline PropertyDetails GetDetails(InternalIndex descriptor_number); 841cb0ef41Sopenharmony_ci inline int GetFieldIndex(InternalIndex descriptor_number); 851cb0ef41Sopenharmony_ci inline FieldType GetFieldType(InternalIndex descriptor_number); 861cb0ef41Sopenharmony_ci inline FieldType GetFieldType(PtrComprCageBase cage_base, 871cb0ef41Sopenharmony_ci InternalIndex descriptor_number); 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci inline Name GetSortedKey(int descriptor_number); 901cb0ef41Sopenharmony_ci inline Name GetSortedKey(PtrComprCageBase cage_base, int descriptor_number); 911cb0ef41Sopenharmony_ci inline int GetSortedKeyIndex(int descriptor_number); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci // Accessor for complete descriptor. 941cb0ef41Sopenharmony_ci inline void Set(InternalIndex descriptor_number, Descriptor* desc); 951cb0ef41Sopenharmony_ci inline void Set(InternalIndex descriptor_number, Name key, MaybeObject value, 961cb0ef41Sopenharmony_ci PropertyDetails details); 971cb0ef41Sopenharmony_ci void Replace(InternalIndex descriptor_number, Descriptor* descriptor); 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci // Generalizes constness, representation and field type of all field 1001cb0ef41Sopenharmony_ci // descriptors. 1011cb0ef41Sopenharmony_ci void GeneralizeAllFields(); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci // Append automatically sets the enumeration index. This should only be used 1041cb0ef41Sopenharmony_ci // to add descriptors in bulk at the end, followed by sorting the descriptor 1051cb0ef41Sopenharmony_ci // array. 1061cb0ef41Sopenharmony_ci inline void Append(Descriptor* desc); 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci static Handle<DescriptorArray> CopyUpTo(Isolate* isolate, 1091cb0ef41Sopenharmony_ci Handle<DescriptorArray> desc, 1101cb0ef41Sopenharmony_ci int enumeration_index, int slack = 0); 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci static Handle<DescriptorArray> CopyUpToAddAttributes( 1131cb0ef41Sopenharmony_ci Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index, 1141cb0ef41Sopenharmony_ci PropertyAttributes attributes, int slack = 0); 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci static Handle<DescriptorArray> CopyForFastObjectClone( 1171cb0ef41Sopenharmony_ci Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index, 1181cb0ef41Sopenharmony_ci int slack = 0); 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci // Sort the instance descriptors by the hash codes of their keys. 1211cb0ef41Sopenharmony_ci V8_EXPORT_PRIVATE void Sort(); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci // Search the instance descriptors for given name. {concurrent_search} signals 1241cb0ef41Sopenharmony_ci // if we are doing the search on a background thread. If so, we will sacrifice 1251cb0ef41Sopenharmony_ci // speed for thread-safety. 1261cb0ef41Sopenharmony_ci V8_INLINE InternalIndex Search(Name name, int number_of_own_descriptors, 1271cb0ef41Sopenharmony_ci bool concurrent_search = false); 1281cb0ef41Sopenharmony_ci V8_INLINE InternalIndex Search(Name name, Map map, 1291cb0ef41Sopenharmony_ci bool concurrent_search = false); 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci // As the above, but uses DescriptorLookupCache and updates it when 1321cb0ef41Sopenharmony_ci // necessary. 1331cb0ef41Sopenharmony_ci V8_INLINE InternalIndex SearchWithCache(Isolate* isolate, Name name, Map map); 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci bool IsEqualUpTo(DescriptorArray desc, int nof_descriptors); 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci // Allocates a DescriptorArray, but returns the singleton 1381cb0ef41Sopenharmony_ci // empty descriptor array object if number_of_descriptors is 0. 1391cb0ef41Sopenharmony_ci template <typename IsolateT> 1401cb0ef41Sopenharmony_ci V8_EXPORT_PRIVATE static Handle<DescriptorArray> Allocate( 1411cb0ef41Sopenharmony_ci IsolateT* isolate, int nof_descriptors, int slack, 1421cb0ef41Sopenharmony_ci AllocationType allocation = AllocationType::kYoung); 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci void Initialize(EnumCache enum_cache, HeapObject undefined_value, 1451cb0ef41Sopenharmony_ci int nof_descriptors, int slack); 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci // Constant for denoting key was not found. 1481cb0ef41Sopenharmony_ci static const int kNotFound = -1; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci STATIC_ASSERT(IsAligned(kStartOfWeakFieldsOffset, kTaggedSize)); 1511cb0ef41Sopenharmony_ci STATIC_ASSERT(IsAligned(kHeaderSize, kTaggedSize)); 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci // Garbage collection support. 1541cb0ef41Sopenharmony_ci DECL_INT16_ACCESSORS(raw_number_of_marked_descriptors) 1551cb0ef41Sopenharmony_ci // Atomic compare-and-swap operation on the raw_number_of_marked_descriptors. 1561cb0ef41Sopenharmony_ci int16_t CompareAndSwapRawNumberOfMarkedDescriptors(int16_t expected, 1571cb0ef41Sopenharmony_ci int16_t value); 1581cb0ef41Sopenharmony_ci int16_t UpdateNumberOfMarkedDescriptors(unsigned mark_compact_epoch, 1591cb0ef41Sopenharmony_ci int16_t number_of_marked_descriptors); 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci static constexpr int SizeFor(int number_of_all_descriptors) { 1621cb0ef41Sopenharmony_ci return OffsetOfDescriptorAt(number_of_all_descriptors); 1631cb0ef41Sopenharmony_ci } 1641cb0ef41Sopenharmony_ci static constexpr int OffsetOfDescriptorAt(int descriptor) { 1651cb0ef41Sopenharmony_ci return kDescriptorsOffset + descriptor * kEntrySize * kTaggedSize; 1661cb0ef41Sopenharmony_ci } 1671cb0ef41Sopenharmony_ci inline ObjectSlot GetFirstPointerSlot(); 1681cb0ef41Sopenharmony_ci inline ObjectSlot GetDescriptorSlot(int descriptor); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci static_assert(kEndOfStrongFieldsOffset == kStartOfWeakFieldsOffset, 1711cb0ef41Sopenharmony_ci "Weak fields follow strong fields."); 1721cb0ef41Sopenharmony_ci static_assert(kEndOfWeakFieldsOffset == kHeaderSize, 1731cb0ef41Sopenharmony_ci "Weak fields extend up to the end of the header."); 1741cb0ef41Sopenharmony_ci static_assert(kDescriptorsOffset == kHeaderSize, 1751cb0ef41Sopenharmony_ci "Variable-size array follows header."); 1761cb0ef41Sopenharmony_ci class BodyDescriptor; 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci // Layout of descriptor. 1791cb0ef41Sopenharmony_ci // Naming is consistent with Dictionary classes for easy templating. 1801cb0ef41Sopenharmony_ci static const int kEntryKeyIndex = 0; 1811cb0ef41Sopenharmony_ci static const int kEntryDetailsIndex = 1; 1821cb0ef41Sopenharmony_ci static const int kEntryValueIndex = 2; 1831cb0ef41Sopenharmony_ci static const int kEntrySize = 3; 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci static const int kEntryKeyOffset = kEntryKeyIndex * kTaggedSize; 1861cb0ef41Sopenharmony_ci static const int kEntryDetailsOffset = kEntryDetailsIndex * kTaggedSize; 1871cb0ef41Sopenharmony_ci static const int kEntryValueOffset = kEntryValueIndex * kTaggedSize; 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci // Print all the descriptors. 1901cb0ef41Sopenharmony_ci void PrintDescriptors(std::ostream& os); 1911cb0ef41Sopenharmony_ci void PrintDescriptorDetails(std::ostream& os, InternalIndex descriptor, 1921cb0ef41Sopenharmony_ci PropertyDetails::PrintMode mode); 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci DECL_PRINTER(DescriptorArray) 1951cb0ef41Sopenharmony_ci DECL_VERIFIER(DescriptorArray) 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci#ifdef DEBUG 1981cb0ef41Sopenharmony_ci // Is the descriptor array sorted and without duplicates? 1991cb0ef41Sopenharmony_ci V8_EXPORT_PRIVATE bool IsSortedNoDuplicates(); 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci // Are two DescriptorArrays equal? 2021cb0ef41Sopenharmony_ci bool IsEqualTo(DescriptorArray other); 2031cb0ef41Sopenharmony_ci#endif 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci static constexpr int ToDetailsIndex(int descriptor_number) { 2061cb0ef41Sopenharmony_ci return (descriptor_number * kEntrySize) + kEntryDetailsIndex; 2071cb0ef41Sopenharmony_ci } 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci // Conversion from descriptor number to array indices. 2101cb0ef41Sopenharmony_ci static constexpr int ToKeyIndex(int descriptor_number) { 2111cb0ef41Sopenharmony_ci return (descriptor_number * kEntrySize) + kEntryKeyIndex; 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci static constexpr int ToValueIndex(int descriptor_number) { 2151cb0ef41Sopenharmony_ci return (descriptor_number * kEntrySize) + kEntryValueIndex; 2161cb0ef41Sopenharmony_ci } 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci using EntryKeyField = TaggedField<HeapObject, kEntryKeyOffset>; 2191cb0ef41Sopenharmony_ci using EntryDetailsField = TaggedField<Smi, kEntryDetailsOffset>; 2201cb0ef41Sopenharmony_ci using EntryValueField = TaggedField<MaybeObject, kEntryValueOffset>; 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci private: 2231cb0ef41Sopenharmony_ci friend class WebSnapshotDeserializer; 2241cb0ef41Sopenharmony_ci DECL_INT16_ACCESSORS(filler16bits) 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci inline void SetKey(InternalIndex descriptor_number, Name key); 2271cb0ef41Sopenharmony_ci inline void SetValue(InternalIndex descriptor_number, MaybeObject value); 2281cb0ef41Sopenharmony_ci inline void SetDetails(InternalIndex descriptor_number, 2291cb0ef41Sopenharmony_ci PropertyDetails details); 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci // Transfer a complete descriptor from the src descriptor array to this 2321cb0ef41Sopenharmony_ci // descriptor array. 2331cb0ef41Sopenharmony_ci void CopyFrom(InternalIndex index, DescriptorArray src); 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci inline void SetSortedKey(int pointer, int descriptor_number); 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci // Swap first and second descriptor. 2381cb0ef41Sopenharmony_ci inline void SwapSortedKeys(int first, int second); 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ci TQ_OBJECT_CONSTRUCTORS(DescriptorArray) 2411cb0ef41Sopenharmony_ci}; 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ciclass NumberOfMarkedDescriptors { 2441cb0ef41Sopenharmony_ci public: 2451cb0ef41Sopenharmony_ci// Bit positions for |bit_field|. 2461cb0ef41Sopenharmony_ci#define BIT_FIELD_FIELDS(V, _) \ 2471cb0ef41Sopenharmony_ci V(Epoch, unsigned, 2, _) \ 2481cb0ef41Sopenharmony_ci V(Marked, int16_t, 14, _) 2491cb0ef41Sopenharmony_ci DEFINE_BIT_FIELDS(BIT_FIELD_FIELDS) 2501cb0ef41Sopenharmony_ci#undef BIT_FIELD_FIELDS 2511cb0ef41Sopenharmony_ci static const int kMaxNumberOfMarkedDescriptors = Marked::kMax; 2521cb0ef41Sopenharmony_ci // Decodes the raw value of the number of marked descriptors for the 2531cb0ef41Sopenharmony_ci // given mark compact garbage collection epoch. 2541cb0ef41Sopenharmony_ci static inline int16_t decode(unsigned mark_compact_epoch, int16_t raw_value) { 2551cb0ef41Sopenharmony_ci unsigned epoch_from_value = Epoch::decode(static_cast<uint16_t>(raw_value)); 2561cb0ef41Sopenharmony_ci int16_t marked_from_value = 2571cb0ef41Sopenharmony_ci Marked::decode(static_cast<uint16_t>(raw_value)); 2581cb0ef41Sopenharmony_ci unsigned actual_epoch = mark_compact_epoch & Epoch::kMask; 2591cb0ef41Sopenharmony_ci if (actual_epoch == epoch_from_value) return marked_from_value; 2601cb0ef41Sopenharmony_ci // If the epochs do not match, then either the raw_value is zero (freshly 2611cb0ef41Sopenharmony_ci // allocated descriptor array) or the epoch from value lags by 1. 2621cb0ef41Sopenharmony_ci DCHECK_IMPLIES(raw_value != 0, 2631cb0ef41Sopenharmony_ci Epoch::decode(epoch_from_value + 1) == actual_epoch); 2641cb0ef41Sopenharmony_ci // Not matching epochs means that the no descriptors were marked in the 2651cb0ef41Sopenharmony_ci // current epoch. 2661cb0ef41Sopenharmony_ci return 0; 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_ci // Encodes the number of marked descriptors for the given mark compact 2701cb0ef41Sopenharmony_ci // garbage collection epoch. 2711cb0ef41Sopenharmony_ci static inline int16_t encode(unsigned mark_compact_epoch, int16_t value) { 2721cb0ef41Sopenharmony_ci // TODO(ulan): avoid casting to int16_t by adding support for uint16_t 2731cb0ef41Sopenharmony_ci // atomics. 2741cb0ef41Sopenharmony_ci return static_cast<int16_t>( 2751cb0ef41Sopenharmony_ci Epoch::encode(mark_compact_epoch & Epoch::kMask) | 2761cb0ef41Sopenharmony_ci Marked::encode(value)); 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci}; 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci} // namespace internal 2811cb0ef41Sopenharmony_ci} // namespace v8 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci#include "src/objects/object-macros-undef.h" 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci#endif // V8_OBJECTS_DESCRIPTOR_ARRAY_H_ 286