mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm, service] Create edges from the root to objects on read-only pages in heap snapshots.
This prevents objects, such as InstructionSection, that have no ordinary references from being labeled as "Uncollected Garbage". TEST=examine heap snapshot in an AOT build with bare-instructions enabled Bug: b/200288075 Change-Id: If576d7f9eabb80afaca1b600507c3a9629beeafd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215006 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
parent
bafa71a8ae
commit
1e4a611ca4
|
@ -90,7 +90,9 @@ var tests = <IsolateTest>[
|
|||
int internalSum = 0;
|
||||
int externalSum = 0;
|
||||
for (SnapshotObject instance in klass.instances) {
|
||||
if (instance == graph.root || instance.klass.name.contains("Isolate")) {
|
||||
if (instance == graph.root ||
|
||||
instance.klass.name.contains("Isolate") ||
|
||||
instance.klass.name.contains("Read-Only Pages")) {
|
||||
// The root and fake root subdivisions have 0 self size.
|
||||
expect(instance.internalSize, greaterThanOrEqualTo(0));
|
||||
expect(instance.externalSize, greaterThanOrEqualTo(0));
|
||||
|
@ -122,7 +124,9 @@ var tests = <IsolateTest>[
|
|||
int internalSum = 0;
|
||||
int externalSum = 0;
|
||||
for (SnapshotObject instance in graph.objects) {
|
||||
if (instance == graph.root || instance.klass.name.contains("Isolate")) {
|
||||
if (instance == graph.root ||
|
||||
instance.klass.name.contains("Isolate") ||
|
||||
instance.klass.name.contains("Read-Only Pages")) {
|
||||
// The root and fake root subdivisions have 0 self size.
|
||||
expect(instance.internalSize, greaterThanOrEqualTo(0));
|
||||
expect(instance.externalSize, greaterThanOrEqualTo(0));
|
||||
|
|
|
@ -90,7 +90,9 @@ var tests = <IsolateTest>[
|
|||
int internalSum = 0;
|
||||
int externalSum = 0;
|
||||
for (SnapshotObject instance in klass.instances) {
|
||||
if (instance == graph.root || instance.klass.name.contains("Isolate")) {
|
||||
if (instance == graph.root ||
|
||||
instance.klass.name.contains("Isolate") ||
|
||||
instance.klass.name.contains("Read-Only Pages")) {
|
||||
// The root and fake root subdivisions have 0 self size.
|
||||
expect(instance.internalSize, greaterThanOrEqualTo(0));
|
||||
expect(instance.externalSize, greaterThanOrEqualTo(0));
|
||||
|
@ -122,7 +124,9 @@ var tests = <IsolateTest>[
|
|||
int internalSum = 0;
|
||||
int externalSum = 0;
|
||||
for (SnapshotObject instance in graph.objects) {
|
||||
if (instance == graph.root || instance.klass.name.contains("Isolate")) {
|
||||
if (instance == graph.root ||
|
||||
instance.klass.name.contains("Isolate") ||
|
||||
instance.klass.name.contains("Read-Only Pages")) {
|
||||
// The root and fake root subdivisions have 0 self size.
|
||||
expect(instance.internalSize, greaterThanOrEqualTo(0));
|
||||
expect(instance.externalSize, greaterThanOrEqualTo(0));
|
||||
|
|
|
@ -849,6 +849,47 @@ class Pass1Visitor : public ObjectVisitor,
|
|||
DISALLOW_COPY_AND_ASSIGN(Pass1Visitor);
|
||||
};
|
||||
|
||||
class CountImagePageRefs : public ObjectVisitor {
|
||||
public:
|
||||
CountImagePageRefs() : ObjectVisitor() {}
|
||||
|
||||
void VisitObject(ObjectPtr obj) {
|
||||
if (obj->IsPseudoObject()) return;
|
||||
count_++;
|
||||
}
|
||||
intptr_t count() const { return count_; }
|
||||
|
||||
private:
|
||||
intptr_t count_ = 0;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CountImagePageRefs);
|
||||
};
|
||||
|
||||
class WriteImagePageRefs : public ObjectVisitor {
|
||||
public:
|
||||
explicit WriteImagePageRefs(HeapSnapshotWriter* writer)
|
||||
: ObjectVisitor(), writer_(writer) {}
|
||||
|
||||
void VisitObject(ObjectPtr obj) {
|
||||
if (obj->IsPseudoObject()) return;
|
||||
#if defined(DEBUG)
|
||||
count_++;
|
||||
#endif
|
||||
writer_->WriteUnsigned(writer_->GetObjectId(obj));
|
||||
}
|
||||
#if defined(DEBUG)
|
||||
intptr_t count() const { return count_; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
HeapSnapshotWriter* const writer_;
|
||||
#if defined(DEBUG)
|
||||
intptr_t count_ = 0;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WriteImagePageRefs);
|
||||
};
|
||||
|
||||
enum NonReferenceDataTags {
|
||||
kNoData = 0,
|
||||
kNullData,
|
||||
|
@ -865,9 +906,10 @@ static const intptr_t kMaxStringElements = 128;
|
|||
|
||||
enum ExtraCids {
|
||||
kRootExtraCid = 1, // 1-origin
|
||||
kIsolateExtraCid = 2,
|
||||
kImagePageExtraCid = 2,
|
||||
kIsolateExtraCid = 3,
|
||||
|
||||
kNumExtraCids = 2,
|
||||
kNumExtraCids = 3,
|
||||
};
|
||||
|
||||
class Pass2Visitor : public ObjectVisitor,
|
||||
|
@ -1209,7 +1251,16 @@ void HeapSnapshotWriter::Write() {
|
|||
WriteUnsigned(0); // Field count
|
||||
}
|
||||
{
|
||||
ASSERT(kIsolateExtraCid == 2);
|
||||
ASSERT(kImagePageExtraCid == 2);
|
||||
WriteUnsigned(0); // Flags
|
||||
WriteUtf8("Read-Only Pages"); // Name
|
||||
WriteUtf8(""); // Library name
|
||||
WriteUtf8(""); // Library uri
|
||||
WriteUtf8(""); // Reserved
|
||||
WriteUnsigned(0); // Field count
|
||||
}
|
||||
{
|
||||
ASSERT(kIsolateExtraCid == 3);
|
||||
WriteUnsigned(0); // Flags
|
||||
WriteUtf8("Isolate"); // Name
|
||||
WriteUtf8(""); // Library name
|
||||
|
@ -1226,7 +1277,7 @@ void HeapSnapshotWriter::Write() {
|
|||
WriteUtf8(""); // Reserved
|
||||
}
|
||||
}
|
||||
ASSERT(kNumExtraCids == 2);
|
||||
ASSERT(kNumExtraCids == 3);
|
||||
for (intptr_t cid = 1; cid <= class_count_; cid++) {
|
||||
if (!class_table->HasValidClassAt(cid)) {
|
||||
WriteUnsigned(0); // Flags
|
||||
|
@ -1320,21 +1371,34 @@ void HeapSnapshotWriter::Write() {
|
|||
SetupCountingPages();
|
||||
|
||||
intptr_t num_isolates = 0;
|
||||
intptr_t num_image_objects = 0;
|
||||
{
|
||||
Pass1Visitor visitor(this);
|
||||
|
||||
// Root "objects".
|
||||
++object_count_;
|
||||
isolate_group()->VisitSharedPointers(&visitor);
|
||||
isolate_group()->ForEachIsolate(
|
||||
[&](Isolate* isolate) {
|
||||
++object_count_;
|
||||
isolate->VisitObjectPointers(&visitor,
|
||||
ValidationPolicy::kDontValidateFrames);
|
||||
++num_isolates;
|
||||
},
|
||||
/*at_safepoint=*/true);
|
||||
CountReferences(num_isolates);
|
||||
{
|
||||
++object_count_;
|
||||
isolate_group()->VisitSharedPointers(&visitor);
|
||||
}
|
||||
{
|
||||
++object_count_;
|
||||
CountImagePageRefs visitor;
|
||||
H->old_space()->VisitObjectsImagePages(&visitor);
|
||||
num_image_objects = visitor.count();
|
||||
CountReferences(num_image_objects);
|
||||
}
|
||||
{
|
||||
isolate_group()->ForEachIsolate(
|
||||
[&](Isolate* isolate) {
|
||||
++object_count_;
|
||||
isolate->VisitObjectPointers(&visitor,
|
||||
ValidationPolicy::kDontValidateFrames);
|
||||
++num_isolates;
|
||||
},
|
||||
/*at_safepoint=*/true);
|
||||
}
|
||||
CountReferences(1); // Root -> Image Pages
|
||||
CountReferences(num_isolates); // Root -> Isolate
|
||||
|
||||
// Heap objects.
|
||||
iteration.IterateVMIsolateObjects(&visitor);
|
||||
|
@ -1357,13 +1421,24 @@ void HeapSnapshotWriter::Write() {
|
|||
WriteUnsigned(kNoData);
|
||||
visitor.DoCount();
|
||||
isolate_group()->VisitSharedPointers(&visitor);
|
||||
visitor.CountExtraRefs(num_isolates);
|
||||
visitor.CountExtraRefs(num_isolates + 1);
|
||||
visitor.DoWrite();
|
||||
isolate_group()->VisitSharedPointers(&visitor);
|
||||
visitor.WriteExtraRef(2); // Root -> Image Pages
|
||||
for (intptr_t i = 0; i < num_isolates; i++) {
|
||||
visitor.WriteExtraRef(i + 2); // 0 = sentinel, 1 = root, 2+ = isolates
|
||||
// 0 = sentinel, 1 = root, 2 = image pages, 2+ = isolates
|
||||
visitor.WriteExtraRef(i + 3);
|
||||
}
|
||||
}
|
||||
{
|
||||
WriteUnsigned(kImagePageExtraCid);
|
||||
WriteUnsigned(0); // shallowSize
|
||||
WriteUnsigned(kNoData);
|
||||
WriteUnsigned(num_image_objects);
|
||||
WriteImagePageRefs visitor(this);
|
||||
H->old_space()->VisitObjectsImagePages(&visitor);
|
||||
DEBUG_ASSERT(visitor.count() == num_image_objects);
|
||||
}
|
||||
isolate_group()->ForEachIsolate(
|
||||
[&](Isolate* isolate) {
|
||||
WriteUnsigned(kIsolateExtraCid);
|
||||
|
@ -1395,10 +1470,13 @@ void HeapSnapshotWriter::Write() {
|
|||
// Identity hash codes
|
||||
Pass3Visitor visitor(this);
|
||||
|
||||
// Handle root object.
|
||||
WriteUnsigned(0);
|
||||
isolate_group()->ForEachIsolate([&](Isolate* isolate) { WriteUnsigned(0); },
|
||||
/*at_safepoint=*/true);
|
||||
WriteUnsigned(0); // Root fake object.
|
||||
WriteUnsigned(0); // Image pages fake object.
|
||||
isolate_group()->ForEachIsolate(
|
||||
[&](Isolate* isolate) {
|
||||
WriteUnsigned(0); // Isolate fake object.
|
||||
},
|
||||
/*at_safepoint=*/true);
|
||||
|
||||
// Handle visit rest of the objects.
|
||||
iteration.IterateVMIsolateObjects(&visitor);
|
||||
|
|
Loading…
Reference in a new issue