diff options
Diffstat (limited to 'deps/v8/src/objects/descriptor-array.h')
-rw-r--r-- | deps/v8/src/objects/descriptor-array.h | 192 |
1 files changed, 129 insertions, 63 deletions
diff --git a/deps/v8/src/objects/descriptor-array.h b/deps/v8/src/objects/descriptor-array.h index c24deb68ad..3e67e94bf1 100644 --- a/deps/v8/src/objects/descriptor-array.h +++ b/deps/v8/src/objects/descriptor-array.h @@ -7,6 +7,8 @@ #include "src/objects.h" #include "src/objects/fixed-array.h" +#include "src/objects/struct.h" +#include "src/utils.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -31,62 +33,57 @@ class EnumCache : public Tuple2 { static const int kKeysOffset = kValue1Offset; static const int kIndicesOffset = kValue2Offset; - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(EnumCache); + OBJECT_CONSTRUCTORS(EnumCache, Tuple2); }; -// A DescriptorArray is a fixed array used to hold instance descriptors. -// The format of these objects is: -// [0]: Number of descriptors -// [1]: Enum cache. -// [2]: first key (and internalized String) -// [3]: first descriptor details (see PropertyDetails) -// [4]: first value for constants | Smi(1) when not used -// -// [2 + number of descriptors * 3]: start of slack +// A DescriptorArray is a custom array that holds instance descriptors. +// It has the following layout: +// Header: +// [16:0 bits]: number_of_all_descriptors (including slack) +// [32:16 bits]: number_of_descriptors +// [48:32 bits]: raw_number_of_marked_descriptors (used by GC) +// [64:48 bits]: alignment filler +// [kEnumCacheOffset]: enum cache +// Elements: +// [kHeaderSize + 0]: first key (and internalized String) +// [kHeaderSize + 1]: first descriptor details (see PropertyDetails) +// [kHeaderSize + 2]: first value for constants / Smi(1) when not used +// Slack: +// [kHeaderSize + number of descriptors * 3]: start of slack // The "value" fields store either values or field types. A field type is either // FieldType::None(), FieldType::Any() or a weak reference to a Map. All other // references are strong. -class DescriptorArray : public WeakFixedArray { +class DescriptorArray : public HeapObject { public: - // Returns the number of descriptors in the array. - inline int number_of_descriptors() const; - inline int number_of_descriptors_storage() const; - inline int NumberOfSlackDescriptors() const; - - inline void SetNumberOfDescriptors(int number_of_descriptors); + DECL_INT16_ACCESSORS(number_of_all_descriptors) + DECL_INT16_ACCESSORS(number_of_descriptors) + inline int16_t number_of_slack_descriptors() const; inline int number_of_entries() const; - - inline EnumCache* GetEnumCache(); + DECL_ACCESSORS(enum_cache, EnumCache) void ClearEnumCache(); - inline void CopyEnumCacheFrom(DescriptorArray* array); - // Initialize or change the enum cache, - static void SetEnumCache(Handle<DescriptorArray> descriptors, - Isolate* isolate, Handle<FixedArray> keys, - Handle<FixedArray> indices); + inline void CopyEnumCacheFrom(DescriptorArray array); + static void InitializeOrChangeEnumCache(Handle<DescriptorArray> descriptors, + Isolate* isolate, + Handle<FixedArray> keys, + Handle<FixedArray> indices); // Accessors for fetching instance descriptor at descriptor number. - inline Name* GetKey(int descriptor_number); - inline Object** GetKeySlot(int descriptor_number); - inline Object* GetStrongValue(int descriptor_number); - inline void SetValue(int descriptor_number, Object* value); - inline MaybeObject* GetValue(int descriptor_number); - inline MaybeObject** GetValueSlot(int descriptor_number); - static inline int GetValueOffset(int descriptor_number); - inline MaybeObject** GetDescriptorStartSlot(int descriptor_number); - inline MaybeObject** GetDescriptorEndSlot(int descriptor_number); + inline Name GetKey(int descriptor_number) const; + inline Object GetStrongValue(int descriptor_number); + inline void SetValue(int descriptor_number, Object value); + inline MaybeObject GetValue(int descriptor_number); inline PropertyDetails GetDetails(int descriptor_number); inline int GetFieldIndex(int descriptor_number); - inline FieldType* GetFieldType(int descriptor_number); + inline FieldType GetFieldType(int descriptor_number); - inline Name* GetSortedKey(int descriptor_number); + inline Name GetSortedKey(int descriptor_number); inline int GetSortedKeyIndex(int descriptor_number); inline void SetSortedKey(int pointer, int descriptor_number); // Accessor for complete descriptor. inline void Set(int descriptor_number, Descriptor* desc); - inline void Set(int descriptor_number, Name* key, MaybeObject* value, + inline void Set(int descriptor_number, Name key, MaybeObject value, PropertyDetails details); void Replace(int descriptor_number, Descriptor* descriptor); @@ -115,34 +112,66 @@ class DescriptorArray : public WeakFixedArray { void Sort(); // Search the instance descriptors for given name. - V8_INLINE int Search(Name* name, int number_of_own_descriptors); - V8_INLINE int Search(Name* name, Map* map); + V8_INLINE int Search(Name name, int number_of_own_descriptors); + V8_INLINE int Search(Name name, Map map); // As the above, but uses DescriptorLookupCache and updates it when // necessary. - V8_INLINE int SearchWithCache(Isolate* isolate, Name* name, Map* map); + V8_INLINE int SearchWithCache(Isolate* isolate, Name name, Map map); - bool IsEqualUpTo(DescriptorArray* desc, int nof_descriptors); + bool IsEqualUpTo(DescriptorArray desc, int nof_descriptors); // Allocates a DescriptorArray, but returns the singleton // empty descriptor array object if number_of_descriptors is 0. static Handle<DescriptorArray> Allocate( - Isolate* isolate, int number_of_descriptors, int slack, + Isolate* isolate, int nof_descriptors, int slack, PretenureFlag pretenure = NOT_TENURED); + void Initialize(EnumCache enum_cache, HeapObject undefined_value, + int nof_descriptors, int slack); + DECL_CAST(DescriptorArray) // Constant for denoting key was not found. static const int kNotFound = -1; - static const int kDescriptorLengthIndex = 0; - static const int kEnumCacheIndex = 1; - static const int kFirstIndex = 2; - // Layout description. - static const int kDescriptorLengthOffset = FixedArray::kHeaderSize; - static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize; - static const int kFirstOffset = kEnumCacheOffset + kPointerSize; +#define DESCRIPTOR_ARRAY_FIELDS(V) \ + V(kNumberOfAllDescriptorsOffset, kUInt16Size) \ + V(kNumberOfDescriptorsOffset, kUInt16Size) \ + V(kRawNumberOfMarkedDescriptorsOffset, kUInt16Size) \ + V(kFiller16BitsOffset, kUInt16Size) \ + V(kPointersStartOffset, 0) \ + V(kEnumCacheOffset, kTaggedSize) \ + V(kHeaderSize, 0) + + DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, + DESCRIPTOR_ARRAY_FIELDS) +#undef DESCRIPTOR_ARRAY_FIELDS + + STATIC_ASSERT(IsAligned(kPointersStartOffset, kTaggedSize)); + STATIC_ASSERT(IsAligned(kHeaderSize, kTaggedSize)); + + // Garbage collection support. + DECL_INT16_ACCESSORS(raw_number_of_marked_descriptors) + // Atomic compare-and-swap operation on the raw_number_of_marked_descriptors. + int16_t CompareAndSwapRawNumberOfMarkedDescriptors(int16_t expected, + int16_t value); + int16_t UpdateNumberOfMarkedDescriptors(unsigned mark_compact_epoch, + int16_t number_of_marked_descriptors); + + static constexpr int SizeFor(int number_of_all_descriptors) { + return offset(number_of_all_descriptors * kEntrySize); + } + static constexpr int OffsetOfDescriptorAt(int descriptor) { + return offset(descriptor * kEntrySize); + } + inline ObjectSlot GetFirstPointerSlot(); + inline ObjectSlot GetDescriptorSlot(int descriptor); + inline ObjectSlot GetKeySlot(int descriptor); + inline MaybeObjectSlot GetValueSlot(int descriptor); + + typedef FlexibleWeakBodyDescriptor<kPointersStartOffset> BodyDescriptor; // Layout of descriptor. // Naming is consistent with Dictionary classes for easy templating. @@ -164,40 +193,77 @@ class DescriptorArray : public WeakFixedArray { bool IsSortedNoDuplicates(int valid_descriptors = -1); // Are two DescriptorArrays equal? - bool IsEqualTo(DescriptorArray* other); + bool IsEqualTo(DescriptorArray other); #endif - // Returns the fixed array length required to hold number_of_descriptors - // descriptors. - static constexpr int LengthFor(int number_of_descriptors) { - return ToKeyIndex(number_of_descriptors); - } - static constexpr int ToDetailsIndex(int descriptor_number) { - return kFirstIndex + (descriptor_number * kEntrySize) + kEntryDetailsIndex; + return (descriptor_number * kEntrySize) + kEntryDetailsIndex; } // Conversion from descriptor number to array indices. static constexpr int ToKeyIndex(int descriptor_number) { - return kFirstIndex + (descriptor_number * kEntrySize) + kEntryKeyIndex; + return (descriptor_number * kEntrySize) + kEntryKeyIndex; } static constexpr int ToValueIndex(int descriptor_number) { - return kFirstIndex + (descriptor_number * kEntrySize) + kEntryValueIndex; + return (descriptor_number * kEntrySize) + kEntryValueIndex; } private: - inline MaybeObject* get(int index) const; - inline void set(int index, MaybeObject* value); + DECL_INT16_ACCESSORS(filler16bits) + // Low-level per-element accessors. + static constexpr int offset(int index) { + return kHeaderSize + index * kTaggedSize; + } + inline int length() const; + inline MaybeObject get(int index) const; + inline void set(int index, MaybeObject value); // Transfer a complete descriptor from the src descriptor array to this // descriptor array. - void CopyFrom(int index, DescriptorArray* src); + void CopyFrom(int index, DescriptorArray src); // Swap first and second descriptor. inline void SwapSortedKeys(int first, int second); - DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray); + OBJECT_CONSTRUCTORS(DescriptorArray, HeapObject); +}; + +class NumberOfMarkedDescriptors { + public: +// Bit positions for |bit_field|. +#define BIT_FIELD_FIELDS(V, _) \ + V(Epoch, unsigned, 2, _) \ + V(Marked, int16_t, 14, _) + DEFINE_BIT_FIELDS(BIT_FIELD_FIELDS) +#undef BIT_FIELD_FIELDS + static const int kMaxNumberOfMarkedDescriptors = Marked::kMax; + // Decodes the raw value of the number of marked descriptors for the + // given mark compact garbage collection epoch. + static inline int16_t decode(unsigned mark_compact_epoch, int16_t raw_value) { + unsigned epoch_from_value = Epoch::decode(static_cast<uint16_t>(raw_value)); + int16_t marked_from_value = + Marked::decode(static_cast<uint16_t>(raw_value)); + unsigned actual_epoch = mark_compact_epoch & Epoch::kMask; + if (actual_epoch == epoch_from_value) return marked_from_value; + // If the epochs do not match, then either the raw_value is zero (freshly + // allocated descriptor array) or the epoch from value lags by 1. + DCHECK_IMPLIES(raw_value != 0, + Epoch::decode(epoch_from_value + 1) == actual_epoch); + // Not matching epochs means that the no descriptors were marked in the + // current epoch. + return 0; + } + + // Encodes the number of marked descriptors for the given mark compact + // garbage collection epoch. + static inline int16_t encode(unsigned mark_compact_epoch, int16_t value) { + // TODO(ulan): avoid casting to int16_t by adding support for uint16_t + // atomics. + return static_cast<int16_t>( + Epoch::encode(mark_compact_epoch & Epoch::kMask) | + Marked::encode(value)); + } }; } // namespace internal |