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