From 25fd0200ef188d45e4d083158098e30131aca339 Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Wed, 10 Feb 2021 01:21:07 +0000 Subject: [PATCH] [vm] Replace recanonicalization in primary snapshots with weak constant tables. TEST=ci Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Icc4a3ebf861dca5172a0cfa2cd2eea266e814d0c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/181480 Commit-Queue: Ryan Macnak Reviewed-by: Siva Annamalai Reviewed-by: Alexander Markov --- runtime/vm/class_id.h | 4 +- runtime/vm/clustered_snapshot.cc | 230 +++++------------- runtime/vm/clustered_snapshot.h | 19 +- runtime/vm/compiler/aot/precompiler.cc | 11 +- .../vm/compiler/runtime_offsets_extracted.h | 44 ++-- runtime/vm/hash_table.h | 35 ++- runtime/vm/object.cc | 33 ++- runtime/vm/object.h | 95 ++------ runtime/vm/raw_object.cc | 6 +- runtime/vm/raw_object.h | 8 +- runtime/vm/raw_object_fields.cc | 5 +- runtime/vm/stack_frame.cc | 5 +- runtime/vm/symbols.h | 1 + 13 files changed, 180 insertions(+), 316 deletions(-) diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h index 5fb3b61e3e3..ed8a2373a47 100644 --- a/runtime/vm/class_id.h +++ b/runtime/vm/class_id.h @@ -28,6 +28,7 @@ typedef uint16_t ClassIdTagType; V(Library) \ V(Namespace) \ V(KernelProgramInfo) \ + V(WeakSerializationReference) \ V(Code) \ V(Instructions) \ V(InstructionsSection) \ @@ -87,8 +88,7 @@ typedef uint16_t ClassIdTagType; V(LinkedHashMap) \ V(FutureOr) \ V(UserTag) \ - V(TransferableTypedData) \ - V(WeakSerializationReference) + V(TransferableTypedData) #define CLASS_LIST_ARRAYS(V) \ V(Array) \ diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc index c52c61fb03c..805f9dc1831 100644 --- a/runtime/vm/clustered_snapshot.cc +++ b/runtime/vm/clustered_snapshot.cc @@ -1997,113 +1997,44 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster { class WeakSerializationReferenceSerializationCluster : public SerializationCluster { public: - WeakSerializationReferenceSerializationCluster(Zone* zone, Heap* heap) + WeakSerializationReferenceSerializationCluster() : SerializationCluster( "WeakSerializationReference", - compiler::target::WeakSerializationReference::InstanceSize()), - heap_(ASSERT_NOTNULL(heap)), - objects_(zone, 0), - canonical_wsrs_(zone, 0), - canonical_wsr_map_(zone) {} + compiler::target::WeakSerializationReference::InstanceSize()) {} ~WeakSerializationReferenceSerializationCluster() {} void Trace(Serializer* s, ObjectPtr object) { ASSERT(s->kind() == Snapshot::kFullAOT); - // Make sure we don't trace again after choosing canonical WSRs. - ASSERT(!have_canonicalized_wsrs_); - - auto const ref = WeakSerializationReference::RawCast(object); - objects_.Add(ref); - // We do _not_ push the target, since this is not a strong reference. + WeakSerializationReferencePtr weak = + WeakSerializationReference::RawCast(object); + objects_.Add(weak); } + intptr_t FinalizeWeak(Serializer* s) { return objects_.length(); } + void WriteAlloc(Serializer* s) { - ASSERT(s->kind() == Snapshot::kFullAOT); - ASSERT(have_canonicalized_wsrs_); - s->WriteCid(kWeakSerializationReferenceCid); - s->WriteUnsigned(WrittenCount()); - - // Set up references for those objects that will be written. - for (auto const& ref : canonical_wsrs_) { - s->AssignRef(ref); - } - - // In precompiled mode, set the object ID of each non-canonical WSR to - // its canonical counterpart's object ID. This ensures that any reference to - // it is serialized as a reference to the canonicalized one. - for (auto const& ref : objects_) { - ASSERT(IsReachableReference(heap_->GetObjectId(ref))); - if (ShouldDrop(ref)) { - // For dropped references, reset their ID to be the unreachable - // reference value, so RefId retrieves the target ID instead. - heap_->SetObjectId(ref, kUnreachableReference); - continue; - } - // Skip if we've already allocated a reference (this is a canonical WSR). - if (IsAllocatedReference(heap_->GetObjectId(ref))) continue; - auto const target_cid = WeakSerializationReference::TargetClassIdOf(ref); - ASSERT(canonical_wsr_map_.HasKey(target_cid)); - auto const canonical_index = canonical_wsr_map_.Lookup(target_cid) - 1; - auto const canonical_wsr = objects_[canonical_index]; - // Set the object ID of this non-canonical WSR to the same as its - // canonical WSR entry, so we'll reference the canonical WSR when - // serializing references to this object. - auto const canonical_heap_id = heap_->GetObjectId(canonical_wsr); - ASSERT(IsAllocatedReference(canonical_heap_id)); - heap_->SetObjectId(ref, canonical_heap_id); - } } - void WriteFill(Serializer* s) { - ASSERT(s->kind() == Snapshot::kFullAOT); - for (auto const& ref : canonical_wsrs_) { - AutoTraceObject(ref); - - // In precompiled mode, we drop the reference to the target and only - // keep the class ID. - s->WriteCid(WeakSerializationReference::TargetClassIdOf(ref)); - } - } - - // Picks a WSR for each target class ID to be canonical. Should only be run - // after all objects have been traced. - void CanonicalizeReferences() { - ASSERT(!have_canonicalized_wsrs_); + void ForwardWeakRefs(Serializer* s) { + Heap* heap = s->heap(); for (intptr_t i = 0; i < objects_.length(); i++) { - auto const ref = objects_[i]; - if (ShouldDrop(ref)) continue; - auto const target_cid = WeakSerializationReference::TargetClassIdOf(ref); - if (canonical_wsr_map_.HasKey(target_cid)) continue; - canonical_wsr_map_.Insert(target_cid, i + 1); - canonical_wsrs_.Add(ref); + WeakSerializationReferencePtr weak = objects_[i]; + + intptr_t id = heap->GetObjectId(weak->untag()->target()); + if (id == kUnreachableReference) { + id = heap->GetObjectId(weak->untag()->replacement()); + ASSERT(id != kUnreachableReference); + } + ASSERT(IsAllocatedReference(id)); + heap->SetObjectId(weak, id); } - have_canonicalized_wsrs_ = true; } - intptr_t WrittenCount() const { - ASSERT(have_canonicalized_wsrs_); - return canonical_wsrs_.length(); - } - - intptr_t DroppedCount() const { return TotalCount() - WrittenCount(); } - - intptr_t TotalCount() const { return objects_.length(); } + void WriteFill(Serializer* s) {} private: - // Returns whether a WSR should be dropped due to its target being reachable - // via strong references. WSRs only wrap heap objects, so we can just retrieve - // the object ID from the heap directly. - bool ShouldDrop(WeakSerializationReferencePtr ref) const { - auto const target = WeakSerializationReference::TargetOf(ref); - return IsReachableReference(heap_->GetObjectId(target)); - } - - Heap* const heap_; GrowableArray objects_; - GrowableArray canonical_wsrs_; - IntMap canonical_wsr_map_; - bool have_canonicalized_wsrs_ = false; }; #endif @@ -2115,29 +2046,8 @@ class WeakSerializationReferenceDeserializationCluster : DeserializationCluster("WeakSerializationReference") {} ~WeakSerializationReferenceDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool is_canonical) { - start_index_ = d->next_index(); - PageSpace* old_space = d->heap()->old_space(); - const intptr_t count = d->ReadUnsigned(); - - for (intptr_t i = 0; i < count; i++) { - auto ref = AllocateUninitialized( - old_space, WeakSerializationReference::InstanceSize()); - d->AssignRef(ref); - } - - stop_index_ = d->next_index(); - } - - void ReadFill(Deserializer* d, bool is_canonical) { - for (intptr_t id = start_index_; id < stop_index_; id++) { - auto const ref = static_cast(d->Ref(id)); - Deserializer::InitializeHeader( - ref, kWeakSerializationReferenceCid, - WeakSerializationReference::InstanceSize()); - ref->untag()->cid_ = d->ReadCid(); - } - } + void ReadAlloc(Deserializer* d, bool stamp_canonical) {} + void ReadFill(Deserializer* d, bool stamp_canonical) {} }; #endif @@ -5008,7 +4918,7 @@ class VMDeserializationRoots : public DeserializationRoots { public: VMDeserializationRoots() : symbol_table_(Array::Handle()) {} - void AddBaseObjects(Deserializer* d) { + bool AddBaseObjects(Deserializer* d) { // These objects are always allocated by Object::InitOnce, so they are not // written into the snapshot. @@ -5057,6 +4967,8 @@ class VMDeserializationRoots : public DeserializationRoots { d->AddBaseObject(StubCode::EntryAt(i).ptr()); } } + + return true; // primary } void ReadRoots(Deserializer* d) { @@ -5101,43 +5013,26 @@ class ProgramSerializationRoots : public SerializationRoots { ObjectStore* object_store) : base_objects_(base_objects), object_store_(object_store), - saved_symbol_table_(Array::Handle()), - saved_canonical_types_(Array::Handle()), - saved_canonical_function_types_(Array::Handle()), - saved_canonical_type_parameters_(Array::Handle()), - saved_canonical_type_arguments_(Array::Handle()), dispatch_table_entries_(Array::Handle()) { - saved_symbol_table_ = object_store->symbol_table(); - object_store->set_symbol_table( - Array::Handle(HashTables::New(4))); - - saved_canonical_types_ = object_store->canonical_types(); - object_store->set_canonical_types( - Array::Handle(HashTables::New(4))); - - saved_canonical_function_types_ = object_store->canonical_function_types(); - object_store->set_canonical_function_types( - Array::Handle(HashTables::New(4))); - - saved_canonical_type_parameters_ = - object_store->canonical_type_parameters(); - object_store->set_canonical_type_parameters( - Array::Handle(HashTables::New(4))); - - saved_canonical_type_arguments_ = object_store->canonical_type_arguments(); - object_store->set_canonical_type_arguments( - Array::Handle(HashTables::New(4))); - } - ~ProgramSerializationRoots() { - object_store_->set_symbol_table(saved_symbol_table_); - object_store_->set_canonical_types(saved_canonical_types_); - object_store_->set_canonical_function_types( - saved_canonical_function_types_); - object_store_->set_canonical_type_parameters( - saved_canonical_type_parameters_); - object_store_->set_canonical_type_arguments( - saved_canonical_type_arguments_); +#if defined(DART_PRECOMPILER) + if (FLAG_precompiled_mode) { + // Elements of constant tables are treated as weak so literals used only + // in deferred libraries do not end up in the main snapshot. + Array& table = Array::Handle(); + table = object_store->symbol_table(); + HashTables::Weaken(table); + table = object_store->canonical_types(); + HashTables::Weaken(table); + table = object_store->canonical_function_types(); + HashTables::Weaken(table); + table = object_store->canonical_type_parameters(); + HashTables::Weaken(table); + table = object_store->canonical_type_arguments(); + HashTables::Weaken(table); + } +#endif } + ~ProgramSerializationRoots() {} void AddBaseObjects(Serializer* s) { if (base_objects_ == nullptr) { @@ -5192,11 +5087,6 @@ class ProgramSerializationRoots : public SerializationRoots { private: ZoneGrowableArray* base_objects_; ObjectStore* object_store_; - Array& saved_symbol_table_; - Array& saved_canonical_types_; - Array& saved_canonical_function_types_; - Array& saved_canonical_type_parameters_; - Array& saved_canonical_type_arguments_; Array& dispatch_table_entries_; }; #endif // !DART_PRECOMPILED_RUNTIME @@ -5206,12 +5096,13 @@ class ProgramDeserializationRoots : public DeserializationRoots { explicit ProgramDeserializationRoots(ObjectStore* object_store) : object_store_(object_store) {} - void AddBaseObjects(Deserializer* d) { + bool AddBaseObjects(Deserializer* d) { // N.B.: Skipping index 0 because ref 0 is illegal. const Array& base_objects = Object::vm_isolate_snapshot_object_table(); for (intptr_t i = kFirstReference; i < base_objects.Length(); i++) { d->AddBaseObject(base_objects.At(i)); } + return true; // primary } void ReadRoots(Deserializer* d) { @@ -5312,12 +5203,13 @@ class UnitDeserializationRoots : public DeserializationRoots { public: explicit UnitDeserializationRoots(const LoadingUnit& unit) : unit_(unit) {} - void AddBaseObjects(Deserializer* d) { + bool AddBaseObjects(Deserializer* d) { const Array& base_objects = Array::Handle(LoadingUnit::Handle(unit_.parent()).base_objects()); for (intptr_t i = kFirstReference; i < base_objects.Length(); i++) { d->AddBaseObject(base_objects.At(i)); } + return false; // primary } void ReadRoots(Deserializer* d) { @@ -5326,7 +5218,8 @@ class UnitDeserializationRoots : public DeserializationRoots { for (intptr_t id = deferred_start_index_; id < deferred_stop_index_; id++) { CodePtr code = static_cast(d->Ref(id)); d->ReadInstructions(code, false); - if (code->untag()->owner_->IsFunction()) { + if (code->untag()->owner_->IsHeapObject() && + code->untag()->owner_->IsFunction()) { FunctionPtr func = static_cast(code->untag()->owner_); uword entry_point = code->untag()->entry_point_; ASSERT(entry_point != 0); @@ -5731,8 +5624,7 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) { case kWeakSerializationReferenceCid: #if defined(DART_PRECOMPILER) ASSERT(kind_ == Snapshot::kFullAOT); - return new (Z) - WeakSerializationReferenceSerializationCluster(zone_, heap_); + return new (Z) WeakSerializationReferenceSerializationCluster(); #endif default: break; @@ -5988,16 +5880,10 @@ ZoneGrowableArray* Serializer::Serialize(SerializationRoots* roots) { } #if defined(DART_PRECOMPILER) - // Before we finalize the count of written objects, pick canonical versions - // of WSR objects that will be serialized and then remove any non-serialized - // or non-canonical WSR objects from that count. if (auto const cluster = reinterpret_cast( clusters_by_cid_[kWeakSerializationReferenceCid])) { - cluster->CanonicalizeReferences(); - auto const dropped_count = cluster->DroppedCount(); - ASSERT(dropped_count == 0 || kind() == Snapshot::kFullAOT); - num_written_objects_ -= dropped_count; + num_written_objects_ -= cluster->FinalizeWeak(this); } #endif @@ -6038,6 +5924,12 @@ ZoneGrowableArray* Serializer::Serialize(SerializationRoots* roots) { ASSERT(objects_->length() == num_objects); #if defined(DART_PRECOMPILER) + if (auto cluster = + reinterpret_cast( + clusters_by_cid_[kWeakSerializationReferenceCid])) { + cluster->ForwardWeakRefs(this); + } + // When writing snapshot profile, we want to retain some of the program // structure information (e.g. information about libraries, classes and // functions - even if it was dropped when writing snapshot itself). @@ -6760,6 +6652,7 @@ void Deserializer::Deserialize(DeserializationRoots* roots) { ASSERT_EQUAL(initial_field_table_->NumFieldIds(), initial_field_table_len); } + bool primary; { // The deserializer initializes objects without using the write barrier, // partly for speed since we know all the deserialized objects will be @@ -6777,7 +6670,7 @@ void Deserializer::Deserialize(DeserializationRoots* roots) { NoSafepointScope no_safepoint; refs_ = refs.ptr(); - roots->AddBaseObjects(this); + primary = roots->AddBaseObjects(this); if (num_base_objects_ != (next_ref_index_ - kFirstReference)) { FATAL2("Snapshot expects %" Pd @@ -6813,8 +6706,8 @@ void Deserializer::Deserialize(DeserializationRoots* roots) { { TIMELINE_DURATION(thread(), Isolate, "ReadFill"); for (intptr_t i = 0; i < num_canonical_clusters_; i++) { - TIMELINE_DURATION(thread(), Isolate, canonical_clusters_[i]->name()); - canonical_clusters_[i]->ReadFill(this, /*is_canonical*/ true); + bool stamp_canonical = primary; + canonical_clusters_[i]->ReadFill(this, stamp_canonical); #if defined(DEBUG) int32_t section_marker = Read(); ASSERT(section_marker == kSectionMarker); @@ -6858,7 +6751,8 @@ void Deserializer::Deserialize(DeserializationRoots* roots) { TIMELINE_DURATION(thread(), Isolate, "PostLoad"); for (intptr_t i = 0; i < num_canonical_clusters_; i++) { TIMELINE_DURATION(thread(), Isolate, canonical_clusters_[i]->name()); - canonical_clusters_[i]->PostLoad(this, refs, /*is_canonical*/ true); + bool canonicalize = !primary; + canonical_clusters_[i]->PostLoad(this, refs, canonicalize); } for (intptr_t i = 0; i < num_clusters_; i++) { TIMELINE_DURATION(thread(), Isolate, clusters_[i]->name()); diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h index d69e444330e..fcd5d905bb2 100644 --- a/runtime/vm/clustered_snapshot.h +++ b/runtime/vm/clustered_snapshot.h @@ -163,7 +163,11 @@ class SerializationRoots { class DeserializationRoots { public: virtual ~DeserializationRoots() {} - virtual void AddBaseObjects(Deserializer* deserializer) = 0; + // Returns true if these roots are the first snapshot loaded into a heap, and + // so can assume any canonical objects don't already exist. Returns false if + // some other snapshot may be loaded before these roots, and so written + // canonical objects need to run canoncalization during load. + virtual bool AddBaseObjects(Deserializer* deserializer) = 0; virtual void ReadRoots(Deserializer* deserializer) = 0; virtual void PostLoad(Deserializer* deserializer, const Array& refs) = 0; }; @@ -412,17 +416,8 @@ class Serializer : public ThreadStackResource { return -id; } ASSERT(!IsArtificialReference(id)); - if (IsAllocatedReference(id)) return id; - if (object->IsWeakSerializationReference()) { - // If a reachable WSR has an object ID of 0, then its target was marked - // for serialization due to reachable strong references and the WSR will - // be dropped instead. Thus, we change the reference to the WSR to a - // direct reference to the serialized target. - auto const ref = WeakSerializationReference::RawCast(object); - auto const target = WeakSerializationReference::TargetOf(ref); - auto const target_id = heap_->GetObjectId(target); - ASSERT(IsAllocatedReference(target_id)); - return target_id; + if (IsAllocatedReference(id)) { + return id; } if (object->IsCode() && !Snapshot::IncludesCode(kind_)) { return RefId(Object::null()); diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc index 855cdca1bf8..50a67e9191c 100644 --- a/runtime/vm/compiler/aot/precompiler.cc +++ b/runtime/vm/compiler/aot/precompiler.cc @@ -1749,7 +1749,8 @@ void Precompiler::DropFunctions() { // Wrap the owner of the code object in case the code object will be // serialized but the function object will not. owner = code.owner(); - owner = WeakSerializationReference::Wrap(Z, owner); + owner = WeakSerializationReference::New( + owner, Smi::Handle(Smi::New(owner.GetClassId()))); code.set_owner(owner); } dropped_function_count_++; @@ -2287,6 +2288,14 @@ void Precompiler::DropClasses() { ClassTable* class_table = IG->class_table(); intptr_t num_cids = class_table->NumCids(); + for (intptr_t cid = 0; cid < num_cids; cid++) { + if (!class_table->IsValidIndex(cid)) continue; + if (!class_table->HasValidClassAt(cid)) continue; + cls = class_table->At(cid); + constants = cls.constants(); + HashTables::Weaken(constants); + } + for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { if (!class_table->IsValidIndex(cid)) continue; if (!class_table->HasValidClassAt(cid)) continue; diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index c4743e3dbb3..35ef1e360bf 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -544,7 +544,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 12; static constexpr dart::compiler::target::word UserTag_InstanceSize = 12; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 16; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 8; + WeakSerializationReference_InstanceSize = 12; #endif // defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS) @@ -1082,7 +1082,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24; static constexpr dart::compiler::target::word UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 16; + WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_IA32) && !defined(DART_COMPRESSED_POINTERS) @@ -1609,7 +1609,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 12; static constexpr dart::compiler::target::word UserTag_InstanceSize = 12; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 16; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 8; + WeakSerializationReference_InstanceSize = 12; #endif // defined(TARGET_ARCH_IA32) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS) @@ -2148,7 +2148,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24; static constexpr dart::compiler::target::word UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 16; + WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS) @@ -2686,7 +2686,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24; static constexpr dart::compiler::target::word UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 16; + WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS) @@ -3225,7 +3225,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24; static constexpr dart::compiler::target::word UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 16; + WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS) #else // !defined(PRODUCT) @@ -3751,7 +3751,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 12; static constexpr dart::compiler::target::word UserTag_InstanceSize = 12; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 16; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 8; + WeakSerializationReference_InstanceSize = 12; #endif // defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS) @@ -4283,7 +4283,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24; static constexpr dart::compiler::target::word UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 16; + WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_IA32) && !defined(DART_COMPRESSED_POINTERS) @@ -4804,7 +4804,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 12; static constexpr dart::compiler::target::word UserTag_InstanceSize = 12; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 16; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 8; + WeakSerializationReference_InstanceSize = 12; #endif // defined(TARGET_ARCH_IA32) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS) @@ -5337,7 +5337,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24; static constexpr dart::compiler::target::word UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 16; + WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS) @@ -5869,7 +5869,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24; static constexpr dart::compiler::target::word UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 16; + WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS) @@ -6402,7 +6402,7 @@ static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24; static constexpr dart::compiler::target::word UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - WeakSerializationReference_InstanceSize = 16; + WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS) #endif // !defined(PRODUCT) @@ -6997,7 +6997,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 12; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 16; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 8; + AOT_WeakSerializationReference_InstanceSize = 12; #endif // defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS) @@ -7592,7 +7592,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 16; + AOT_WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_IA32) && !defined(DART_COMPRESSED_POINTERS) @@ -8191,7 +8191,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 16; + AOT_WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS) @@ -8786,7 +8786,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 16; + AOT_WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS) @@ -9382,7 +9382,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 16; + AOT_WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS) #else // !defined(PRODUCT) @@ -9968,7 +9968,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 12; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 16; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 8; + AOT_WeakSerializationReference_InstanceSize = 12; #endif // defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS) @@ -10556,7 +10556,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 16; + AOT_WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_IA32) && !defined(DART_COMPRESSED_POINTERS) @@ -11148,7 +11148,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 16; + AOT_WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS) @@ -11736,7 +11736,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 16; + AOT_WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS) #if defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS) @@ -12325,7 +12325,7 @@ static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize = 32; static constexpr dart::compiler::target::word - AOT_WeakSerializationReference_InstanceSize = 16; + AOT_WeakSerializationReference_InstanceSize = 24; #endif // defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS) #endif // !defined(PRODUCT) diff --git a/runtime/vm/hash_table.h b/runtime/vm/hash_table.h index cb6d01d7dfa..ef895561b43 100644 --- a/runtime/vm/hash_table.h +++ b/runtime/vm/hash_table.h @@ -152,7 +152,9 @@ class HashTable : public ValueObject { template intptr_t FindKey(const Key& key) const { const intptr_t num_entries = NumEntries(); - ASSERT(NumOccupied() < num_entries); + // Deleted may undercount due to weak references used during AOT + // snapshotting. + NOT_IN_PRECOMPILED(ASSERT(NumOccupied() < num_entries)); // TODO(koda): Add salt. NOT_IN_PRODUCT(intptr_t collisions = 0;) uword hash = KeyTraits::Hash(key); @@ -188,7 +190,9 @@ class HashTable : public ValueObject { bool FindKeyOrDeletedOrUnused(const Key& key, intptr_t* entry) const { const intptr_t num_entries = NumEntries(); ASSERT(entry != NULL); - ASSERT(NumOccupied() < num_entries); + // Deleted may undercount due to weak references used during AOT + // snapshotting. + NOT_IN_PRECOMPILED(ASSERT(NumOccupied() < num_entries)); NOT_IN_PRODUCT(intptr_t collisions = 0;) uword hash = KeyTraits::Hash(key); ASSERT(Utils::IsPowerOfTwo(num_entries)); @@ -236,7 +240,9 @@ class HashTable : public ValueObject { } InternalSetKey(entry, key); ASSERT(IsOccupied(entry)); - ASSERT(NumOccupied() < NumEntries()); + // Deleted may undercount due to weak references used during AOT + // snapshotting. + NOT_IN_PRECOMPILED(ASSERT(NumOccupied() < NumEntries())); } const Object& UnusedMarker() const { return Object::transition_sentinel(); } @@ -258,7 +264,8 @@ class HashTable : public ValueObject { } ObjectPtr GetPayload(intptr_t entry, intptr_t component) const { ASSERT(IsOccupied(entry)); - return data_->At(PayloadIndex(entry, component)); + return WeakSerializationReference::Unwrap( + data_->At(PayloadIndex(entry, component))); } void UpdatePayload(intptr_t entry, intptr_t component, @@ -371,7 +378,7 @@ class HashTable : public ValueObject { } ObjectPtr InternalGetKey(intptr_t entry) const { - return data_->At(KeyIndex(entry)); + return WeakSerializationReference::Unwrap(data_->At(KeyIndex(entry))); } void InternalSetKey(intptr_t entry, const Object& key) const { @@ -531,6 +538,22 @@ class HashTables : public AllStatic { } return result.ptr(); } + +#if defined(DART_PRECOMPILER) + // Replace elements of this set with WeakSerializationReferences. + static void Weaken(const Array& table) { + if (!table.IsNull()) { + Object& element = Object::Handle(); + for (intptr_t i = 0; i < table.Length(); i++) { + element = table.At(i); + if (!element.IsSmi()) { + element = WeakSerializationReference::New(element, table); + table.SetAt(i, element); + } + } + } + } +#endif }; template @@ -724,7 +747,7 @@ class UnorderedHashSet : public HashSet > { void Dump() const { Object& entry = Object::Handle(); for (intptr_t i = 0; i < this->data_->Length(); i++) { - entry = this->data_->At(i); + entry = WeakSerializationReference::Unwrap(this->data_->At(i)); if (entry.ptr() == BaseSet::UnusedMarker().ptr() || entry.ptr() == BaseSet::DeletedMarker().ptr() || entry.IsSmi()) { // empty, deleted, num_used/num_deleted diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 0626dc154d4..dcb54c36cf5 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -1325,6 +1325,7 @@ void Object::FinalizeVMIsolate(IsolateGroup* isolate_group) { SET_CLASS_NAME(library, LibraryClass); SET_CLASS_NAME(namespace, Namespace); SET_CLASS_NAME(kernel_program_info, KernelProgramInfo); + SET_CLASS_NAME(weak_serialization_reference, WeakSerializationReference); SET_CLASS_NAME(code, Code); SET_CLASS_NAME(instructions, Instructions); SET_CLASS_NAME(instructions_section, InstructionsSection); @@ -4767,6 +4768,8 @@ const char* Class::GenerateUserVisibleName() const { return Symbols::Namespace().ToCString(); case kKernelProgramInfoCid: return Symbols::KernelProgramInfo().ToCString(); + case kWeakSerializationReferenceCid: + return Symbols::WeakSerializationReference().ToCString(); case kCodeCid: return Symbols::Code().ToCString(); case kInstructionsCid: @@ -16027,26 +16030,14 @@ ICDataPtr ICData::Clone(const ICData& from) { #endif const char* WeakSerializationReference::ToCString() const { -#if defined(DART_PRECOMPILED_RUNTIME) - return Symbols::OptimizedOut().ToCString(); -#else return Object::Handle(target()).ToCString(); -#endif } -#if defined(DART_PRECOMPILER) -bool WeakSerializationReference::CanWrap(const Object& object) { - // Currently we do not wrap the null object (which cannot be dropped from - // snapshots), non-heap objects, and WSRs (as there is no point in deeply - // nesting them). We also only wrap objects in the precompiler. - return FLAG_precompiled_mode && !object.IsNull() && - object.ptr()->IsHeapObject() && !object.IsWeakSerializationReference(); -} - -ObjectPtr WeakSerializationReference::Wrap(Zone* zone, const Object& target) { - if (!CanWrap(target)) return target.ptr(); +WeakSerializationReferencePtr WeakSerializationReference::New( + const Object& target, + const Object& replacement) { ASSERT(Object::weak_serialization_reference_class() != Class::null()); - WeakSerializationReference& result = WeakSerializationReference::Handle(zone); + WeakSerializationReference& result = WeakSerializationReference::Handle(); { ObjectPtr raw = Object::Allocate(WeakSerializationReference::kClassId, WeakSerializationReference::InstanceSize(), @@ -16055,10 +16046,10 @@ ObjectPtr WeakSerializationReference::Wrap(Zone* zone, const Object& target) { result ^= raw; result.untag()->set_target(target.ptr()); + result.untag()->set_replacement(replacement.ptr()); } return result.ptr(); } -#endif #if defined(INCLUDE_IL_PRINTER) Code::Comments& Code::Comments::New(intptr_t count) { @@ -24772,6 +24763,7 @@ const char* StackTrace::ToCString() const { auto const T = Thread::Current(); auto const zone = T->zone(); auto& stack_trace = StackTrace::Handle(zone, this->ptr()); + auto& owner = Object::Handle(zone); auto& function = Function::Handle(zone); auto& code_object = Object::Handle(zone); auto& code = Code::Handle(zone); @@ -24861,7 +24853,12 @@ const char* StackTrace::ToCString() const { ASSERT(code_object.IsCode()); code ^= code_object.ptr(); ASSERT(code.IsFunctionCode()); - function = code.function(); + owner = code.owner(); + if (owner.IsFunction()) { + function ^= owner.ptr(); + } else { + function = Function::null(); + } const uword pc = code.PayloadStart() + pc_offset; // If the function is not to be shown, skip. diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 6449bf20ad2..0739a206e5f 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -5853,87 +5853,32 @@ class ExceptionHandlers : public Object { // // Current uses of WSRs: // * Code::owner_ +// * Canonical table elements class WeakSerializationReference : public Object { public: ObjectPtr target() const { return TargetOf(ptr()); } - static ObjectPtr TargetOf(const WeakSerializationReferencePtr raw) { -#if defined(DART_PRECOMPILED_RUNTIME) - // WSRs in the precompiled runtime only contain some remaining info about - // their old target, not a reference to the target itself.. - return Object::null(); -#else - // Outside the precompiled runtime, they should always have a target. - ASSERT(raw->untag()->target() != Object::null()); - return raw->untag()->target(); -#endif + static ObjectPtr TargetOf(const WeakSerializationReferencePtr obj) { + return obj->untag()->target(); } - classid_t TargetClassId() const { return TargetClassIdOf(ptr()); } - static classid_t TargetClassIdOf(const WeakSerializationReferencePtr raw) { -#if defined(DART_PRECOMPILED_RUNTIME) - // No new instances of WSRs are created in the precompiled runtime, so - // this instance came from deserialization and thus must be the empty WSR. - return raw->untag()->cid_; -#else - return TargetOf(raw)->GetClassId(); -#endif - } - - static ObjectPtr Unwrap(const Object& obj) { return Unwrap(obj.ptr()); } - // Gets the underlying object from a WSR, or the original object if it is - // not one. Notably, Unwrap(Wrap(r)) == r for all raw objects r, whether - // CanWrap(r) or not. However, this will not hold if a serialization and - // deserialization step is put between the two calls. static ObjectPtr Unwrap(ObjectPtr obj) { - if (!obj->IsWeakSerializationReference()) return obj; - return TargetOf(static_cast(obj)); - } - - // An Unwrap that only unwraps if there's a valid target, otherwise the - // WSR is returned. Useful for cases where we want to call Object methods - // like ToCString() on whatever non-null object we can get. - static ObjectPtr UnwrapIfTarget(const Object& obj) { - return UnwrapIfTarget(obj.ptr()); - } - static ObjectPtr UnwrapIfTarget(ObjectPtr raw) { -#if defined(DART_PRECOMPILED_RUNTIME) - // In the precompiled runtime, WSRs never have a target so we always return - // the argument. - return raw; -#else - if (!raw->IsWeakSerializationReference()) return raw; - // Otherwise, they always do. - return TargetOf(WeakSerializationReference::RawCast(raw)); +#if defined(DART_PRECOMPILER) + if (obj->IsHeapObject() && obj->IsWeakSerializationReference()) { + return TargetOf(static_cast(obj)); + } #endif + return obj; } - - static classid_t UnwrappedClassIdOf(const Object& obj) { - return UnwrappedClassIdOf(obj.ptr()); - } - // Gets the class ID of the underlying object from a WSR, or the class ID of - // the object if it is not one. - // - // UnwrappedClassOf(Wrap(r)) == UnwrappedClassOf(r) for all raw objects r, - // whether CanWrap(r) or not. Unlike Unwrap, this is still true even if - // there is a serialization and deserialization step between the two calls, - // since that information is saved in the serialized WSR. - static classid_t UnwrappedClassIdOf(ObjectPtr obj) { - if (!obj->IsWeakSerializationReference()) return obj->GetClassId(); - return TargetClassIdOf(WeakSerializationReference::RawCast(obj)); - } + static ObjectPtr Unwrap(const Object& obj) { return Unwrap(obj.ptr()); } + static ObjectPtr UnwrapIfTarget(ObjectPtr obj) { return Unwrap(obj); } + static ObjectPtr UnwrapIfTarget(const Object& obj) { return Unwrap(obj); } static intptr_t InstanceSize() { return RoundedAllocationSize(sizeof(UntaggedWeakSerializationReference)); } -#if defined(DART_PRECOMPILER) - // Returns true if a new WSR would be created when calling Wrap. - static bool CanWrap(const Object& object); - - // This returns ObjectPtr, not WeakSerializationReferencePtr, because - // target.ptr() is returned when CanWrap(target) is false. - static ObjectPtr Wrap(Zone* zone, const Object& target); -#endif + static WeakSerializationReferencePtr New(const Object& target, + const Object& replacement); private: FINAL_HEAP_OBJECT_IMPLEMENTATION(WeakSerializationReference, Object); @@ -6294,17 +6239,21 @@ class Code : public Object { // while generating the snapshot. FunctionPtr function() const { ASSERT(IsFunctionCode()); - return Function::RawCast( - WeakSerializationReference::Unwrap(untag()->owner())); + return Function::RawCast(owner()); } - ObjectPtr owner() const { return untag()->owner(); } + ObjectPtr owner() const { + return WeakSerializationReference::Unwrap(untag()->owner()); + } void set_owner(const Object& owner) const; classid_t OwnerClassId() const { return OwnerClassIdOf(ptr()); } static classid_t OwnerClassIdOf(CodePtr raw) { - return WeakSerializationReference::UnwrappedClassIdOf( - raw->untag()->owner()); + ObjectPtr owner = WeakSerializationReference::Unwrap(raw->untag()->owner()); + if (!owner->IsHeapObject()) { + return RawSmiValue(static_cast(owner)); + } + return owner->GetClassId(); } static intptr_t owner_offset() { return OFFSET_OF(UntaggedCode, owner_); } diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc index a1425165e2c..6a03bffad00 100644 --- a/runtime/vm/raw_object.cc +++ b/runtime/vm/raw_object.cc @@ -536,6 +536,7 @@ REGULAR_VISITOR(UserTag) REGULAR_VISITOR(SubtypeTestCache) REGULAR_VISITOR(LoadingUnit) REGULAR_VISITOR(KernelProgramInfo) +REGULAR_VISITOR(WeakSerializationReference) VARIABLE_VISITOR(TypeArguments, Smi::Value(raw_obj->untag()->length_)) VARIABLE_VISITOR(LocalVarDescriptors, raw_obj->untag()->num_entries_) VARIABLE_VISITOR(ExceptionHandlers, raw_obj->untag()->num_entries_) @@ -576,11 +577,6 @@ UNREACHABLE_VISITOR(String) UNREACHABLE_VISITOR(FutureOr) // Smi has no heap representation. UNREACHABLE_VISITOR(Smi) -#if defined(DART_PRECOMPILED_RUNTIME) -NULL_VISITOR(WeakSerializationReference) -#else -REGULAR_VISITOR(WeakSerializationReference) -#endif intptr_t UntaggedField::VisitFieldPointers(FieldPtr raw_obj, ObjectPointerVisitor* visitor) { diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 21f3aaa63fa..8c041a280e4 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -1508,14 +1508,10 @@ class UntaggedKernelProgramInfo : public UntaggedObject { class UntaggedWeakSerializationReference : public UntaggedObject { RAW_HEAP_OBJECT_IMPLEMENTATION(WeakSerializationReference); -#if defined(DART_PRECOMPILED_RUNTIME) - VISIT_NOTHING(); - ClassIdTagType cid_; -#else VISIT_FROM(ObjectPtr, target) POINTER_FIELD(ObjectPtr, target) - VISIT_TO(ObjectPtr, target) -#endif + POINTER_FIELD(ObjectPtr, replacement) + VISIT_TO(ObjectPtr, replacement) }; class UntaggedCode : public UntaggedObject { diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc index 16b25bdd4d9..07f24dbf46b 100644 --- a/runtime/vm/raw_object_fields.cc +++ b/runtime/vm/raw_object_fields.cc @@ -84,6 +84,8 @@ namespace dart { F(KernelProgramInfo, libraries_cache_) \ F(KernelProgramInfo, classes_cache_) \ F(KernelProgramInfo, retained_kernel_blob_) \ + F(WeakSerializationReference, target_) \ + F(WeakSerializationReference, replacement_) \ F(Code, object_pool_) \ F(Code, instructions_) \ F(Code, owner_) \ @@ -192,7 +194,7 @@ namespace dart { F(TypedDataView, offset_in_bytes_) \ F(FutureOr, type_arguments_) -#define AOT_CLASSES_AND_FIELDS(F) F(WeakSerializationReference, cid_) +#define AOT_CLASSES_AND_FIELDS(F) #define JIT_CLASSES_AND_FIELDS(F) \ F(Code, active_instructions_) \ @@ -201,7 +203,6 @@ namespace dart { F(ICData, receivers_static_type_) \ F(Function, unoptimized_code_) \ F(Field, type_test_cache_) \ - F(WeakSerializationReference, target_) #define NON_PRODUCT_CLASSES_AND_FIELDS(F) \ F(ReceivePort, debug_name_) \ diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc index 96ad60dee64..51c1722e539 100644 --- a/runtime/vm/stack_frame.cc +++ b/runtime/vm/stack_frame.cc @@ -321,7 +321,10 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { FunctionPtr StackFrame::LookupDartFunction() const { const Code& code = Code::Handle(LookupDartCode()); if (!code.IsNull()) { - return code.function(); + const Object& owner = Object::Handle(code.owner()); + if (owner.IsFunction()) { + return Function::Cast(owner).ptr(); + } } return Function::null(); } diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h index 378436253cb..39dfa25f22a 100644 --- a/runtime/vm/symbols.h +++ b/runtime/vm/symbols.h @@ -293,6 +293,7 @@ class ObjectPointerVisitor; V(UnwindError, "UnwindError") \ V(Value, "value") \ V(Values, "values") \ + V(WeakSerializationReference, "WeakSerializationReference") \ V(YieldKw, "yield") \ V(_AsyncAwaitStart, "start") \ V(_AsyncStarStreamController, "_AsyncStarStreamController") \