| 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);
|
| }
|
|
|