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

Unified Diff: src/heap-snapshot-generator.cc

Issue 213673006: Show references from weak containers as weak in heap snapshots. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Added a test. Created 6 years, 9 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-snapshot-generator.h ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap-snapshot-generator.cc
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 332d0dbf6ff3705318f28a666d7134667e12295c..b23b60f3f537a699735720cfb56b96762b51a58b 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -1101,10 +1101,8 @@ class IndexedReferencesExtractor : public ObjectVisitor {
};
-void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
- HeapEntry* heap_entry = GetEntry(obj);
- if (heap_entry == NULL) return; // No interest in this object.
- int entry = heap_entry->index();
+bool V8HeapExplorer::ExtractReferencesPass1(int entry, HeapObject* obj) {
+ if (obj->IsFixedArray()) return false; // FixedArrays are processed on pass 2
if (obj->IsJSGlobalProxy()) {
ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj));
@@ -1114,8 +1112,6 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
ExtractJSObjectReferences(entry, JSObject::cast(obj));
} else if (obj->IsString()) {
ExtractStringReferences(entry, String::cast(obj));
- } else if (obj->IsContext()) {
- ExtractContextReferences(entry, Context::cast(obj));
} else if (obj->IsMap()) {
ExtractMapReferences(entry, Map::cast(obj));
} else if (obj->IsSharedFunctionInfo()) {
@@ -1137,12 +1133,19 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
} else if (obj->IsAllocationSite()) {
ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj));
}
- SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
+ return true;
+}
+
- // Extract unvisited fields as hidden references and restore tags
- // of visited fields.
- IndexedReferencesExtractor refs_extractor(this, obj, entry);
- obj->Iterate(&refs_extractor);
+bool V8HeapExplorer::ExtractReferencesPass2(int entry, HeapObject* obj) {
+ if (!obj->IsFixedArray()) return false;
+
+ if (obj->IsContext()) {
+ ExtractContextReferences(entry, Context::cast(obj));
+ } else {
+ ExtractFixedArrayReferences(entry, FixedArray::cast(obj));
+ }
+ return true;
}
@@ -1320,6 +1323,7 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
SetInternalReference(transitions, transitions_entry,
"back_pointer", back_pointer);
TagObject(transitions, "(transition array)");
+ MarkAsWeakContainer(transitions);
SetInternalReference(map, entry,
"transitions", transitions,
Map::kTransitionsOrBackPointerOffset);
@@ -1336,6 +1340,7 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
"descriptors", descriptors,
Map::kDescriptorsOffset);
+ MarkAsWeakContainer(map->code_cache());
SetInternalReference(map, entry,
"code_cache", map->code_cache(),
Map::kCodeCacheOffset);
@@ -1345,6 +1350,7 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
"constructor", map->constructor(),
Map::kConstructorOffset);
TagObject(map->dependent_code(), "(dependent code)");
+ MarkAsWeakContainer(map->dependent_code());
SetInternalReference(map, entry,
"dependent_code", map->dependent_code(),
Map::kDependentCodeOffset);
@@ -1506,6 +1512,7 @@ void V8HeapExplorer::ExtractPropertyCellReferences(int entry,
ExtractCellReferences(entry, cell);
SetInternalReference(cell, entry, "type", cell->type(),
PropertyCell::kTypeOffset);
+ MarkAsWeakContainer(cell->dependent_code());
SetInternalReference(cell, entry, "dependent_code", cell->dependent_code(),
PropertyCell::kDependentCodeOffset);
}
@@ -1517,6 +1524,7 @@ void V8HeapExplorer::ExtractAllocationSiteReferences(int entry,
AllocationSite::kTransitionInfoOffset);
SetInternalReference(site, entry, "nested_site", site->nested_site(),
AllocationSite::kNestedSiteOffset);
+ MarkAsWeakContainer(site->dependent_code());
SetInternalReference(site, entry, "dependent_code", site->dependent_code(),
AllocationSite::kDependentCodeOffset);
// Do not visit weak_next as it is not visited by the StaticVisitor,
@@ -1562,6 +1570,20 @@ void V8HeapExplorer::ExtractJSArrayBufferReferences(
}
+void V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) {
+ bool is_weak = weak_containers_.Contains(array);
+ for (int i = 0, l = array->length(); i < l; ++i) {
+ if (is_weak) {
+ SetWeakReference(array, entry,
+ i, array->get(i), array->OffsetOfElementAt(i));
+ } else {
+ SetInternalReference(array, entry,
+ i, array->get(i), array->OffsetOfElementAt(i));
+ }
+ }
+}
+
+
void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) {
if (!js_obj->IsJSFunction()) return;
@@ -1833,6 +1855,25 @@ bool V8HeapExplorer::IterateAndExtractReferences(
heap_->IterateRoots(&extractor, VISIT_ALL);
extractor.FillReferences(this);
+ // We have to do two passes as sometimes FixedArrays are used
+ // to weakly hold their items, and it's impossible to distinguish
+ // between these cases without processing the array owner first.
+ bool interrupted =
+ IterateAndExtractSinglePass<&V8HeapExplorer::ExtractReferencesPass1>() ||
+ IterateAndExtractSinglePass<&V8HeapExplorer::ExtractReferencesPass2>();
+
+ if (interrupted) {
+ filler_ = NULL;
+ return false;
+ }
+
+ filler_ = NULL;
+ return progress_->ProgressReport(true);
+}
+
+
+template<V8HeapExplorer::ExtractReferencesMethod extractor>
+bool V8HeapExplorer::IterateAndExtractSinglePass() {
// Now iterate the whole heap.
bool interrupted = false;
HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable);
@@ -1840,18 +1881,22 @@ bool V8HeapExplorer::IterateAndExtractReferences(
for (HeapObject* obj = iterator.next();
obj != NULL;
obj = iterator.next(), progress_->ProgressStep()) {
- if (!interrupted) {
- ExtractReferences(obj);
- if (!progress_->ProgressReport(false)) interrupted = true;
+ if (interrupted) continue;
+
+ HeapEntry* heap_entry = GetEntry(obj);
+ int entry = heap_entry->index();
+ if ((this->*extractor)(entry, obj)) {
+ SetInternalReference(obj, entry,
+ "map", obj->map(), HeapObject::kMapOffset);
+ // Extract unvisited fields as hidden references and restore tags
+ // of visited fields.
+ IndexedReferencesExtractor refs_extractor(this, obj, entry);
+ obj->Iterate(&refs_extractor);
}
- }
- if (interrupted) {
- filler_ = NULL;
- return false;
- }
- filler_ = NULL;
- return progress_->ProgressReport(true);
+ if (!progress_->ProgressReport(false)) interrupted = true;
+ }
+ return interrupted;
}
@@ -1987,6 +2032,24 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
}
+void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
+ int parent_entry,
+ int index,
+ Object* child_obj,
+ int field_offset) {
+ ASSERT(parent_entry == GetEntry(parent_obj)->index());
+ HeapEntry* child_entry = GetEntry(child_obj);
+ if (child_entry == NULL) return;
+ if (IsEssentialObject(child_obj)) {
+ filler_->SetNamedReference(HeapGraphEdge::kWeak,
+ parent_entry,
+ names_->GetFormatted("%d", index),
+ child_entry);
+ }
+ IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
+}
+
+
void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
int parent_entry,
Name* reference_name,
@@ -2114,6 +2177,13 @@ void V8HeapExplorer::TagObject(Object* obj, const char* tag) {
}
+void V8HeapExplorer::MarkAsWeakContainer(Object* object) {
+ if (IsEssentialObject(object) && object->IsFixedArray()) {
+ weak_containers_.Insert(object);
+ }
+}
+
+
class GlobalObjectsEnumerator : public ObjectVisitor {
public:
virtual void VisitPointers(Object** start, Object** end) {
@@ -2504,7 +2574,7 @@ bool HeapSnapshotGenerator::GenerateSnapshot() {
debug_heap->Verify();
#endif
- SetProgressTotal(1); // 1 pass.
+ SetProgressTotal(2); // 2 passes.
#ifdef VERIFY_HEAP
debug_heap->Verify();
« no previous file with comments | « src/heap-snapshot-generator.h ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698