[in-place weak refs] Add WeakFixedArray (an array of in-place weak references).
Not used yet apart from tests. BUG=v8:7308 Change-Id: Ibbe12597007cba123236c9fab85c524df3d5dd4a Reviewed-on: https://chromium-review.googlesource.com/955427 Commit-Queue: Marja Hölttä <marja@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Hannes Payer <hpayer@chromium.org> Cr-Commit-Position: refs/heads/master@{#51876}
This commit is contained in:
parent
8f1cdc722b
commit
b0dc290a9a
@ -264,6 +264,7 @@ Type::bitset BitsetType::Lub(i::Map* map) {
|
||||
case ACCESSOR_PAIR_TYPE:
|
||||
case FIXED_ARRAY_TYPE:
|
||||
case HASH_TABLE_TYPE:
|
||||
case WEAK_FIXED_ARRAY_TYPE:
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
case FEEDBACK_METADATA_TYPE:
|
||||
case BYTE_ARRAY_TYPE:
|
||||
|
@ -203,6 +203,16 @@ Handle<FixedArray> Factory::NewFixedArray(int length, PretenureFlag pretenure) {
|
||||
FixedArray);
|
||||
}
|
||||
|
||||
Handle<WeakFixedArray> Factory::NewWeakFixedArray(int length,
|
||||
PretenureFlag pretenure) {
|
||||
DCHECK_LE(0, length);
|
||||
if (length == 0) return empty_weak_fixed_array();
|
||||
|
||||
CALL_HEAP_FUNCTION(
|
||||
isolate(), isolate()->heap()->AllocateWeakFixedArray(length, pretenure),
|
||||
WeakFixedArray);
|
||||
}
|
||||
|
||||
MaybeHandle<FixedArray> Factory::TryNewFixedArray(int length,
|
||||
PretenureFlag pretenure) {
|
||||
DCHECK_LE(0, length);
|
||||
|
@ -96,6 +96,12 @@ class V8_EXPORT_PRIVATE Factory final {
|
||||
// Allocates a fixed array initialized with undefined values.
|
||||
Handle<FixedArray> NewFixedArray(int length,
|
||||
PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
// Allocates a fixed array which may contain in-place weak references. The
|
||||
// array is initialized with undefined values
|
||||
Handle<WeakFixedArray> NewWeakFixedArray(
|
||||
int length, PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
Handle<PropertyArray> NewPropertyArray(int length,
|
||||
PretenureFlag pretenure = NOT_TENURED);
|
||||
// Tries allocating a fixed array initialized with undefined values.
|
||||
|
@ -247,6 +247,42 @@ AllocationResult Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
|
||||
pretenure, undefined_value());
|
||||
}
|
||||
|
||||
AllocationResult Heap::AllocateWeakFixedArray(int length,
|
||||
PretenureFlag pretenure) {
|
||||
// Zero-length case must be handled outside, where the knowledge about
|
||||
// the map is.
|
||||
DCHECK_LT(0, length);
|
||||
HeapObject* result = nullptr;
|
||||
{
|
||||
AllocationResult allocation = AllocateRawWeakFixedArray(length, pretenure);
|
||||
if (!allocation.To(&result)) return allocation;
|
||||
}
|
||||
DCHECK(RootIsImmortalImmovable(Heap::kWeakFixedArrayMapRootIndex));
|
||||
Map* map = Map::cast(root(Heap::kWeakFixedArrayMapRootIndex));
|
||||
result->set_map_after_allocation(map, SKIP_WRITE_BARRIER);
|
||||
WeakFixedArray* array = WeakFixedArray::cast(result);
|
||||
array->set_length(length);
|
||||
MemsetPointer(array->data_start(),
|
||||
HeapObjectReference::Strong(undefined_value()), length);
|
||||
return array;
|
||||
}
|
||||
|
||||
AllocationResult Heap::AllocateRawFixedArray(int length,
|
||||
PretenureFlag pretenure) {
|
||||
if (length < 0 || length > FixedArray::kMaxLength) {
|
||||
v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
|
||||
}
|
||||
return AllocateRawArray(FixedArray::SizeFor(length), pretenure);
|
||||
}
|
||||
|
||||
AllocationResult Heap::AllocateRawWeakFixedArray(int length,
|
||||
PretenureFlag pretenure) {
|
||||
if (length < 0 || length > WeakFixedArray::kMaxLength) {
|
||||
v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
|
||||
}
|
||||
return AllocateRawArray(WeakFixedArray::SizeFor(length), pretenure);
|
||||
}
|
||||
|
||||
AllocationResult Heap::AllocateRaw(int size_in_bytes, AllocationSpace space,
|
||||
AllocationAlignment alignment) {
|
||||
DCHECK(AllowHandleAllocation::IsAllowed());
|
||||
|
@ -3763,6 +3763,18 @@ AllocationResult Heap::AllocateEmptyFixedArray() {
|
||||
return result;
|
||||
}
|
||||
|
||||
AllocationResult Heap::AllocateEmptyWeakFixedArray() {
|
||||
int size = WeakFixedArray::SizeFor(0);
|
||||
HeapObject* result = nullptr;
|
||||
{
|
||||
AllocationResult allocation = AllocateRaw(size, OLD_SPACE);
|
||||
if (!allocation.To(&result)) return allocation;
|
||||
}
|
||||
result->set_map_after_allocation(weak_fixed_array_map(), SKIP_WRITE_BARRIER);
|
||||
WeakFixedArray::cast(result)->set_length(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
AllocationResult Heap::AllocateEmptyScopeInfo() {
|
||||
int size = FixedArray::SizeFor(0);
|
||||
HeapObject* result = nullptr;
|
||||
@ -3975,12 +3987,7 @@ AllocationResult Heap::CopyFeedbackVector(FeedbackVector* src) {
|
||||
return result;
|
||||
}
|
||||
|
||||
AllocationResult Heap::AllocateRawFixedArray(int length,
|
||||
PretenureFlag pretenure) {
|
||||
if (length < 0 || length > FixedArray::kMaxLength) {
|
||||
v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
|
||||
}
|
||||
int size = FixedArray::SizeFor(length);
|
||||
AllocationResult Heap::AllocateRawArray(int size, PretenureFlag pretenure) {
|
||||
AllocationSpace space = SelectSpace(pretenure);
|
||||
|
||||
AllocationResult result = AllocateRaw(size, space);
|
||||
|
@ -133,6 +133,7 @@ using v8::MemoryPressureLevel;
|
||||
V(Map, small_ordered_hash_map_map, SmallOrderedHashMapMap) \
|
||||
V(Map, small_ordered_hash_set_map, SmallOrderedHashSetMap) \
|
||||
V(Map, string_table_map, StringTableMap) \
|
||||
V(Map, weak_fixed_array_map, WeakFixedArrayMap) \
|
||||
V(Map, weak_hash_table_map, WeakHashTableMap) \
|
||||
/* String maps */ \
|
||||
V(Map, native_source_string_map, NativeSourceStringMap) \
|
||||
@ -217,6 +218,7 @@ using v8::MemoryPressureLevel;
|
||||
V(WeakCell, empty_weak_cell, EmptyWeakCell) \
|
||||
V(Cell, invalid_prototype_validity_cell, InvalidPrototypeValidityCell) \
|
||||
V(InterceptorInfo, noop_interceptor_info, NoOpInterceptorInfo) \
|
||||
V(WeakFixedArray, empty_weak_fixed_array, EmptyWeakFixedArray) \
|
||||
/* Protectors */ \
|
||||
V(Cell, array_constructor_protector, ArrayConstructorProtector) \
|
||||
V(PropertyCell, no_elements_protector, NoElementsProtector) \
|
||||
@ -403,6 +405,7 @@ using v8::MemoryPressureLevel;
|
||||
V(UninitializedMap) \
|
||||
V(UninitializedValue) \
|
||||
V(WeakCellMap) \
|
||||
V(WeakFixedArrayMap) \
|
||||
V(WeakHashTableMap) \
|
||||
V(WithContextMap) \
|
||||
V(empty_string) \
|
||||
@ -2159,6 +2162,19 @@ class Heap {
|
||||
MUST_USE_RESULT inline AllocationResult AllocateFixedArray(
|
||||
int length, PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
// Allocates an array allowing in-place weak references, initialized with
|
||||
// undefined values
|
||||
MUST_USE_RESULT inline AllocationResult AllocateWeakFixedArray(
|
||||
int length, PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
// Allocate memory for an uninitialized FixedArray.
|
||||
MUST_USE_RESULT inline AllocationResult AllocateRawFixedArray(
|
||||
int length, PretenureFlag pretenure);
|
||||
|
||||
// Allocate memory for an uninitialized WeakFixedArray.
|
||||
MUST_USE_RESULT inline AllocationResult AllocateRawWeakFixedArray(
|
||||
int length, PretenureFlag pretenure);
|
||||
|
||||
// Allocates a property array initialized with undefined values
|
||||
MUST_USE_RESULT AllocationResult
|
||||
AllocatePropertyArray(int length, PretenureFlag pretenure = NOT_TENURED);
|
||||
@ -2199,9 +2215,9 @@ class Heap {
|
||||
MUST_USE_RESULT AllocationResult
|
||||
AllocateFillerObject(int size, bool double_align, AllocationSpace space);
|
||||
|
||||
// Allocate an uninitialized fixed array.
|
||||
MUST_USE_RESULT AllocationResult
|
||||
AllocateRawFixedArray(int length, PretenureFlag pretenure);
|
||||
// Allocate memory for an uninitialized array (e.g., a FixedArray or similar).
|
||||
MUST_USE_RESULT AllocationResult AllocateRawArray(int size,
|
||||
PretenureFlag pretenure);
|
||||
|
||||
// Allocate an uninitialized fixed double array.
|
||||
MUST_USE_RESULT AllocationResult
|
||||
@ -2313,6 +2329,9 @@ class Heap {
|
||||
|
||||
// Allocate empty fixed array like objects.
|
||||
MUST_USE_RESULT AllocationResult AllocateEmptyFixedArray();
|
||||
|
||||
MUST_USE_RESULT AllocationResult AllocateEmptyWeakFixedArray();
|
||||
|
||||
MUST_USE_RESULT AllocationResult AllocateEmptyScopeInfo();
|
||||
MUST_USE_RESULT AllocationResult AllocateEmptyBoilerplateDescription();
|
||||
|
||||
|
@ -3033,7 +3033,9 @@ class PointersUpdatingVisitor : public ObjectVisitor, public RootVisitor {
|
||||
|
||||
void VisitPointers(HeapObject* host, MaybeObject** start,
|
||||
MaybeObject** end) final {
|
||||
UNREACHABLE();
|
||||
for (MaybeObject** p = start; p < end; p++) {
|
||||
UpdateSlotInternal(p);
|
||||
}
|
||||
}
|
||||
|
||||
void VisitRootPointer(Root root, const char* description,
|
||||
|
@ -55,7 +55,8 @@ class JSWeakCollection;
|
||||
V(Symbol) \
|
||||
V(ThinString) \
|
||||
V(TransitionArray) \
|
||||
V(WeakCell)
|
||||
V(WeakCell) \
|
||||
V(WeakFixedArray)
|
||||
|
||||
// The base class for visitors that need to dispatch on object type. The default
|
||||
// behavior of all visit functions is to iterate body of the given object using
|
||||
|
@ -113,6 +113,8 @@ bool Heap::CreateInitialMaps() {
|
||||
}
|
||||
|
||||
ALLOCATE_PARTIAL_MAP(FIXED_ARRAY_TYPE, kVariableSizeSentinel, fixed_array);
|
||||
ALLOCATE_PARTIAL_MAP(WEAK_FIXED_ARRAY_TYPE, kVariableSizeSentinel,
|
||||
weak_fixed_array);
|
||||
ALLOCATE_PARTIAL_MAP(FIXED_ARRAY_TYPE, kVariableSizeSentinel,
|
||||
fixed_cow_array)
|
||||
DCHECK_NE(fixed_array_map(), fixed_cow_array_map());
|
||||
@ -134,6 +136,12 @@ bool Heap::CreateInitialMaps() {
|
||||
}
|
||||
set_empty_fixed_array(FixedArray::cast(obj));
|
||||
|
||||
{
|
||||
AllocationResult allocation = AllocateEmptyWeakFixedArray();
|
||||
if (!allocation.To(&obj)) return false;
|
||||
}
|
||||
set_empty_weak_fixed_array(WeakFixedArray::cast(obj));
|
||||
|
||||
{
|
||||
AllocationResult allocation = Allocate(null_map(), OLD_SPACE);
|
||||
if (!allocation.To(&obj)) return false;
|
||||
@ -192,6 +200,7 @@ bool Heap::CreateInitialMaps() {
|
||||
// Fix the instance_descriptors for the existing maps.
|
||||
FinalizePartialMap(this, meta_map());
|
||||
FinalizePartialMap(this, fixed_array_map());
|
||||
FinalizePartialMap(this, weak_fixed_array_map());
|
||||
FinalizePartialMap(this, fixed_cow_array_map());
|
||||
FinalizePartialMap(this, descriptor_array_map());
|
||||
FinalizePartialMap(this, undefined_map());
|
||||
|
@ -69,6 +69,13 @@ void BodyDescriptorBase::IteratePointer(HeapObject* obj, int offset,
|
||||
v->VisitPointer(obj, HeapObject::RawField(obj, offset));
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
DISABLE_CFI_PERF void BodyDescriptorBase::IterateMaybeWeakPointers(
|
||||
HeapObject* obj, int start_offset, int end_offset, ObjectVisitor* v) {
|
||||
v->VisitPointers(obj, HeapObject::RawMaybeWeakField(obj, start_offset),
|
||||
HeapObject::RawMaybeWeakField(obj, end_offset));
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
void BodyDescriptorBase::IterateMaybeWeakPointer(HeapObject* obj, int offset,
|
||||
ObjectVisitor* v) {
|
||||
@ -268,6 +275,23 @@ class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
|
||||
}
|
||||
};
|
||||
|
||||
class WeakFixedArray::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
return offset >= kHeaderSize;
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IterateMaybeWeakPointers(obj, kHeaderSize, object_size, v);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) {
|
||||
return object->SizeFromMap(map);
|
||||
}
|
||||
};
|
||||
|
||||
class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
|
||||
@ -472,6 +496,8 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
|
||||
case HASH_TABLE_TYPE:
|
||||
case SCOPE_INFO_TYPE:
|
||||
return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3);
|
||||
case WEAK_FIXED_ARRAY_TYPE:
|
||||
return Op::template apply<WeakFixedArray::BodyDescriptor>(p1, p2, p3);
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
return ReturnType();
|
||||
case FEEDBACK_METADATA_TYPE:
|
||||
|
@ -36,6 +36,10 @@ class BodyDescriptorBase BASE_EMBEDDED {
|
||||
static inline void IteratePointer(HeapObject* obj, int offset,
|
||||
ObjectVisitor* v);
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateMaybeWeakPointers(HeapObject* obj, int start_offset,
|
||||
int end_offset, ObjectVisitor* v);
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateMaybeWeakPointer(HeapObject* obj, int offset,
|
||||
ObjectVisitor* v);
|
||||
|
@ -126,6 +126,9 @@ void HeapObject::HeapObjectVerify() {
|
||||
case SCOPE_INFO_TYPE:
|
||||
FixedArray::cast(this)->FixedArrayVerify();
|
||||
break;
|
||||
case WEAK_FIXED_ARRAY_TYPE:
|
||||
WeakFixedArray::cast(this)->WeakFixedArrayVerify();
|
||||
break;
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
FixedDoubleArray::cast(this)->FixedDoubleArrayVerify();
|
||||
break;
|
||||
@ -529,6 +532,12 @@ void FixedArray::FixedArrayVerify() {
|
||||
}
|
||||
}
|
||||
|
||||
void WeakFixedArray::WeakFixedArrayVerify() {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
MaybeObject::VerifyMaybeObjectPointer(Get(i));
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyArray::PropertyArrayVerify() {
|
||||
if (length() == 0) {
|
||||
CHECK_EQ(this, this->GetHeap()->empty_property_array());
|
||||
|
@ -2234,6 +2234,10 @@ int HeapObject::SizeFromMap(Map* map) const {
|
||||
reinterpret_cast<const FeedbackMetadata*>(this)
|
||||
->synchronized_slot_count());
|
||||
}
|
||||
if (instance_type == WEAK_FIXED_ARRAY_TYPE) {
|
||||
return WeakFixedArray::SizeFor(
|
||||
reinterpret_cast<const WeakFixedArray*>(this)->synchronized_length());
|
||||
}
|
||||
if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
|
||||
instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
|
||||
return reinterpret_cast<const FixedTypedArrayBase*>(this)->TypedArraySize(
|
||||
|
@ -2984,6 +2984,9 @@ VisitorId Map::GetVisitorId(Map* map) {
|
||||
case SCOPE_INFO_TYPE:
|
||||
return kVisitFixedArray;
|
||||
|
||||
case WEAK_FIXED_ARRAY_TYPE:
|
||||
return kVisitWeakFixedArray;
|
||||
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
return kVisitFixedDoubleArray;
|
||||
|
||||
|
@ -413,6 +413,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
|
||||
V(SMALL_ORDERED_HASH_SET_TYPE) \
|
||||
V(STORE_HANDLER_TYPE) \
|
||||
V(WEAK_CELL_TYPE) \
|
||||
V(WEAK_FIXED_ARRAY_TYPE) \
|
||||
\
|
||||
V(JS_PROXY_TYPE) \
|
||||
V(JS_GLOBAL_OBJECT_TYPE) \
|
||||
@ -767,6 +768,7 @@ enum InstanceType : uint16_t {
|
||||
SMALL_ORDERED_HASH_SET_TYPE,
|
||||
STORE_HANDLER_TYPE,
|
||||
WEAK_CELL_TYPE,
|
||||
WEAK_FIXED_ARRAY_TYPE,
|
||||
|
||||
// All the following types are subtypes of JSReceiver, which corresponds to
|
||||
// objects in the JS sense. The first and the last type in this range are
|
||||
@ -985,6 +987,7 @@ template <class C> inline bool Is(Object* obj);
|
||||
V(FixedArray) \
|
||||
V(FixedArrayBase) \
|
||||
V(FixedArrayExact) \
|
||||
V(FixedArrayOfWeakCells) \
|
||||
V(FixedBigInt64Array) \
|
||||
V(FixedBigUint64Array) \
|
||||
V(FixedDoubleArray) \
|
||||
@ -1097,7 +1100,7 @@ template <class C> inline bool Is(Object* obj);
|
||||
V(WasmModuleObject) \
|
||||
V(WasmTableObject) \
|
||||
V(WeakCell) \
|
||||
V(FixedArrayOfWeakCells) \
|
||||
V(WeakFixedArray) \
|
||||
V(WeakHashTable)
|
||||
|
||||
#define HEAP_OBJECT_TEMPLATE_TYPE_LIST(V) \
|
||||
|
@ -17,6 +17,7 @@ TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
|
||||
TYPE_CHECKER(FixedArrayExact, FIXED_ARRAY_TYPE)
|
||||
TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
|
||||
TYPE_CHECKER(FixedArrayOfWeakCells, FIXED_ARRAY_TYPE)
|
||||
TYPE_CHECKER(WeakFixedArray, WEAK_FIXED_ARRAY_TYPE)
|
||||
|
||||
CAST_ACCESSOR(ArrayList)
|
||||
CAST_ACCESSOR(ByteArray)
|
||||
@ -26,9 +27,12 @@ CAST_ACCESSOR(FixedDoubleArray)
|
||||
CAST_ACCESSOR(FixedTypedArrayBase)
|
||||
CAST_ACCESSOR(TemplateList)
|
||||
CAST_ACCESSOR(FixedArrayOfWeakCells)
|
||||
CAST_ACCESSOR(WeakFixedArray)
|
||||
|
||||
SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
|
||||
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
|
||||
SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
|
||||
SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
|
||||
|
||||
Object* FixedArrayBase::unchecked_synchronized_length() const {
|
||||
return ACQUIRE_READ_FIELD(this, kLengthOffset);
|
||||
@ -142,7 +146,7 @@ void FixedArray::FillWithHoles(int from, int to) {
|
||||
}
|
||||
|
||||
Object** FixedArray::data_start() {
|
||||
return HeapObject::RawField(this, kHeaderSize);
|
||||
return HeapObject::RawField(this, OffsetOfElementAt(0));
|
||||
}
|
||||
|
||||
Object** FixedArray::RawFieldOfElementAt(int index) {
|
||||
@ -215,6 +219,23 @@ void FixedDoubleArray::FillWithHoles(int from, int to) {
|
||||
}
|
||||
}
|
||||
|
||||
MaybeObject* WeakFixedArray::Get(int index) const {
|
||||
SLOW_DCHECK(index >= 0 && index < this->length());
|
||||
return RELAXED_READ_WEAK_FIELD(this, OffsetOfElementAt(index));
|
||||
}
|
||||
|
||||
void WeakFixedArray::Set(int index, MaybeObject* value) {
|
||||
DCHECK_GE(index, 0);
|
||||
DCHECK_LT(index, length());
|
||||
int offset = OffsetOfElementAt(index);
|
||||
RELAXED_WRITE_FIELD(this, offset, value);
|
||||
WEAK_WRITE_BARRIER(GetHeap(), this, offset, value);
|
||||
}
|
||||
|
||||
MaybeObject** WeakFixedArray::data_start() {
|
||||
return HeapObject::RawMaybeWeakField(this, kHeaderSize);
|
||||
}
|
||||
|
||||
Object* FixedArrayOfWeakCells::Get(int index) const {
|
||||
Object* raw = FixedArray::cast(this)->get(index + kFirstIndex);
|
||||
if (raw->IsSmi()) return raw;
|
||||
|
@ -243,6 +243,54 @@ class FixedDoubleArray : public FixedArrayBase {
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray);
|
||||
};
|
||||
|
||||
// WeakFixedArray describes fixed-sized arrays with element type
|
||||
// MaybeObject*.
|
||||
class WeakFixedArray : public HeapObject {
|
||||
public:
|
||||
DECL_CAST(WeakFixedArray)
|
||||
|
||||
inline MaybeObject* Get(int index) const;
|
||||
|
||||
// Setter that uses write barrier.
|
||||
inline void Set(int index, MaybeObject* value);
|
||||
|
||||
static constexpr int SizeFor(int length) {
|
||||
return kHeaderSize + length * kPointerSize;
|
||||
}
|
||||
|
||||
DECL_INT_ACCESSORS(length)
|
||||
|
||||
// Get and set the length using acquire loads and release stores.
|
||||
inline int synchronized_length() const;
|
||||
inline void synchronized_set_length(int value);
|
||||
|
||||
// Gives access to raw memory which stores the array's data.
|
||||
inline MaybeObject** data_start();
|
||||
|
||||
DECL_VERIFIER(WeakFixedArray)
|
||||
|
||||
class BodyDescriptor;
|
||||
typedef BodyDescriptor BodyDescriptorWeak;
|
||||
|
||||
static const int kLengthOffset = HeapObject::kHeaderSize;
|
||||
static const int kHeaderSize = kLengthOffset + kPointerSize;
|
||||
|
||||
static const int kMaxLength =
|
||||
(FixedArray::kMaxSize - kHeaderSize) / kPointerSize;
|
||||
|
||||
private:
|
||||
static int OffsetOfElementAt(int index) {
|
||||
return kHeaderSize + index * kPointerSize;
|
||||
}
|
||||
|
||||
friend class Heap;
|
||||
|
||||
static const int kFirstIndex = 1;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(WeakFixedArray);
|
||||
};
|
||||
|
||||
// Deprecated. Use WeakFixedArray instead.
|
||||
class FixedArrayOfWeakCells : public FixedArray {
|
||||
public:
|
||||
// If |maybe_array| is not a FixedArrayOfWeakCells, a fresh one will be
|
||||
|
@ -56,7 +56,8 @@ namespace internal {
|
||||
V(Symbol) \
|
||||
V(ThinString) \
|
||||
V(TransitionArray) \
|
||||
V(WeakCell)
|
||||
V(WeakCell) \
|
||||
V(WeakFixedArray)
|
||||
|
||||
// For data objects, JS objects and structs along with generic visitor which
|
||||
// can visit object of any size we provide visitors specialized by
|
||||
|
@ -165,6 +165,10 @@
|
||||
reinterpret_cast<Object*>(base::Relaxed_Load( \
|
||||
reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
|
||||
|
||||
#define RELAXED_READ_WEAK_FIELD(p, offset) \
|
||||
reinterpret_cast<MaybeObject*>(base::Relaxed_Load( \
|
||||
reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
|
||||
|
||||
#ifdef V8_CONCURRENT_MARKING
|
||||
#define WRITE_FIELD(p, offset, value) \
|
||||
base::Relaxed_Store( \
|
||||
@ -196,6 +200,12 @@
|
||||
object, HeapObject::RawField(object, offset), value); \
|
||||
heap->RecordWrite(object, HeapObject::RawField(object, offset), value);
|
||||
|
||||
#define WEAK_WRITE_BARRIER(heap, object, offset, value) \
|
||||
heap->incremental_marking()->RecordMaybeWeakWrite( \
|
||||
object, HeapObject::RawMaybeWeakField(object, offset), value); \
|
||||
heap->RecordWrite(object, HeapObject::RawMaybeWeakField(object, offset), \
|
||||
value);
|
||||
|
||||
#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
|
||||
if (mode != SKIP_WRITE_BARRIER) { \
|
||||
if (mode == UPDATE_WRITE_BARRIER) { \
|
||||
|
@ -1625,6 +1625,7 @@ bool V8HeapExplorer::IsEssentialObject(Object* object) {
|
||||
return object->IsHeapObject() && !object->IsOddball() &&
|
||||
object != heap_->empty_byte_array() &&
|
||||
object != heap_->empty_fixed_array() &&
|
||||
object != heap_->empty_weak_fixed_array() &&
|
||||
object != heap_->empty_descriptor_array() &&
|
||||
object != heap_->fixed_array_map() && object != heap_->cell_map() &&
|
||||
object != heap_->global_property_cell_map() &&
|
||||
|
@ -307,6 +307,86 @@ TEST(WeakReferenceWriteBarrier) {
|
||||
CHECK(fv->optimized_code_weak_or_smi()->IsWeakHeapObject());
|
||||
}
|
||||
|
||||
TEST(EmptyWeakArray) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
HandleScope outer_scope(isolate);
|
||||
|
||||
Handle<WeakFixedArray> array = factory->empty_weak_fixed_array();
|
||||
CHECK(array->IsWeakFixedArray());
|
||||
CHECK(!array->IsFixedArray());
|
||||
CHECK_EQ(array->length(), 0);
|
||||
}
|
||||
|
||||
TEST(WeakArraysBasic) {
|
||||
ManualGCScope manual_gc_scope;
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
Heap* heap = isolate->heap();
|
||||
HandleScope outer_scope(isolate);
|
||||
|
||||
const int length = 4;
|
||||
Handle<WeakFixedArray> array = factory->NewWeakFixedArray(length);
|
||||
CHECK(array->IsWeakFixedArray());
|
||||
CHECK(!array->IsFixedArray());
|
||||
CHECK_EQ(array->length(), length);
|
||||
CHECK(heap->InNewSpace(*array));
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
HeapObject* heap_object;
|
||||
CHECK(array->Get(i)->ToStrongHeapObject(&heap_object));
|
||||
CHECK_EQ(heap_object, heap->undefined_value());
|
||||
}
|
||||
|
||||
Handle<HeapObject> saved;
|
||||
{
|
||||
HandleScope inner_scope(isolate);
|
||||
Handle<FixedArray> index0 = factory->NewFixedArray(1);
|
||||
index0->set(0, Smi::FromInt(2016));
|
||||
Handle<FixedArray> index1 = factory->NewFixedArray(1);
|
||||
index1->set(0, Smi::FromInt(2017));
|
||||
|
||||
Handle<FixedArray> index2 = factory->NewFixedArray(1);
|
||||
index2->set(0, Smi::FromInt(2018));
|
||||
Handle<FixedArray> index3 = factory->NewFixedArray(1);
|
||||
index3->set(0, Smi::FromInt(2019));
|
||||
|
||||
array->Set(0, HeapObjectReference::Weak(*index0));
|
||||
array->Set(1, HeapObjectReference::Weak(*index1));
|
||||
array->Set(2, HeapObjectReference::Strong(*index2));
|
||||
array->Set(3, HeapObjectReference::Weak(*index3));
|
||||
saved = inner_scope.CloseAndEscape(index1);
|
||||
} // inner_scope goes out of scope.
|
||||
|
||||
// The references are only cleared by the mark-compact (scavenger treats weak
|
||||
// references as strong). Thus we need to GC until the array reaches old
|
||||
// space.
|
||||
|
||||
// TODO(marja): update this when/if we do handle weak references in the new
|
||||
// space.
|
||||
CcTest::CollectGarbage(NEW_SPACE);
|
||||
HeapObject* heap_object;
|
||||
CHECK(array->Get(0)->ToWeakHeapObject(&heap_object));
|
||||
CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2016);
|
||||
CHECK(array->Get(1)->ToWeakHeapObject(&heap_object));
|
||||
CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2017);
|
||||
CHECK(array->Get(2)->ToStrongHeapObject(&heap_object));
|
||||
CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2018);
|
||||
CHECK(array->Get(3)->ToWeakHeapObject(&heap_object));
|
||||
CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2019);
|
||||
|
||||
CcTest::CollectAllGarbage();
|
||||
CHECK(heap->InOldSpace(*array));
|
||||
CHECK(array->Get(0)->IsClearedWeakHeapObject());
|
||||
CHECK(array->Get(1)->ToWeakHeapObject(&heap_object));
|
||||
CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2017);
|
||||
CHECK(array->Get(2)->ToStrongHeapObject(&heap_object));
|
||||
CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2018);
|
||||
CHECK(array->Get(3)->IsClearedWeakHeapObject());
|
||||
}
|
||||
|
||||
} // namespace heap
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -101,6 +101,7 @@ INSTANCE_TYPES = {
|
||||
197: "SMALL_ORDERED_HASH_SET_TYPE",
|
||||
198: "STORE_HANDLER_TYPE",
|
||||
199: "WEAK_CELL_TYPE",
|
||||
200: "WEAK_FIXED_ARRAY_TYPE",
|
||||
1024: "JS_PROXY_TYPE",
|
||||
1025: "JS_GLOBAL_OBJECT_TYPE",
|
||||
1026: "JS_GLOBAL_PROXY_TYPE",
|
||||
@ -211,68 +212,69 @@ KNOWN_MAPS = {
|
||||
0x03801: (196, "SmallOrderedHashMapMap"),
|
||||
0x03859: (197, "SmallOrderedHashSetMap"),
|
||||
0x038b1: (185, "StringTableMap"),
|
||||
0x03909: (185, "WeakHashTableMap"),
|
||||
0x03961: (106, "NativeSourceStringMap"),
|
||||
0x039b9: (64, "StringMap"),
|
||||
0x03a11: (73, "ConsOneByteStringMap"),
|
||||
0x03a69: (65, "ConsStringMap"),
|
||||
0x03ac1: (77, "ThinOneByteStringMap"),
|
||||
0x03b19: (69, "ThinStringMap"),
|
||||
0x03b71: (67, "SlicedStringMap"),
|
||||
0x03bc9: (75, "SlicedOneByteStringMap"),
|
||||
0x03c21: (66, "ExternalStringMap"),
|
||||
0x03c79: (82, "ExternalStringWithOneByteDataMap"),
|
||||
0x03cd1: (74, "ExternalOneByteStringMap"),
|
||||
0x03d29: (98, "ShortExternalStringMap"),
|
||||
0x03d81: (114, "ShortExternalStringWithOneByteDataMap"),
|
||||
0x03dd9: (0, "InternalizedStringMap"),
|
||||
0x03e31: (2, "ExternalInternalizedStringMap"),
|
||||
0x03e89: (18, "ExternalInternalizedStringWithOneByteDataMap"),
|
||||
0x03ee1: (10, "ExternalOneByteInternalizedStringMap"),
|
||||
0x03f39: (34, "ShortExternalInternalizedStringMap"),
|
||||
0x03f91: (50, "ShortExternalInternalizedStringWithOneByteDataMap"),
|
||||
0x03fe9: (42, "ShortExternalOneByteInternalizedStringMap"),
|
||||
0x04041: (106, "ShortExternalOneByteStringMap"),
|
||||
0x04099: (140, "FixedUint8ArrayMap"),
|
||||
0x040f1: (139, "FixedInt8ArrayMap"),
|
||||
0x04149: (142, "FixedUint16ArrayMap"),
|
||||
0x041a1: (141, "FixedInt16ArrayMap"),
|
||||
0x041f9: (144, "FixedUint32ArrayMap"),
|
||||
0x04251: (143, "FixedInt32ArrayMap"),
|
||||
0x042a9: (145, "FixedFloat32ArrayMap"),
|
||||
0x04301: (146, "FixedFloat64ArrayMap"),
|
||||
0x04359: (147, "FixedUint8ClampedArrayMap"),
|
||||
0x043b1: (149, "FixedBigUint64ArrayMap"),
|
||||
0x04409: (148, "FixedBigInt64ArrayMap"),
|
||||
0x04461: (172, "Tuple2Map"),
|
||||
0x044b9: (170, "ScriptMap"),
|
||||
0x04511: (163, "InterceptorInfoMap"),
|
||||
0x04569: (154, "AccessorInfoMap"),
|
||||
0x045c1: (153, "AccessCheckInfoMap"),
|
||||
0x04619: (155, "AccessorPairMap"),
|
||||
0x04671: (156, "AliasedArgumentsEntryMap"),
|
||||
0x046c9: (157, "AllocationMementoMap"),
|
||||
0x04721: (158, "AllocationSiteMap"),
|
||||
0x04779: (159, "AsyncGeneratorRequestMap"),
|
||||
0x047d1: (160, "ContextExtensionMap"),
|
||||
0x04829: (161, "DebugInfoMap"),
|
||||
0x04881: (162, "FunctionTemplateInfoMap"),
|
||||
0x048d9: (164, "ModuleInfoEntryMap"),
|
||||
0x04931: (165, "ModuleMap"),
|
||||
0x04989: (166, "ObjectTemplateInfoMap"),
|
||||
0x049e1: (167, "PromiseCapabilityMap"),
|
||||
0x04a39: (168, "PromiseReactionMap"),
|
||||
0x04a91: (169, "PrototypeInfoMap"),
|
||||
0x04ae9: (171, "StackFrameInfoMap"),
|
||||
0x04b41: (173, "Tuple3Map"),
|
||||
0x04b99: (174, "WasmCompiledModuleMap"),
|
||||
0x04bf1: (175, "WasmDebugInfoMap"),
|
||||
0x04c49: (176, "WasmSharedModuleDataMap"),
|
||||
0x04ca1: (177, "CallableTaskMap"),
|
||||
0x04cf9: (178, "CallbackTaskMap"),
|
||||
0x04d51: (179, "PromiseFulfillReactionJobTaskMap"),
|
||||
0x04da9: (180, "PromiseRejectReactionJobTaskMap"),
|
||||
0x04e01: (181, "PromiseResolveThenableJobTaskMap"),
|
||||
0x03909: (200, "WeakFixedArrayMap"),
|
||||
0x03961: (185, "WeakHashTableMap"),
|
||||
0x039b9: (106, "NativeSourceStringMap"),
|
||||
0x03a11: (64, "StringMap"),
|
||||
0x03a69: (73, "ConsOneByteStringMap"),
|
||||
0x03ac1: (65, "ConsStringMap"),
|
||||
0x03b19: (77, "ThinOneByteStringMap"),
|
||||
0x03b71: (69, "ThinStringMap"),
|
||||
0x03bc9: (67, "SlicedStringMap"),
|
||||
0x03c21: (75, "SlicedOneByteStringMap"),
|
||||
0x03c79: (66, "ExternalStringMap"),
|
||||
0x03cd1: (82, "ExternalStringWithOneByteDataMap"),
|
||||
0x03d29: (74, "ExternalOneByteStringMap"),
|
||||
0x03d81: (98, "ShortExternalStringMap"),
|
||||
0x03dd9: (114, "ShortExternalStringWithOneByteDataMap"),
|
||||
0x03e31: (0, "InternalizedStringMap"),
|
||||
0x03e89: (2, "ExternalInternalizedStringMap"),
|
||||
0x03ee1: (18, "ExternalInternalizedStringWithOneByteDataMap"),
|
||||
0x03f39: (10, "ExternalOneByteInternalizedStringMap"),
|
||||
0x03f91: (34, "ShortExternalInternalizedStringMap"),
|
||||
0x03fe9: (50, "ShortExternalInternalizedStringWithOneByteDataMap"),
|
||||
0x04041: (42, "ShortExternalOneByteInternalizedStringMap"),
|
||||
0x04099: (106, "ShortExternalOneByteStringMap"),
|
||||
0x040f1: (140, "FixedUint8ArrayMap"),
|
||||
0x04149: (139, "FixedInt8ArrayMap"),
|
||||
0x041a1: (142, "FixedUint16ArrayMap"),
|
||||
0x041f9: (141, "FixedInt16ArrayMap"),
|
||||
0x04251: (144, "FixedUint32ArrayMap"),
|
||||
0x042a9: (143, "FixedInt32ArrayMap"),
|
||||
0x04301: (145, "FixedFloat32ArrayMap"),
|
||||
0x04359: (146, "FixedFloat64ArrayMap"),
|
||||
0x043b1: (147, "FixedUint8ClampedArrayMap"),
|
||||
0x04409: (149, "FixedBigUint64ArrayMap"),
|
||||
0x04461: (148, "FixedBigInt64ArrayMap"),
|
||||
0x044b9: (172, "Tuple2Map"),
|
||||
0x04511: (170, "ScriptMap"),
|
||||
0x04569: (163, "InterceptorInfoMap"),
|
||||
0x045c1: (154, "AccessorInfoMap"),
|
||||
0x04619: (153, "AccessCheckInfoMap"),
|
||||
0x04671: (155, "AccessorPairMap"),
|
||||
0x046c9: (156, "AliasedArgumentsEntryMap"),
|
||||
0x04721: (157, "AllocationMementoMap"),
|
||||
0x04779: (158, "AllocationSiteMap"),
|
||||
0x047d1: (159, "AsyncGeneratorRequestMap"),
|
||||
0x04829: (160, "ContextExtensionMap"),
|
||||
0x04881: (161, "DebugInfoMap"),
|
||||
0x048d9: (162, "FunctionTemplateInfoMap"),
|
||||
0x04931: (164, "ModuleInfoEntryMap"),
|
||||
0x04989: (165, "ModuleMap"),
|
||||
0x049e1: (166, "ObjectTemplateInfoMap"),
|
||||
0x04a39: (167, "PromiseCapabilityMap"),
|
||||
0x04a91: (168, "PromiseReactionMap"),
|
||||
0x04ae9: (169, "PrototypeInfoMap"),
|
||||
0x04b41: (171, "StackFrameInfoMap"),
|
||||
0x04b99: (173, "Tuple3Map"),
|
||||
0x04bf1: (174, "WasmCompiledModuleMap"),
|
||||
0x04c49: (175, "WasmDebugInfoMap"),
|
||||
0x04ca1: (176, "WasmSharedModuleDataMap"),
|
||||
0x04cf9: (177, "CallableTaskMap"),
|
||||
0x04d51: (178, "CallbackTaskMap"),
|
||||
0x04da9: (179, "PromiseFulfillReactionJobTaskMap"),
|
||||
0x04e01: (180, "PromiseRejectReactionJobTaskMap"),
|
||||
0x04e59: (181, "PromiseResolveThenableJobTaskMap"),
|
||||
}
|
||||
|
||||
# List of known V8 objects.
|
||||
@ -312,15 +314,15 @@ KNOWN_OBJECTS = {
|
||||
("OLD_SPACE", 0x02909): "EmptyOrderedHashSet",
|
||||
("OLD_SPACE", 0x02941): "EmptyPropertyCell",
|
||||
("OLD_SPACE", 0x02969): "EmptyWeakCell",
|
||||
("OLD_SPACE", 0x029d9): "NoElementsProtector",
|
||||
("OLD_SPACE", 0x02a01): "IsConcatSpreadableProtector",
|
||||
("OLD_SPACE", 0x02a11): "SpeciesProtector",
|
||||
("OLD_SPACE", 0x02a39): "StringLengthProtector",
|
||||
("OLD_SPACE", 0x02a49): "ArrayIteratorProtector",
|
||||
("OLD_SPACE", 0x02a71): "ArrayBufferNeuteringProtector",
|
||||
("OLD_SPACE", 0x02af9): "InfinityValue",
|
||||
("OLD_SPACE", 0x02b09): "MinusZeroValue",
|
||||
("OLD_SPACE", 0x02b19): "MinusInfinityValue",
|
||||
("OLD_SPACE", 0x029e9): "NoElementsProtector",
|
||||
("OLD_SPACE", 0x02a11): "IsConcatSpreadableProtector",
|
||||
("OLD_SPACE", 0x02a21): "SpeciesProtector",
|
||||
("OLD_SPACE", 0x02a49): "StringLengthProtector",
|
||||
("OLD_SPACE", 0x02a59): "ArrayIteratorProtector",
|
||||
("OLD_SPACE", 0x02a81): "ArrayBufferNeuteringProtector",
|
||||
("OLD_SPACE", 0x02b09): "InfinityValue",
|
||||
("OLD_SPACE", 0x02b19): "MinusZeroValue",
|
||||
("OLD_SPACE", 0x02b29): "MinusInfinityValue",
|
||||
}
|
||||
|
||||
# List of known V8 Frame Markers.
|
||||
|
Loading…
Reference in New Issue
Block a user