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

Unified Diff: src/heap/heap.cc

Issue 890663005: Introduce a flag for tracing retaining path in GC. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months 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 | « src/heap/heap.h ('k') | src/heap/mark-compact.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap/heap.cc
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 0742aafc83913c1c3e4a46792ca6da2e415c2ebe..02cde2d7c7fca6a1b5d9a94e343a2d7da9a61c15 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -166,6 +166,10 @@ Heap::Heap()
RememberUnmappedPage(NULL, false);
ClearObjectStats(true);
+
+#ifdef TRACE_RETAINING_PATH
+ ClearRetainingInfo();
+#endif
}
@@ -614,6 +618,10 @@ void Heap::GarbageCollectionEpilogue() {
}
#endif
+#ifdef TRACE_RETAINING_PATH
+ ClearRetainingInfo();
+#endif
+
AllowHeapAllocation for_the_rest_of_the_epilogue;
#ifdef DEBUG
@@ -5044,41 +5052,62 @@ void Heap::IterateSmiRoots(ObjectVisitor* v) {
}
+#ifdef TRACE_RETAINING_PATH
+#define TRACE_ROOT(root) SetCurrentRootRetainer(std::string(root))
+#else
+#define TRACE_ROOT(root)
+#endif
+
+
void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
+ TRACE_ROOT("[strong root list]");
v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]);
v->Synchronize(VisitorSynchronization::kStrongRootList);
+ TRACE_ROOT("[internalized string]");
v->VisitPointer(bit_cast<Object**>(&hidden_string_));
v->Synchronize(VisitorSynchronization::kInternalizedString);
+ TRACE_ROOT("[bootstrapper]");
isolate_->bootstrapper()->Iterate(v);
v->Synchronize(VisitorSynchronization::kBootstrapper);
+
+ TRACE_ROOT("[isolate threads]");
isolate_->Iterate(v);
v->Synchronize(VisitorSynchronization::kTop);
+
+ TRACE_ROOT("[isolate relocatable]");
Relocatable::Iterate(isolate_, v);
v->Synchronize(VisitorSynchronization::kRelocatable);
+ TRACE_ROOT("[deoptimizer data]");
if (isolate_->deoptimizer_data() != NULL) {
isolate_->deoptimizer_data()->Iterate(v);
}
v->Synchronize(VisitorSynchronization::kDebug);
+
+ TRACE_ROOT("[compilation cache]");
isolate_->compilation_cache()->Iterate(v);
v->Synchronize(VisitorSynchronization::kCompilationCache);
// Iterate over local handles in handle scopes.
+ TRACE_ROOT("[internal handles]");
isolate_->handle_scope_implementer()->Iterate(v);
+ TRACE_ROOT("[internal deferred handles]");
isolate_->IterateDeferredHandles(v);
v->Synchronize(VisitorSynchronization::kHandleScope);
// Iterate over the builtin code objects and code stubs in the
// heap. Note that it is not necessary to iterate over code objects
// on scavenge collections.
+ TRACE_ROOT("[builtins]");
if (mode != VISIT_ALL_IN_SCAVENGE) {
isolate_->builtins()->IterateBuiltins(v);
}
v->Synchronize(VisitorSynchronization::kBuiltins);
// Iterate over global handles.
+ TRACE_ROOT("[global handles]");
switch (mode) {
case VISIT_ONLY_STRONG:
isolate_->global_handles()->IterateStrongRoots(v);
@@ -5094,6 +5123,7 @@ void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
v->Synchronize(VisitorSynchronization::kGlobalHandles);
// Iterate over eternal handles.
+ TRACE_ROOT("[eternal handles]");
if (mode == VISIT_ALL_IN_SCAVENGE) {
isolate_->eternal_handles()->IterateNewSpaceRoots(v);
} else {
@@ -5101,6 +5131,7 @@ void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
}
v->Synchronize(VisitorSynchronization::kEternalHandles);
+ TRACE_ROOT("[isolate inactive threads]");
// Iterate over pointers being held by inactive threads.
isolate_->thread_manager()->Iterate(v);
v->Synchronize(VisitorSynchronization::kThreadManager);
@@ -5113,11 +5144,13 @@ void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
// serialization this does nothing, since the partial snapshot cache is
// empty. However the next thing we do is create the partial snapshot,
// filling up the partial snapshot cache with objects it needs as we go.
+ TRACE_ROOT("[serializer/deserializer]");
SerializerDeserializer::Iterate(isolate_, v);
// We don't do a v->Synchronize call here, because in debug mode that will
// output a flag to the snapshot. However at this point the serializer and
// deserializer are deliberately a little unsynchronized (see above) so the
// checking of the sync flag in the snapshot would fail.
+ TRACE_ROOT("[]");
}
@@ -5524,6 +5557,72 @@ void Heap::SetStackLimits() {
void Heap::NotifyDeserializationComplete() { deserialization_complete_ = true; }
+#ifdef TRACE_RETAINING_PATH
+void Heap::SetCurrentRetainer(HeapObject* obj) { current_retainer_ = obj; }
+
+
+void Heap::SetCurrentRootRetainer(std::string root) {
+ current_root_retainer_ = root;
+}
+
+
+void Heap::PrintRetainingPath(HeapObject* obj, const char* comment) {
+ PrintF("Retaining path for %s [%p]:\n", comment, static_cast<void*>(obj));
+ obj->ShortPrint();
+ PrintF("\n");
+ while (retainer_.count(obj) && retainer_[obj] != NULL) {
+ PrintF("^^^^^^^^\n");
+ obj = retainer_[obj];
+#ifdef OBJECT_PRINT
+ obj->Print();
+#else
+ obj->ShortPrint();
+#endif
+ PrintF("\n");
+ }
+ if (root_retainer_.count(obj)) {
+ PrintF("^^^^^^^^\n");
+ PrintF("%s\n", root_retainer_[obj].c_str());
+ }
+ PrintF("End of retaining path.\n");
+}
+
+
+void Heap::AddRetainedObject(HeapObject* obj) {
+ if (retainer_.count(obj)) return;
+ retainer_[obj] = current_retainer_;
+ if (current_retainer_ == NULL) {
+ root_retainer_[obj] = current_root_retainer_;
+ }
+ const char* filter = FLAG_trace_retaining_path_for;
+ if (obj->IsJSObject() && *filter != 0) {
+ JSObject* jsobj = JSObject::cast(obj);
+ String* name = jsobj->constructor_name();
+ if (!strcmp(filter, name->ToCString().get())) {
+ PrintRetainingPath(obj, filter);
+ }
+ }
+ if (FLAG_track_detached_contexts && obj->IsNativeContext()) {
+ FixedArray* dc = detached_contexts();
+ int length = dc->length();
+ for (int i = 0; i < length; i += 2) {
+ int mark_sweeps = Smi::cast(dc->get(i))->value();
+ if (mark_sweeps > 5 && WeakCell::cast(dc->get(i + 1))->value() == obj) {
Hannes Payer (out of office) 2015/02/06 13:31:31 make 5 a constant
+ PrintRetainingPath(obj, "detached context");
+ }
+ }
+ }
+}
+
+
+void Heap::ClearRetainingInfo() {
+ retainer_.clear();
+ root_retainer_.clear();
+ current_retainer_ = NULL;
+ current_root_retainer_ = "";
+}
+#endif
+
Hannes Payer (out of office) 2015/02/06 13:31:32 +1 newline
void Heap::TearDown() {
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
« no previous file with comments | « src/heap/heap.h ('k') | src/heap/mark-compact.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698