mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:59:38 +00:00
[vm] Add WeakArray; to be used to create weak canonical sets.
TEST=ci Bug: https://github.com/dart-lang/sdk/issues/50648 Change-Id: I788a8e3e5e8383c0b8d6f248d64a33dc67013260 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/278860 Reviewed-by: Siva Annamalai <asiva@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
5fbbb75c53
commit
f3067e8740
|
@ -36,6 +36,7 @@ static constexpr intptr_t kClassIdTagMax = (1 << 20) - 1;
|
|||
V(Namespace) \
|
||||
V(KernelProgramInfo) \
|
||||
V(WeakSerializationReference) \
|
||||
V(WeakArray) \
|
||||
V(Code) \
|
||||
V(Instructions) \
|
||||
V(InstructionsSection) \
|
||||
|
|
|
@ -1423,6 +1423,12 @@ class WeakSerializationReference : public AllStatic {
|
|||
FINAL_CLASS();
|
||||
};
|
||||
|
||||
class WeakArray : public AllStatic {
|
||||
public:
|
||||
static word InstanceSize() { return 0; }
|
||||
FINAL_CLASS();
|
||||
};
|
||||
|
||||
class SubtypeTestCache : public AllStatic {
|
||||
public:
|
||||
static word cache_offset();
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace dart {
|
|||
// - variable name
|
||||
#define GC_LINKED_LIST(V) \
|
||||
V(WeakProperty, weak_properties) \
|
||||
V(WeakArray, weak_arrays) \
|
||||
V(WeakReference, weak_references) \
|
||||
V(FinalizerEntry, finalizer_entries)
|
||||
|
||||
|
|
|
@ -865,6 +865,8 @@ ISOLATE_UNIT_TEST_CASE(WeakSmi) {
|
|||
WeakReference::Handle(WeakReference::New(Heap::kNew));
|
||||
WeakReference& old_weakref =
|
||||
WeakReference::Handle(WeakReference::New(Heap::kOld));
|
||||
WeakArray& new_weakarray = WeakArray::Handle(WeakArray::New(1, Heap::kNew));
|
||||
WeakArray& old_weakarray = WeakArray::Handle(WeakArray::New(1, Heap::kOld));
|
||||
FinalizerEntry& new_finalizer = FinalizerEntry::Handle(
|
||||
FinalizerEntry::New(FinalizerBase::Handle(), Heap::kNew));
|
||||
FinalizerEntry& old_finalizer = FinalizerEntry::Handle(
|
||||
|
@ -877,6 +879,8 @@ ISOLATE_UNIT_TEST_CASE(WeakSmi) {
|
|||
old_ephemeron.set_key(smi);
|
||||
new_weakref.set_target(smi);
|
||||
old_weakref.set_target(smi);
|
||||
new_weakarray.SetAt(0, smi);
|
||||
old_weakarray.SetAt(0, smi);
|
||||
new_finalizer.set_value(smi);
|
||||
old_finalizer.set_value(smi);
|
||||
}
|
||||
|
@ -888,6 +892,8 @@ ISOLATE_UNIT_TEST_CASE(WeakSmi) {
|
|||
EXPECT(old_ephemeron.key() == Smi::New(42));
|
||||
EXPECT(new_weakref.target() == Smi::New(42));
|
||||
EXPECT(old_weakref.target() == Smi::New(42));
|
||||
EXPECT(new_weakarray.At(0) == Smi::New(42));
|
||||
EXPECT(old_weakarray.At(0) == Smi::New(42));
|
||||
EXPECT(new_finalizer.value() == Smi::New(42));
|
||||
EXPECT(old_finalizer.value() == Smi::New(42));
|
||||
}
|
||||
|
|
|
@ -123,14 +123,13 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
|
|||
|
||||
intptr_t size;
|
||||
if (class_id == kWeakPropertyCid) {
|
||||
WeakPropertyPtr raw_weak = static_cast<WeakPropertyPtr>(raw_obj);
|
||||
size = ProcessWeakProperty(raw_weak);
|
||||
size = ProcessWeakProperty(static_cast<WeakPropertyPtr>(raw_obj));
|
||||
} else if (class_id == kWeakReferenceCid) {
|
||||
WeakReferencePtr raw_weak = static_cast<WeakReferencePtr>(raw_obj);
|
||||
size = ProcessWeakReference(raw_weak);
|
||||
size = ProcessWeakReference(static_cast<WeakReferencePtr>(raw_obj));
|
||||
} else if (class_id == kWeakArrayCid) {
|
||||
size = ProcessWeakArray(static_cast<WeakArrayPtr>(raw_obj));
|
||||
} else if (class_id == kFinalizerEntryCid) {
|
||||
FinalizerEntryPtr raw_weak = static_cast<FinalizerEntryPtr>(raw_obj);
|
||||
size = ProcessFinalizerEntry(raw_weak);
|
||||
size = ProcessFinalizerEntry(static_cast<FinalizerEntryPtr>(raw_obj));
|
||||
} else {
|
||||
if ((class_id == kArrayCid) || (class_id == kImmutableArrayCid)) {
|
||||
size = raw_obj->untag()->HeapSize();
|
||||
|
@ -232,6 +231,11 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
|
|||
return raw_weak->untag()->HeapSize();
|
||||
}
|
||||
|
||||
intptr_t ProcessWeakArray(WeakArrayPtr raw_weak) {
|
||||
delayed_.weak_arrays.Enqueue(raw_weak);
|
||||
return raw_weak->untag()->HeapSize();
|
||||
}
|
||||
|
||||
intptr_t ProcessFinalizerEntry(FinalizerEntryPtr raw_entry) {
|
||||
ASSERT(IsMarked(raw_entry));
|
||||
delayed_.finalizer_entries.Enqueue(raw_entry);
|
||||
|
@ -315,6 +319,23 @@ class MarkingVisitorBase : public ObjectPointerVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
void MournWeakArrays() {
|
||||
WeakArrayPtr cur_weak = delayed_.weak_arrays.Release();
|
||||
while (cur_weak != WeakArray::null()) {
|
||||
WeakArrayPtr next_weak =
|
||||
cur_weak->untag()->next_seen_by_gc_.Decompress(cur_weak->heap_base());
|
||||
cur_weak->untag()->next_seen_by_gc_ = WeakArray::null();
|
||||
|
||||
intptr_t length = Smi::Value(cur_weak->untag()->length());
|
||||
for (intptr_t i = 0; i < length; i++) {
|
||||
ForwardOrSetNullIfCollected(cur_weak->heap_base(),
|
||||
&cur_weak->untag()->data()[i]);
|
||||
}
|
||||
|
||||
cur_weak = next_weak;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether the object referred to in `ptr_address` was GCed this GC.
|
||||
static bool ForwardOrSetNullIfCollected(uword heap_base,
|
||||
CompressedObjectPtr* ptr_address) {
|
||||
|
@ -742,6 +763,7 @@ class ParallelMarkTask : public ThreadPool::Task {
|
|||
// Phase 3: Weak processing and statistics.
|
||||
visitor_->MournWeakProperties();
|
||||
visitor_->MournWeakReferences();
|
||||
visitor_->MournWeakArrays();
|
||||
// Don't MournFinalized here, do it on main thread, so that we don't have
|
||||
// to coordinate workers.
|
||||
|
||||
|
@ -1044,6 +1066,7 @@ void GCMarker::MarkObjects(PageSpace* page_space) {
|
|||
visitor.FinalizeMarking();
|
||||
visitor.MournWeakProperties();
|
||||
visitor.MournWeakReferences();
|
||||
visitor.MournWeakArrays();
|
||||
MournFinalized(&visitor);
|
||||
IterateWeakRoots(thread);
|
||||
// All marking done; detach code, etc.
|
||||
|
|
|
@ -309,7 +309,8 @@ class ScavengerVisitorBase : public ObjectPointerVisitor {
|
|||
}
|
||||
|
||||
MournWeakProperties();
|
||||
MournOrUpdateWeakReferences();
|
||||
MournWeakReferences();
|
||||
MournWeakArrays();
|
||||
MournFinalized(this);
|
||||
}
|
||||
page_space_->ReleaseLock(freelist_);
|
||||
|
@ -539,7 +540,8 @@ class ScavengerVisitorBase : public ObjectPointerVisitor {
|
|||
}
|
||||
|
||||
void MournWeakProperties();
|
||||
void MournOrUpdateWeakReferences();
|
||||
void MournWeakReferences();
|
||||
void MournWeakArrays();
|
||||
|
||||
Thread* thread_;
|
||||
Scavenger* scavenger_;
|
||||
|
@ -1351,6 +1353,10 @@ intptr_t ScavengerVisitorBase<parallel>::ProcessCopied(ObjectPtr raw_obj) {
|
|||
return raw_weak->untag()->HeapSize();
|
||||
}
|
||||
}
|
||||
} else if (UNLIKELY(class_id == kWeakArrayCid)) {
|
||||
WeakArrayPtr raw_weak = static_cast<WeakArrayPtr>(raw_obj);
|
||||
delayed_.weak_arrays.Enqueue(raw_weak);
|
||||
return raw_weak->untag()->HeapSize();
|
||||
} else if (UNLIKELY(class_id == kFinalizerEntryCid)) {
|
||||
FinalizerEntryPtr raw_entry = static_cast<FinalizerEntryPtr>(raw_obj);
|
||||
ASSERT(IsNotForwarding(raw_entry));
|
||||
|
@ -1484,7 +1490,7 @@ void ScavengerVisitorBase<parallel>::MournWeakProperties() {
|
|||
}
|
||||
|
||||
template <bool parallel>
|
||||
void ScavengerVisitorBase<parallel>::MournOrUpdateWeakReferences() {
|
||||
void ScavengerVisitorBase<parallel>::MournWeakReferences() {
|
||||
ASSERT(!scavenger_->abort_);
|
||||
|
||||
// The queued weak references at this point either should have their target
|
||||
|
@ -1506,6 +1512,27 @@ void ScavengerVisitorBase<parallel>::MournOrUpdateWeakReferences() {
|
|||
}
|
||||
}
|
||||
|
||||
template <bool parallel>
|
||||
void ScavengerVisitorBase<parallel>::MournWeakArrays() {
|
||||
ASSERT(!scavenger_->abort_);
|
||||
WeakArrayPtr cur_weak = delayed_.weak_arrays.Release();
|
||||
while (cur_weak != WeakArray::null()) {
|
||||
WeakArrayPtr next_weak =
|
||||
cur_weak->untag()->next_seen_by_gc_.Decompress(cur_weak->heap_base());
|
||||
// Reset the next pointer in the weak reference.
|
||||
cur_weak->untag()->next_seen_by_gc_ = WeakArray::null();
|
||||
|
||||
intptr_t length = Smi::Value(cur_weak->untag()->length());
|
||||
for (intptr_t i = 0; i < length; i++) {
|
||||
ForwardOrSetNullIfCollected(cur_weak->heap_base(),
|
||||
&(cur_weak->untag()->data()[i]));
|
||||
}
|
||||
|
||||
// Advance to next weak reference in the queue.
|
||||
cur_weak = next_weak;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether the object referred to in `ptr_address` was GCed this GC.
|
||||
template <bool parallel>
|
||||
bool ScavengerVisitorBase<parallel>::ForwardOrSetNullIfCollected(
|
||||
|
|
|
@ -187,6 +187,7 @@ ClassPtr Object::unhandled_exception_class_ = static_cast<ClassPtr>(RAW_NULL);
|
|||
ClassPtr Object::unwind_error_class_ = static_cast<ClassPtr>(RAW_NULL);
|
||||
ClassPtr Object::weak_serialization_reference_class_ =
|
||||
static_cast<ClassPtr>(RAW_NULL);
|
||||
ClassPtr Object::weak_array_class_ = static_cast<ClassPtr>(RAW_NULL);
|
||||
|
||||
const double MegamorphicCache::kLoadFactor = 0.50;
|
||||
|
||||
|
@ -942,6 +943,9 @@ void Object::Init(IsolateGroup* isolate_group) {
|
|||
isolate_group);
|
||||
weak_serialization_reference_class_ = cls.ptr();
|
||||
|
||||
cls = Class::New<WeakArray, RTN::WeakArray>(isolate_group);
|
||||
weak_array_class_ = cls.ptr();
|
||||
|
||||
ASSERT(class_class() != null_);
|
||||
|
||||
// Pre-allocate classes in the vm isolate so that we can for example create a
|
||||
|
@ -1469,6 +1473,7 @@ void Object::FinalizeVMIsolate(IsolateGroup* isolate_group) {
|
|||
SET_CLASS_NAME(namespace, Namespace);
|
||||
SET_CLASS_NAME(kernel_program_info, KernelProgramInfo);
|
||||
SET_CLASS_NAME(weak_serialization_reference, WeakSerializationReference);
|
||||
SET_CLASS_NAME(weak_array, WeakArray);
|
||||
SET_CLASS_NAME(code, Code);
|
||||
SET_CLASS_NAME(instructions, Instructions);
|
||||
SET_CLASS_NAME(instructions_section, InstructionsSection);
|
||||
|
@ -5258,6 +5263,8 @@ const char* Class::GenerateUserVisibleName() const {
|
|||
return Symbols::KernelProgramInfo().ToCString();
|
||||
case kWeakSerializationReferenceCid:
|
||||
return Symbols::WeakSerializationReference().ToCString();
|
||||
case kWeakArrayCid:
|
||||
return Symbols::WeakArray().ToCString();
|
||||
case kCodeCid:
|
||||
return Symbols::Code().ToCString();
|
||||
case kInstructionsCid:
|
||||
|
@ -17402,6 +17409,24 @@ ObjectPtr WeakSerializationReference::New(const Object& target,
|
|||
return result.ptr();
|
||||
}
|
||||
|
||||
const char* WeakArray::ToCString() const {
|
||||
return Thread::Current()->zone()->PrintToString("WeakArray len:%" Pd,
|
||||
Length());
|
||||
}
|
||||
|
||||
WeakArrayPtr WeakArray::New(intptr_t length, Heap::Space space) {
|
||||
ASSERT(Object::weak_array_class() != Class::null());
|
||||
if (!IsValidLength(length)) {
|
||||
// This should be caught before we reach here.
|
||||
FATAL("Fatal error in WeakArray::New: invalid len %" Pd "\n", length);
|
||||
}
|
||||
WeakArrayPtr raw = static_cast<WeakArrayPtr>(
|
||||
Object::Allocate(kWeakArrayCid, WeakArray::InstanceSize(length), space,
|
||||
WeakArray::ContainsCompressedPointers()));
|
||||
raw->untag()->set_length(Smi::New(length));
|
||||
return raw;
|
||||
}
|
||||
|
||||
#if defined(INCLUDE_IL_PRINTER)
|
||||
Code::Comments& Code::Comments::New(intptr_t count) {
|
||||
Comments* comments;
|
||||
|
|
|
@ -524,7 +524,6 @@ class Object {
|
|||
static ClassPtr exception_handlers_class() {
|
||||
return exception_handlers_class_;
|
||||
}
|
||||
static ClassPtr deopt_info_class() { return deopt_info_class_; }
|
||||
static ClassPtr context_class() { return context_class_; }
|
||||
static ClassPtr context_scope_class() { return context_scope_class_; }
|
||||
static ClassPtr sentinel_class() { return sentinel_class_; }
|
||||
|
@ -546,6 +545,7 @@ class Object {
|
|||
static ClassPtr weak_serialization_reference_class() {
|
||||
return weak_serialization_reference_class_;
|
||||
}
|
||||
static ClassPtr weak_array_class() { return weak_array_class_; }
|
||||
|
||||
// Initialize the VM isolate.
|
||||
static void InitNullAndBool(IsolateGroup* isolate_group);
|
||||
|
@ -839,51 +839,46 @@ class Object {
|
|||
static BoolPtr true_;
|
||||
static BoolPtr false_;
|
||||
|
||||
static ClassPtr class_class_; // Class of the Class vm object.
|
||||
static ClassPtr dynamic_class_; // Class of the 'dynamic' type.
|
||||
static ClassPtr void_class_; // Class of the 'void' type.
|
||||
static ClassPtr type_parameters_class_; // Class of TypeParameters vm object.
|
||||
static ClassPtr type_arguments_class_; // Class of TypeArguments vm object.
|
||||
static ClassPtr patch_class_class_; // Class of the PatchClass vm object.
|
||||
static ClassPtr function_class_; // Class of the Function vm object.
|
||||
static ClassPtr closure_data_class_; // Class of ClosureData vm obj.
|
||||
static ClassPtr ffi_trampoline_data_class_; // Class of FfiTrampolineData
|
||||
// vm obj.
|
||||
static ClassPtr field_class_; // Class of the Field vm object.
|
||||
static ClassPtr script_class_; // Class of the Script vm object.
|
||||
static ClassPtr library_class_; // Class of the Library vm object.
|
||||
static ClassPtr namespace_class_; // Class of Namespace vm object.
|
||||
static ClassPtr kernel_program_info_class_; // Class of KernelProgramInfo vm
|
||||
// object.
|
||||
static ClassPtr code_class_; // Class of the Code vm object.
|
||||
|
||||
static ClassPtr instructions_class_; // Class of the Instructions vm object.
|
||||
static ClassPtr instructions_section_class_; // Class of InstructionsSection.
|
||||
static ClassPtr instructions_table_class_; // Class of InstructionsTable.
|
||||
static ClassPtr object_pool_class_; // Class of the ObjectPool vm object.
|
||||
static ClassPtr pc_descriptors_class_; // Class of PcDescriptors vm object.
|
||||
static ClassPtr code_source_map_class_; // Class of CodeSourceMap vm object.
|
||||
static ClassPtr compressed_stackmaps_class_; // Class of CompressedStackMaps.
|
||||
static ClassPtr var_descriptors_class_; // Class of LocalVarDescriptors.
|
||||
static ClassPtr exception_handlers_class_; // Class of ExceptionHandlers.
|
||||
static ClassPtr deopt_info_class_; // Class of DeoptInfo.
|
||||
static ClassPtr context_class_; // Class of the Context vm object.
|
||||
static ClassPtr context_scope_class_; // Class of ContextScope vm object.
|
||||
static ClassPtr sentinel_class_; // Class of Sentinel vm object.
|
||||
static ClassPtr singletargetcache_class_; // Class of SingleTargetCache.
|
||||
static ClassPtr unlinkedcall_class_; // Class of UnlinkedCall.
|
||||
static ClassPtr
|
||||
monomorphicsmiablecall_class_; // Class of MonomorphicSmiableCall.
|
||||
static ClassPtr icdata_class_; // Class of ICData.
|
||||
static ClassPtr megamorphic_cache_class_; // Class of MegamorphiCache.
|
||||
static ClassPtr subtypetestcache_class_; // Class of SubtypeTestCache.
|
||||
static ClassPtr loadingunit_class_; // Class of LoadingUnit.
|
||||
static ClassPtr api_error_class_; // Class of ApiError.
|
||||
static ClassPtr language_error_class_; // Class of LanguageError.
|
||||
static ClassPtr unhandled_exception_class_; // Class of UnhandledException.
|
||||
static ClassPtr unwind_error_class_; // Class of UnwindError.
|
||||
// Class of WeakSerializationReference.
|
||||
static ClassPtr class_class_;
|
||||
static ClassPtr dynamic_class_;
|
||||
static ClassPtr void_class_;
|
||||
static ClassPtr type_parameters_class_;
|
||||
static ClassPtr type_arguments_class_;
|
||||
static ClassPtr patch_class_class_;
|
||||
static ClassPtr function_class_;
|
||||
static ClassPtr closure_data_class_;
|
||||
static ClassPtr ffi_trampoline_data_class_;
|
||||
static ClassPtr field_class_;
|
||||
static ClassPtr script_class_;
|
||||
static ClassPtr library_class_;
|
||||
static ClassPtr namespace_class_;
|
||||
static ClassPtr kernel_program_info_class_;
|
||||
static ClassPtr code_class_;
|
||||
static ClassPtr instructions_class_;
|
||||
static ClassPtr instructions_section_class_;
|
||||
static ClassPtr instructions_table_class_;
|
||||
static ClassPtr object_pool_class_;
|
||||
static ClassPtr pc_descriptors_class_;
|
||||
static ClassPtr code_source_map_class_;
|
||||
static ClassPtr compressed_stackmaps_class_;
|
||||
static ClassPtr var_descriptors_class_;
|
||||
static ClassPtr exception_handlers_class_;
|
||||
static ClassPtr context_class_;
|
||||
static ClassPtr context_scope_class_;
|
||||
static ClassPtr sentinel_class_;
|
||||
static ClassPtr singletargetcache_class_;
|
||||
static ClassPtr unlinkedcall_class_;
|
||||
static ClassPtr monomorphicsmiablecall_class_;
|
||||
static ClassPtr icdata_class_;
|
||||
static ClassPtr megamorphic_cache_class_;
|
||||
static ClassPtr subtypetestcache_class_;
|
||||
static ClassPtr loadingunit_class_;
|
||||
static ClassPtr api_error_class_;
|
||||
static ClassPtr language_error_class_;
|
||||
static ClassPtr unhandled_exception_class_;
|
||||
static ClassPtr unwind_error_class_;
|
||||
static ClassPtr weak_serialization_reference_class_;
|
||||
static ClassPtr weak_array_class_;
|
||||
|
||||
#define DECLARE_SHARED_READONLY_HANDLE(Type, name) static Type* name##_;
|
||||
SHARED_READONLY_HANDLES_LIST(DECLARE_SHARED_READONLY_HANDLE)
|
||||
|
@ -6361,6 +6356,72 @@ class WeakSerializationReference : public Object {
|
|||
friend class Class;
|
||||
};
|
||||
|
||||
class WeakArray : public Object {
|
||||
public:
|
||||
intptr_t Length() const { return LengthOf(ptr()); }
|
||||
static inline intptr_t LengthOf(const WeakArrayPtr array);
|
||||
|
||||
static intptr_t length_offset() {
|
||||
return OFFSET_OF(UntaggedWeakArray, length_);
|
||||
}
|
||||
static intptr_t data_offset() {
|
||||
return OFFSET_OF_RETURNED_VALUE(UntaggedWeakArray, data);
|
||||
}
|
||||
static intptr_t element_offset(intptr_t index) {
|
||||
return OFFSET_OF_RETURNED_VALUE(UntaggedWeakArray, data) +
|
||||
kBytesPerElement * index;
|
||||
}
|
||||
static intptr_t index_at_offset(intptr_t offset_in_bytes) {
|
||||
intptr_t index = (offset_in_bytes - data_offset()) / kBytesPerElement;
|
||||
ASSERT(index >= 0);
|
||||
return index;
|
||||
}
|
||||
|
||||
struct ArrayTraits {
|
||||
static intptr_t elements_start_offset() { return WeakArray::data_offset(); }
|
||||
|
||||
static constexpr intptr_t kElementSize = kCompressedWordSize;
|
||||
};
|
||||
|
||||
ObjectPtr At(intptr_t index) const { return untag()->element(index); }
|
||||
void SetAt(intptr_t index, const Object& value) const {
|
||||
untag()->set_element(index, value.ptr());
|
||||
}
|
||||
|
||||
// Access to the array with acquire release semantics.
|
||||
ObjectPtr AtAcquire(intptr_t index) const {
|
||||
return untag()->element<std::memory_order_acquire>(index);
|
||||
}
|
||||
void SetAtRelease(intptr_t index, const Object& value) const {
|
||||
untag()->set_element<std::memory_order_release>(index, value.ptr());
|
||||
}
|
||||
|
||||
static const intptr_t kBytesPerElement = kCompressedWordSize;
|
||||
static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
|
||||
|
||||
static constexpr bool IsValidLength(intptr_t length) {
|
||||
return 0 <= length && length <= kMaxElements;
|
||||
}
|
||||
|
||||
static intptr_t InstanceSize() {
|
||||
ASSERT(sizeof(UntaggedWeakArray) ==
|
||||
OFFSET_OF_RETURNED_VALUE(UntaggedWeakArray, data));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static constexpr intptr_t InstanceSize(intptr_t len) {
|
||||
return RoundedAllocationSize(sizeof(UntaggedWeakArray) +
|
||||
(len * kBytesPerElement));
|
||||
}
|
||||
|
||||
static WeakArrayPtr New(intptr_t length, Heap::Space space = Heap::kNew);
|
||||
|
||||
private:
|
||||
FINAL_HEAP_OBJECT_IMPLEMENTATION(WeakArray, Object);
|
||||
friend class Class;
|
||||
friend class Object;
|
||||
};
|
||||
|
||||
class Code : public Object {
|
||||
public:
|
||||
// When dual mapping, this returns the executable view.
|
||||
|
@ -12963,6 +13024,10 @@ void Field::set_field_id_unsafe(intptr_t field_id) const {
|
|||
untag()->set_host_offset_or_field_id(Smi::New(field_id));
|
||||
}
|
||||
|
||||
intptr_t WeakArray::LengthOf(const WeakArrayPtr array) {
|
||||
return Smi::Value(array->untag()->length());
|
||||
}
|
||||
|
||||
void Context::SetAt(intptr_t index, const Object& value) const {
|
||||
untag()->set_element(index, value.ptr());
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
V(UnlinkedCall) \
|
||||
V(UnwindError) \
|
||||
V(UserTag) \
|
||||
V(WeakArray) \
|
||||
V(WeakSerializationReference)
|
||||
|
||||
namespace dart {
|
||||
|
|
|
@ -705,6 +705,35 @@ void WeakSerializationReference::PrintJSONImpl(JSONStream* stream,
|
|||
jsobj.AddProperty("target", obj);
|
||||
}
|
||||
|
||||
void WeakArray::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
AddCommonObjectProperties(&jsobj, "Object", ref);
|
||||
jsobj.AddServiceId(*this);
|
||||
jsobj.AddProperty("length", Length());
|
||||
if (ref) {
|
||||
return;
|
||||
}
|
||||
intptr_t offset;
|
||||
intptr_t count;
|
||||
stream->ComputeOffsetAndCount(Length(), &offset, &count);
|
||||
if (offset > 0) {
|
||||
jsobj.AddProperty("offset", offset);
|
||||
}
|
||||
if (count < Length()) {
|
||||
jsobj.AddProperty("count", count);
|
||||
}
|
||||
intptr_t limit = offset + count;
|
||||
ASSERT(limit <= Length());
|
||||
{
|
||||
JSONArray jsarr(&jsobj, "elements");
|
||||
Object& element = Object::Handle();
|
||||
for (intptr_t index = offset; index < limit; index++) {
|
||||
element = At(index);
|
||||
jsarr.AddValue(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectPool::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
AddCommonObjectProperties(&jsobj, "Object", ref);
|
||||
|
|
|
@ -4086,6 +4086,50 @@ ISOLATE_UNIT_TEST_CASE(
|
|||
WeakReference_Preserve_ReachableThroughWeakProperty(thread, Heap::kOld);
|
||||
}
|
||||
|
||||
ISOLATE_UNIT_TEST_CASE(WeakArray_New) {
|
||||
WeakArray& array = WeakArray::Handle(WeakArray::New(2, Heap::kNew));
|
||||
Object& target0 = Object::Handle();
|
||||
{
|
||||
HANDLESCOPE(thread);
|
||||
target0 = String::New("0", Heap::kNew);
|
||||
Object& target1 = Object::Handle(String::New("1", Heap::kNew));
|
||||
array.SetAt(0, target0);
|
||||
array.SetAt(1, target1);
|
||||
}
|
||||
|
||||
EXPECT(array.Length() == 2);
|
||||
EXPECT(array.At(0) != Object::null());
|
||||
EXPECT(array.At(1) != Object::null());
|
||||
|
||||
GCTestHelper::CollectNewSpace();
|
||||
|
||||
EXPECT(array.Length() == 2);
|
||||
EXPECT(array.At(0) != Object::null()); // Survives
|
||||
EXPECT(array.At(1) == Object::null()); // Cleared
|
||||
}
|
||||
|
||||
ISOLATE_UNIT_TEST_CASE(WeakArray_Old) {
|
||||
WeakArray& array = WeakArray::Handle(WeakArray::New(2, Heap::kOld));
|
||||
Object& target0 = Object::Handle();
|
||||
{
|
||||
HANDLESCOPE(thread);
|
||||
target0 = String::New("0", Heap::kOld);
|
||||
Object& target1 = Object::Handle(String::New("1", Heap::kOld));
|
||||
array.SetAt(0, target0);
|
||||
array.SetAt(1, target1);
|
||||
}
|
||||
|
||||
EXPECT(array.Length() == 2);
|
||||
EXPECT(array.At(0) != Object::null());
|
||||
EXPECT(array.At(1) != Object::null());
|
||||
|
||||
GCTestHelper::CollectAllGarbage();
|
||||
|
||||
EXPECT(array.Length() == 2);
|
||||
EXPECT(array.At(0) != Object::null()); // Survives
|
||||
EXPECT(array.At(1) == Object::null()); // Cleared
|
||||
}
|
||||
|
||||
static int NumEntries(const FinalizerEntry& entry, intptr_t acc = 0) {
|
||||
if (entry.IsNull()) {
|
||||
return acc;
|
||||
|
|
|
@ -151,6 +151,12 @@ intptr_t UntaggedObject::HeapSizeFromClass(uword tags) const {
|
|||
instance_size = Array::InstanceSize(array_length);
|
||||
break;
|
||||
}
|
||||
case kWeakArrayCid: {
|
||||
const WeakArrayPtr raw_array = static_cast<const WeakArrayPtr>(this);
|
||||
intptr_t array_length = Smi::Value(raw_array->untag()->length());
|
||||
instance_size = WeakArray::InstanceSize(array_length);
|
||||
break;
|
||||
}
|
||||
case kObjectPoolCid: {
|
||||
const ObjectPoolPtr raw_object_pool =
|
||||
static_cast<const ObjectPoolPtr>(this);
|
||||
|
@ -529,6 +535,7 @@ COMPRESSED_VISITOR(Library)
|
|||
COMPRESSED_VISITOR(Namespace)
|
||||
COMPRESSED_VISITOR(KernelProgramInfo)
|
||||
COMPRESSED_VISITOR(WeakSerializationReference)
|
||||
VARIABLE_COMPRESSED_VISITOR(WeakArray, Smi::Value(raw_obj->untag()->length()))
|
||||
COMPRESSED_VISITOR(Type)
|
||||
COMPRESSED_VISITOR(FunctionType)
|
||||
COMPRESSED_VISITOR(RecordType)
|
||||
|
|
|
@ -1713,6 +1713,28 @@ class UntaggedWeakSerializationReference : public UntaggedObject {
|
|||
VISIT_TO(replacement)
|
||||
};
|
||||
|
||||
class UntaggedWeakArray : public UntaggedObject {
|
||||
RAW_HEAP_OBJECT_IMPLEMENTATION(WeakArray);
|
||||
|
||||
COMPRESSED_POINTER_FIELD(WeakArrayPtr, next_seen_by_gc)
|
||||
|
||||
COMPRESSED_SMI_FIELD(SmiPtr, length)
|
||||
VISIT_FROM(length)
|
||||
// Variable length data follows here.
|
||||
COMPRESSED_VARIABLE_POINTER_FIELDS(ObjectPtr, element, data)
|
||||
|
||||
template <typename Table, bool kAllCanonicalObjectsAreIncludedIntoSet>
|
||||
friend class CanonicalSetDeserializationCluster;
|
||||
template <typename Type, typename PtrType>
|
||||
friend class GCLinkedList;
|
||||
friend class GCMarker;
|
||||
template <bool>
|
||||
friend class MarkingVisitorBase;
|
||||
friend class Scavenger;
|
||||
template <bool>
|
||||
friend class ScavengerVisitorBase;
|
||||
};
|
||||
|
||||
class UntaggedCode : public UntaggedObject {
|
||||
RAW_HEAP_OBJECT_IMPLEMENTATION(Code);
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ namespace dart {
|
|||
F(KernelProgramInfo, retained_kernel_blob_) \
|
||||
F(WeakSerializationReference, target_) \
|
||||
F(WeakSerializationReference, replacement_) \
|
||||
F(WeakArray, length_) \
|
||||
F(Code, object_pool_) \
|
||||
F(Code, instructions_) \
|
||||
F(Code, owner_) \
|
||||
|
|
|
@ -267,6 +267,7 @@ class ObjectPointerVisitor;
|
|||
V(UnwindError, "UnwindError") \
|
||||
V(Value, "value") \
|
||||
V(Values, "values") \
|
||||
V(WeakArray, "WeakArray") \
|
||||
V(WeakSerializationReference, "WeakSerializationReference") \
|
||||
V(_AsyncStarStreamController, "_AsyncStarStreamController") \
|
||||
V(_BufferingStreamSubscription, "_BufferingStreamSubscription") \
|
||||
|
|
|
@ -355,6 +355,7 @@ DEFINE_TAGGED_POINTER(Library, Object)
|
|||
DEFINE_TAGGED_POINTER(Namespace, Object)
|
||||
DEFINE_TAGGED_POINTER(KernelProgramInfo, Object)
|
||||
DEFINE_TAGGED_POINTER(WeakSerializationReference, Object)
|
||||
DEFINE_TAGGED_POINTER(WeakArray, Object)
|
||||
DEFINE_TAGGED_POINTER(Code, Object)
|
||||
DEFINE_TAGGED_POINTER(ObjectPool, Object)
|
||||
DEFINE_TAGGED_POINTER(Instructions, Object)
|
||||
|
|
Loading…
Reference in a new issue