Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(318)

Unified Diff: runtime/vm/object_graph.cc

Issue 2502283003: Add a version of heap snapshots that use only fields and stack frames as roots and only include ins… (Closed)
Patch Set: . Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object_graph.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object_graph.cc
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index c80c80c4f3e33e9b9c2c02b8b078a0718e42c728..2352bd8890964f3b687cbf8ffd50e8eec8ce826b 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -8,6 +8,7 @@
#include "vm/growable_array.h"
#include "vm/isolate.h"
#include "vm/object.h"
+#include "vm/object_store.h"
#include "vm/raw_object.h"
#include "vm/reusable_handles.h"
#include "vm/visitor.h"
@@ -487,8 +488,13 @@ static void WritePtr(RawObject* raw, WriteStream* stream) {
class WritePointerVisitor : public ObjectPointerVisitor {
public:
- WritePointerVisitor(Isolate* isolate, WriteStream* stream)
- : ObjectPointerVisitor(isolate), stream_(stream), count_(0) {}
+ WritePointerVisitor(Isolate* isolate,
+ WriteStream* stream,
+ bool only_instances)
+ : ObjectPointerVisitor(isolate),
+ stream_(stream),
+ only_instances_(only_instances),
+ count_(0) {}
virtual void VisitPointers(RawObject** first, RawObject** last) {
for (RawObject** current = first; current <= last; ++current) {
RawObject* object = *current;
@@ -498,6 +504,9 @@ class WritePointerVisitor : public ObjectPointerVisitor {
// we'll need to encode which fields were omitted here.
continue;
}
+ if (only_instances_ && (object->GetClassId() < kInstanceCid)) {
+ continue;
+ }
WritePtr(object, stream_);
++count_;
}
@@ -507,6 +516,7 @@ class WritePointerVisitor : public ObjectPointerVisitor {
private:
WriteStream* stream_;
+ bool only_instances_;
intptr_t count_;
};
@@ -524,8 +534,13 @@ static void WriteHeader(RawObject* raw,
class WriteGraphVisitor : public ObjectGraph::Visitor {
public:
- WriteGraphVisitor(Isolate* isolate, WriteStream* stream)
- : stream_(stream), ptr_writer_(isolate, stream), count_(0) {}
+ WriteGraphVisitor(Isolate* isolate,
+ WriteStream* stream,
+ ObjectGraph::SnapshotRoots roots)
+ : stream_(stream),
+ ptr_writer_(isolate, stream, roots == ObjectGraph::kUser),
+ roots_(roots),
+ count_(0) {}
virtual Direction VisitObject(ObjectGraph::StackIterator* it) {
RawObject* raw_obj = it->Get();
@@ -533,11 +548,13 @@ class WriteGraphVisitor : public ObjectGraph::Visitor {
REUSABLE_OBJECT_HANDLESCOPE(thread);
Object& obj = thread->ObjectHandle();
obj = raw_obj;
- // Each object is a header + a zero-terminated list of its neighbors.
- WriteHeader(raw_obj, raw_obj->Size(), obj.GetClassId(), stream_);
- raw_obj->VisitPointers(&ptr_writer_);
- stream_->WriteUnsigned(0);
- ++count_;
+ if ((roots_ == ObjectGraph::kVM) || obj.IsField() || obj.IsInstance()) {
+ // Each object is a header + a zero-terminated list of its neighbors.
+ WriteHeader(raw_obj, raw_obj->Size(), obj.GetClassId(), stream_);
+ raw_obj->VisitPointers(&ptr_writer_);
+ stream_->WriteUnsigned(0);
+ ++count_;
+ }
return kProceed;
}
@@ -546,29 +563,98 @@ class WriteGraphVisitor : public ObjectGraph::Visitor {
private:
WriteStream* stream_;
WritePointerVisitor ptr_writer_;
+ ObjectGraph::SnapshotRoots roots_;
intptr_t count_;
};
-intptr_t ObjectGraph::Serialize(WriteStream* stream, bool collect_garbage) {
+static void IterateUserFields(ObjectPointerVisitor* visitor) {
+ Thread* thread = Thread::Current();
+ // Scope to prevent handles create here from appearing as stack references.
+ HANDLESCOPE(thread);
+ Zone* zone = thread->zone();
+ const GrowableObjectArray& libraries = GrowableObjectArray::Handle(
+ zone, thread->isolate()->object_store()->libraries());
+ Library& library = Library::Handle(zone);
+ Object& entry = Object::Handle(zone);
+ Class& cls = Class::Handle(zone);
+ Array& fields = Array::Handle(zone);
+ Field& field = Field::Handle(zone);
+ for (intptr_t i = 0; i < libraries.Length(); i++) {
+ library ^= libraries.At(i);
+ DictionaryIterator entries(library);
+ while (entries.HasNext()) {
+ entry = entries.GetNext();
+ if (entry.IsClass()) {
+ cls ^= entry.raw();
+ fields = cls.fields();
+ for (intptr_t j = 0; j < fields.Length(); j++) {
+ field ^= fields.At(j);
+ RawObject* ptr = field.raw();
+ visitor->VisitPointer(&ptr);
+ }
+ } else if (entry.IsField()) {
+ field ^= entry.raw();
+ RawObject* ptr = field.raw();
+ visitor->VisitPointer(&ptr);
+ }
+ }
+ }
+}
+
+
+intptr_t ObjectGraph::Serialize(WriteStream* stream,
+ SnapshotRoots roots,
+ bool collect_garbage) {
if (collect_garbage) {
isolate()->heap()->CollectAllGarbage();
}
// Current encoding assumes objects do not move, so promote everything to old.
isolate()->heap()->new_space()->Evacuate();
- WriteGraphVisitor visitor(isolate(), stream);
+ RawObject* kRootAddress = reinterpret_cast<RawObject*>(kHeapObjectTag);
+ const intptr_t kRootCid = kIllegalCid;
+ RawObject* kStackAddress =
+ reinterpret_cast<RawObject*>(kObjectAlignment + kHeapObjectTag);
+
stream->WriteUnsigned(kObjectAlignment);
- stream->WriteUnsigned(0);
- stream->WriteUnsigned(0);
- stream->WriteUnsigned(0);
- {
- WritePointerVisitor ptr_writer(isolate(), stream);
+ stream->WriteUnsigned(kStackCid);
+
+ if (roots == kVM) {
+ // Write root "object".
+ WriteHeader(kRootAddress, 0, kRootCid, stream);
+ WritePointerVisitor ptr_writer(isolate(), stream, false);
isolate()->IterateObjectPointers(&ptr_writer, false);
+ stream->WriteUnsigned(0);
+ } else {
+ {
+ // Write root "object".
+ WriteHeader(kRootAddress, 0, kRootCid, stream);
+ WritePointerVisitor ptr_writer(isolate(), stream, false);
+ IterateUserFields(&ptr_writer);
+ WritePtr(kStackAddress, stream);
+ stream->WriteUnsigned(0);
+ }
+
+ {
+ // Write stack "object".
+ WriteHeader(kStackAddress, 0, kStackCid, stream);
+ WritePointerVisitor ptr_writer(isolate(), stream, true);
+ isolate()->IterateStackPointers(&ptr_writer, false);
+ stream->WriteUnsigned(0);
+ }
}
- stream->WriteUnsigned(0);
+
+ WriteGraphVisitor visitor(isolate(), stream, roots);
IterateObjects(&visitor);
- return visitor.count() + 1; // + root
+
+ intptr_t object_count = visitor.count();
+ if (roots == kVM) {
+ object_count += 1; // root
+ } else {
+ object_count += 2; // root and stack
+ }
+ return object_count;
}
} // namespace dart
« no previous file with comments | « runtime/vm/object_graph.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698