diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h index 5aecb4cc45b..6a0a6816a32 100644 --- a/runtime/vm/class_id.h +++ b/runtime/vm/class_id.h @@ -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) \ diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h index 520a50a3940..ad9f9f71280 100644 --- a/runtime/vm/compiler/runtime_api.h +++ b/runtime/vm/compiler/runtime_api.h @@ -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(); diff --git a/runtime/vm/heap/gc_shared.h b/runtime/vm/heap/gc_shared.h index 4d6d0762f66..8264edccc90 100644 --- a/runtime/vm/heap/gc_shared.h +++ b/runtime/vm/heap/gc_shared.h @@ -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) diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc index 58b22bc0df6..0d050029b55 100644 --- a/runtime/vm/heap/heap_test.cc +++ b/runtime/vm/heap/heap_test.cc @@ -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)); } diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc index ab3a0fd2609..5c70fdc524b 100644 --- a/runtime/vm/heap/marker.cc +++ b/runtime/vm/heap/marker.cc @@ -123,14 +123,13 @@ class MarkingVisitorBase : public ObjectPointerVisitor { intptr_t size; if (class_id == kWeakPropertyCid) { - WeakPropertyPtr raw_weak = static_cast(raw_obj); - size = ProcessWeakProperty(raw_weak); + size = ProcessWeakProperty(static_cast(raw_obj)); } else if (class_id == kWeakReferenceCid) { - WeakReferencePtr raw_weak = static_cast(raw_obj); - size = ProcessWeakReference(raw_weak); + size = ProcessWeakReference(static_cast(raw_obj)); + } else if (class_id == kWeakArrayCid) { + size = ProcessWeakArray(static_cast(raw_obj)); } else if (class_id == kFinalizerEntryCid) { - FinalizerEntryPtr raw_weak = static_cast(raw_obj); - size = ProcessFinalizerEntry(raw_weak); + size = ProcessFinalizerEntry(static_cast(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. diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc index ff7ca3f066b..40445773a3c 100644 --- a/runtime/vm/heap/scavenger.cc +++ b/runtime/vm/heap/scavenger.cc @@ -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::ProcessCopied(ObjectPtr raw_obj) { return raw_weak->untag()->HeapSize(); } } + } else if (UNLIKELY(class_id == kWeakArrayCid)) { + WeakArrayPtr raw_weak = static_cast(raw_obj); + delayed_.weak_arrays.Enqueue(raw_weak); + return raw_weak->untag()->HeapSize(); } else if (UNLIKELY(class_id == kFinalizerEntryCid)) { FinalizerEntryPtr raw_entry = static_cast(raw_obj); ASSERT(IsNotForwarding(raw_entry)); @@ -1484,7 +1490,7 @@ void ScavengerVisitorBase::MournWeakProperties() { } template -void ScavengerVisitorBase::MournOrUpdateWeakReferences() { +void ScavengerVisitorBase::MournWeakReferences() { ASSERT(!scavenger_->abort_); // The queued weak references at this point either should have their target @@ -1506,6 +1512,27 @@ void ScavengerVisitorBase::MournOrUpdateWeakReferences() { } } +template +void ScavengerVisitorBase::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 ScavengerVisitorBase::ForwardOrSetNullIfCollected( diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index e9640b4f218..a0757bb2c73 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -187,6 +187,7 @@ ClassPtr Object::unhandled_exception_class_ = static_cast(RAW_NULL); ClassPtr Object::unwind_error_class_ = static_cast(RAW_NULL); ClassPtr Object::weak_serialization_reference_class_ = static_cast(RAW_NULL); +ClassPtr Object::weak_array_class_ = static_cast(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(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( + 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; diff --git a/runtime/vm/object.h b/runtime/vm/object.h index e6a639d56c8..b832a1a5b3d 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -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(index); + } + void SetAtRelease(intptr_t index, const Object& value) const { + untag()->set_element(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()); } diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc index dad29ac5a2b..7f42d12994c 100644 --- a/runtime/vm/object_graph_copy.cc +++ b/runtime/vm/object_graph_copy.cc @@ -87,6 +87,7 @@ V(UnlinkedCall) \ V(UnwindError) \ V(UserTag) \ + V(WeakArray) \ V(WeakSerializationReference) namespace dart { diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc index 7edada71f48..ded3bd2c07c 100644 --- a/runtime/vm/object_service.cc +++ b/runtime/vm/object_service.cc @@ -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); diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc index 23a6d33154e..4dccb7795e5 100644 --- a/runtime/vm/object_test.cc +++ b/runtime/vm/object_test.cc @@ -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; diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc index 2f048f13a23..dd03ee02910 100644 --- a/runtime/vm/raw_object.cc +++ b/runtime/vm/raw_object.cc @@ -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(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(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) diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 7a7432b97a9..267b369396e 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -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 + friend class CanonicalSetDeserializationCluster; + template + friend class GCLinkedList; + friend class GCMarker; + template + friend class MarkingVisitorBase; + friend class Scavenger; + template + friend class ScavengerVisitorBase; +}; + class UntaggedCode : public UntaggedObject { RAW_HEAP_OBJECT_IMPLEMENTATION(Code); diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc index 61b4cffa742..d90424241de 100644 --- a/runtime/vm/raw_object_fields.cc +++ b/runtime/vm/raw_object_fields.cc @@ -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_) \ diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h index e136c18f82f..b7ed2be230d 100644 --- a/runtime/vm/symbols.h +++ b/runtime/vm/symbols.h @@ -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") \ diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h index 529e3b2464c..c0327529104 100644 --- a/runtime/vm/tagged_pointer.h +++ b/runtime/vm/tagged_pointer.h @@ -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)