[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 <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Ryan Macnak
2021-02-10 01:21:07 +00:00
committed by commit-bot@chromium.org
parent c290fc0eaf
commit 25fd0200ef
13 changed files with 180 additions and 316 deletions
+2 -2
View File
@@ -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) \
+62 -168
View File
@@ -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<WeakSerializationReferencePtr> objects_;
GrowableArray<WeakSerializationReferencePtr> canonical_wsrs_;
IntMap<intptr_t> 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<WeakSerializationReferencePtr>(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<CanonicalStringSet>(4)));
saved_canonical_types_ = object_store->canonical_types();
object_store->set_canonical_types(
Array::Handle(HashTables::New<CanonicalTypeSet>(4)));
saved_canonical_function_types_ = object_store->canonical_function_types();
object_store->set_canonical_function_types(
Array::Handle(HashTables::New<CanonicalFunctionTypeSet>(4)));
saved_canonical_type_parameters_ =
object_store->canonical_type_parameters();
object_store->set_canonical_type_parameters(
Array::Handle(HashTables::New<CanonicalTypeParameterSet>(4)));
saved_canonical_type_arguments_ = object_store->canonical_type_arguments();
object_store->set_canonical_type_arguments(
Array::Handle(HashTables::New<CanonicalTypeArgumentsSet>(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<Object*>* 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<CodePtr>(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<FunctionPtr>(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<Object*>* 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<WeakSerializationReferenceSerializationCluster*>(
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<Object*>* Serializer::Serialize(SerializationRoots* roots) {
ASSERT(objects_->length() == num_objects);
#if defined(DART_PRECOMPILER)
if (auto cluster =
reinterpret_cast<WeakSerializationReferenceSerializationCluster*>(
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<int32_t>();
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());
+7 -12
View File
@@ -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());
+10 -1
View File
@@ -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;
+22 -22
View File
@@ -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)
+29 -6
View File
@@ -152,7 +152,9 @@ class HashTable : public ValueObject {
template <typename Key>
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 <typename BaseIterTable>
@@ -724,7 +747,7 @@ class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > {
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
+15 -18
View File
@@ -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.
+22 -73
View File
@@ -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<WeakSerializationReferencePtr>(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<WeakSerializationReferencePtr>(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<SmiPtr>(owner));
}
return owner->GetClassId();
}
static intptr_t owner_offset() { return OFFSET_OF(UntaggedCode, owner_); }
+1 -5
View File
@@ -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) {
+2 -6
View File
@@ -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 {
+3 -2
View File
@@ -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_) \
+4 -1
View File
@@ -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();
}
+1
View File
@@ -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") \