Index: src/heap-snapshot-generator.cc |
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc |
index bae1baed29ec072902f7601f289ca8e575b1f3d5..9f4d6da89ffec82258151eda30dd9c62532026b5 100644 |
--- a/src/heap-snapshot-generator.cc |
+++ b/src/heap-snapshot-generator.cc |
@@ -992,8 +992,9 @@ class IndexedReferencesExtractor : public ObjectVisitor { |
} |
void VisitPointers(Object** start, Object** end) { |
for (Object** p = start; p < end; p++) { |
+ ++next_index_; |
if (CheckVisitedAndUnmark(p)) continue; |
- generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
+ generator_->SetHiddenReference(parent_obj_, parent_, next_index_, *p); |
} |
} |
static void MarkVisitedField(HeapObject* obj, int offset) { |
@@ -1131,8 +1132,13 @@ void V8HeapExplorer::ExtractJSObjectReferences( |
"native_context", global_obj->native_context(), |
GlobalObject::kNativeContextOffset); |
SetInternalReference(global_obj, entry, |
+ "global_context", global_obj->global_context(), |
+ GlobalObject::kGlobalContextOffset); |
+ SetInternalReference(global_obj, entry, |
"global_receiver", global_obj->global_receiver(), |
GlobalObject::kGlobalReceiverOffset); |
+ STATIC_CHECK(GlobalObject::kHeaderSize - JSObject::kHeaderSize == |
+ 4 * kPointerSize); |
} else if (obj->IsJSArrayBufferView()) { |
JSArrayBufferView* view = JSArrayBufferView::cast(obj); |
SetInternalReference(view, entry, "buffer", view->buffer(), |
@@ -1365,8 +1371,8 @@ void V8HeapExplorer::ExtractCodeCacheReferences( |
} |
-void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { |
- TagObject(code, names_->GetFormatted("(%s code)", external_name)); |
+void V8HeapExplorer::TagBuiltinCodeObject(Code* code, const char* name) { |
+ TagObject(code, names_->GetFormatted("(%s builtin)", name)); |
} |
@@ -1403,6 +1409,11 @@ void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { |
SetInternalReference(code, entry, |
"constant_pool", code->constant_pool(), |
Code::kConstantPoolOffset); |
+ if (code->kind() == Code::OPTIMIZED_FUNCTION) { |
+ SetWeakReference(code, entry, |
+ "next_code_link", code->next_code_link(), |
+ Code::kNextCodeLinkOffset); |
+ } |
} |
@@ -1427,14 +1438,12 @@ void V8HeapExplorer::ExtractAllocationSiteReferences(int entry, |
AllocationSite::kTransitionInfoOffset); |
SetInternalReference(site, entry, "nested_site", site->nested_site(), |
AllocationSite::kNestedSiteOffset); |
- SetInternalReference(site, entry, "pretenure_data", |
- site->pretenure_data(), |
- AllocationSite::kPretenureDataOffset); |
- SetInternalReference(site, entry, "pretenure_create_count", |
- site->pretenure_create_count(), |
- AllocationSite::kPretenureCreateCountOffset); |
SetInternalReference(site, entry, "dependent_code", site->dependent_code(), |
AllocationSite::kDependentCodeOffset); |
+ // Do not visit weak_next as it is not visited by the StaticVisitor, |
+ // and we're not very interested in weak_next field here. |
+ STATIC_CHECK(AllocationSite::kWeakNextOffset >= |
+ AllocationSite::BodyDescriptor::kEndOffset); |
} |
@@ -1659,24 +1668,20 @@ class RootsReferencesExtractor : public ObjectVisitor { |
} |
int strong_index = 0, all_index = 0, tags_index = 0, builtin_index = 0; |
while (all_index < all_references_.length()) { |
- if (strong_index < strong_references_.length() && |
- strong_references_[strong_index] == all_references_[all_index]) { |
- explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
- false, |
- all_references_[all_index]); |
- ++strong_index; |
- } else { |
- explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
- true, |
- all_references_[all_index]); |
- } |
+ bool is_strong = strong_index < strong_references_.length() |
+ && strong_references_[strong_index] == all_references_[all_index]; |
+ explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
+ !is_strong, |
+ all_references_[all_index]); |
if (reference_tags_[tags_index].tag == |
VisitorSynchronization::kBuiltins) { |
ASSERT(all_references_[all_index]->IsCode()); |
- explorer->TagCodeObject(Code::cast(all_references_[all_index]), |
+ explorer->TagBuiltinCodeObject( |
+ Code::cast(all_references_[all_index]), |
builtins->name(builtin_index++)); |
} |
++all_index; |
+ if (is_strong) ++strong_index; |
if (reference_tags_[tags_index].index == all_index) ++tags_index; |
} |
} |
@@ -1701,11 +1706,21 @@ class RootsReferencesExtractor : public ObjectVisitor { |
bool V8HeapExplorer::IterateAndExtractReferences( |
SnapshotFillerInterface* filler) { |
- HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); |
- |
filler_ = filler; |
- bool interrupted = false; |
+ // Make sure builtin code objects get their builtin tags |
+ // first. Otherwise a particular JSFunction object could set |
+ // its custom name to a generic builtin. |
+ SetRootGcRootsReference(); |
+ RootsReferencesExtractor extractor(heap_); |
+ heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); |
+ extractor.SetCollectingAllReferences(); |
+ heap_->IterateRoots(&extractor, VISIT_ALL); |
+ extractor.FillReferences(this); |
+ |
+ // Now iterate the whole heap. |
+ bool interrupted = false; |
+ HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); |
// Heap iteration with filtering must be finished in any case. |
for (HeapObject* obj = iterator.next(); |
obj != NULL; |
@@ -1720,12 +1735,6 @@ bool V8HeapExplorer::IterateAndExtractReferences( |
return false; |
} |
- SetRootGcRootsReference(); |
- RootsReferencesExtractor extractor(heap_); |
- heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); |
- extractor.SetCollectingAllReferences(); |
- heap_->IterateRoots(&extractor, VISIT_ALL); |
- extractor.FillReferences(this); |
filler_ = NULL; |
return progress_->ProgressReport(true); |
} |