}
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) {
ExtractCodeCacheReferences(entry, CodeCache::cast(obj));
} else if (obj->IsCode()) {
ExtractCodeReferences(entry, Code::cast(obj));
+ } else if (obj->IsBox()) {
+ ExtractBoxReferences(entry, Box::cast(obj));
} else if (obj->IsCell()) {
ExtractCellReferences(entry, Cell::cast(obj));
} else if (obj->IsPropertyCell()) {
"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(),
TagObject(context->runtime_context(), "(runtime context)");
TagObject(context->embedder_data(), "(context data)");
NATIVE_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD);
- EXTRACT_CONTEXT_FIELD(OPTIMIZED_FUNCTIONS_LIST, , optimized_functions_list);
- EXTRACT_CONTEXT_FIELD(OPTIMIZED_CODE_LIST, , optimized_code_list);
- EXTRACT_CONTEXT_FIELD(DEOPTIMIZED_CODE_LIST, , deoptimized_code_list);
- EXTRACT_CONTEXT_FIELD(NEXT_CONTEXT_LINK, , next_context_link);
+ EXTRACT_CONTEXT_FIELD(OPTIMIZED_FUNCTIONS_LIST, unused,
+ optimized_functions_list);
+ EXTRACT_CONTEXT_FIELD(OPTIMIZED_CODE_LIST, unused, optimized_code_list);
+ EXTRACT_CONTEXT_FIELD(DEOPTIMIZED_CODE_LIST, unused, deoptimized_code_list);
+ EXTRACT_CONTEXT_FIELD(NEXT_CONTEXT_LINK, unused, next_context_link);
#undef EXTRACT_CONTEXT_FIELD
STATIC_CHECK(Context::OPTIMIZED_FUNCTIONS_LIST == Context::FIRST_WEAK_SLOT);
STATIC_CHECK(Context::NEXT_CONTEXT_LINK + 1
}
-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));
}
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);
+ }
+}
+
+
+void V8HeapExplorer::ExtractBoxReferences(int entry, Box* box) {
+ SetInternalReference(box, entry, "value", box->value(), Box::kValueOffset);
}
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);
}
}
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;
}
}
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;
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);
}