Heap profiler: annotate fixed arrays by their purpose.
This helps understanding what is a particular array for by just looking at its name. R=vitalyr@chromium.org Review URL: http://codereview.chromium.org/7248058 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8494 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
a482bd7ee3
commit
d0559ee206
@ -1635,7 +1635,8 @@ HeapObject *const V8HeapExplorer::kGcRootsObject =
|
||||
V8HeapExplorer::V8HeapExplorer(
|
||||
HeapSnapshot* snapshot,
|
||||
SnapshottingProgressReportingInterface* progress)
|
||||
: snapshot_(snapshot),
|
||||
: heap_(Isolate::Current()->heap()),
|
||||
snapshot_(snapshot),
|
||||
collection_(snapshot_->collection()),
|
||||
progress_(progress),
|
||||
filler_(NULL) {
|
||||
@ -1725,10 +1726,14 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
|
||||
: "",
|
||||
children_count,
|
||||
retainers_count);
|
||||
} else if (object->IsFixedArray() || object->IsByteArray()) {
|
||||
} else if (object->IsFixedArray() ||
|
||||
object->IsFixedDoubleArray() ||
|
||||
object->IsByteArray() ||
|
||||
object->IsExternalArray()) {
|
||||
const char* tag = objects_tags_.GetTag(object);
|
||||
return AddEntry(object,
|
||||
HeapEntry::kArray,
|
||||
"",
|
||||
tag != NULL ? tag : "",
|
||||
children_count,
|
||||
retainers_count);
|
||||
} else if (object->IsHeapNumber()) {
|
||||
@ -1836,15 +1841,13 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
|
||||
HeapEntry* entry = GetEntry(obj);
|
||||
if (entry == NULL) return; // No interest in this object.
|
||||
|
||||
bool extract_indexed_refs = true;
|
||||
if (obj->IsJSGlobalProxy()) {
|
||||
// We need to reference JS global objects from snapshot's root.
|
||||
// We use JSGlobalProxy because this is what embedder (e.g. browser)
|
||||
// uses for the global object.
|
||||
JSGlobalProxy* proxy = JSGlobalProxy::cast(obj);
|
||||
SetRootShortcutReference(proxy->map()->prototype());
|
||||
SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
|
||||
IndexedReferencesExtractor refs_extractor(this, obj, entry);
|
||||
obj->Iterate(&refs_extractor);
|
||||
} else if (obj->IsJSObject()) {
|
||||
JSObject* js_obj = JSObject::cast(obj);
|
||||
ExtractClosureReferences(js_obj, entry);
|
||||
@ -1852,7 +1855,7 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
|
||||
ExtractElementReferences(js_obj, entry);
|
||||
ExtractInternalReferences(js_obj, entry);
|
||||
SetPropertyReference(
|
||||
obj, entry, HEAP->Proto_symbol(), js_obj->GetPrototype());
|
||||
obj, entry, heap_->Proto_symbol(), js_obj->GetPrototype());
|
||||
if (obj->IsJSFunction()) {
|
||||
JSFunction* js_fun = JSFunction::cast(js_obj);
|
||||
Object* proto_or_map = js_fun->prototype_or_initial_map();
|
||||
@ -1860,39 +1863,49 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
|
||||
if (!proto_or_map->IsMap()) {
|
||||
SetPropertyReference(
|
||||
obj, entry,
|
||||
HEAP->prototype_symbol(), proto_or_map,
|
||||
heap_->prototype_symbol(), proto_or_map,
|
||||
JSFunction::kPrototypeOrInitialMapOffset);
|
||||
} else {
|
||||
SetPropertyReference(
|
||||
obj, entry,
|
||||
HEAP->prototype_symbol(), js_fun->prototype());
|
||||
heap_->prototype_symbol(), js_fun->prototype());
|
||||
}
|
||||
}
|
||||
SetInternalReference(js_fun, entry,
|
||||
"shared", js_fun->shared(),
|
||||
JSFunction::kSharedFunctionInfoOffset);
|
||||
TagObject(js_fun->unchecked_context(), "(context)");
|
||||
SetInternalReference(js_fun, entry,
|
||||
"context", js_fun->unchecked_context(),
|
||||
JSFunction::kContextOffset);
|
||||
TagObject(js_fun->literals(), "(function literals)");
|
||||
SetInternalReference(js_fun, entry,
|
||||
"literals", js_fun->literals(),
|
||||
JSFunction::kLiteralsOffset);
|
||||
}
|
||||
TagObject(js_obj->properties(), "(object properties)");
|
||||
SetInternalReference(obj, entry,
|
||||
"properties", js_obj->properties(),
|
||||
JSObject::kPropertiesOffset);
|
||||
TagObject(js_obj->elements(), "(object elements)");
|
||||
SetInternalReference(obj, entry,
|
||||
"elements", js_obj->elements(),
|
||||
JSObject::kElementsOffset);
|
||||
SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
|
||||
IndexedReferencesExtractor refs_extractor(this, obj, entry);
|
||||
obj->Iterate(&refs_extractor);
|
||||
} else if (obj->IsString()) {
|
||||
if (obj->IsConsString()) {
|
||||
ConsString* cs = ConsString::cast(obj);
|
||||
SetInternalReference(obj, entry, 1, cs->first());
|
||||
SetInternalReference(obj, entry, 2, cs->second());
|
||||
}
|
||||
extract_indexed_refs = false;
|
||||
} else if (obj->IsGlobalContext()) {
|
||||
Context* context = Context::cast(obj);
|
||||
TagObject(context->jsfunction_result_caches(),
|
||||
"(context func. result caches)");
|
||||
TagObject(context->normalized_map_cache(), "(context norm. map cache)");
|
||||
TagObject(context->runtime_context(), "(runtime context)");
|
||||
TagObject(context->map_cache(), "(context map cache)");
|
||||
TagObject(context->data(), "(context data)");
|
||||
} else if (obj->IsMap()) {
|
||||
Map* map = Map::cast(obj);
|
||||
SetInternalReference(obj, entry,
|
||||
@ -1901,6 +1914,7 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
|
||||
"constructor", map->constructor(),
|
||||
Map::kConstructorOffset);
|
||||
if (!map->instance_descriptors()->IsEmpty()) {
|
||||
TagObject(map->instance_descriptors(), "(map descriptors)");
|
||||
SetInternalReference(obj, entry,
|
||||
"descriptors", map->instance_descriptors(),
|
||||
Map::kInstanceDescriptorsOrBitField3Offset);
|
||||
@ -1908,9 +1922,6 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
|
||||
SetInternalReference(obj, entry,
|
||||
"code_cache", map->code_cache(),
|
||||
Map::kCodeCacheOffset);
|
||||
SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
|
||||
IndexedReferencesExtractor refs_extractor(this, obj, entry);
|
||||
obj->Iterate(&refs_extractor);
|
||||
} else if (obj->IsSharedFunctionInfo()) {
|
||||
SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
|
||||
SetInternalReference(obj, entry,
|
||||
@ -1919,16 +1930,61 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
|
||||
SetInternalReference(obj, entry,
|
||||
"code", shared->unchecked_code(),
|
||||
SharedFunctionInfo::kCodeOffset);
|
||||
TagObject(shared->scope_info(), "(function scope info)");
|
||||
SetInternalReference(obj, entry,
|
||||
"scope_info", shared->scope_info(),
|
||||
SharedFunctionInfo::kScopeInfoOffset);
|
||||
SetInternalReference(obj, entry,
|
||||
"instance_class_name", shared->instance_class_name(),
|
||||
SharedFunctionInfo::kInstanceClassNameOffset);
|
||||
SetInternalReference(obj, entry,
|
||||
"script", shared->script(),
|
||||
SharedFunctionInfo::kScriptOffset);
|
||||
SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
|
||||
IndexedReferencesExtractor refs_extractor(this, obj, entry);
|
||||
obj->Iterate(&refs_extractor);
|
||||
} else {
|
||||
} else if (obj->IsScript()) {
|
||||
Script* script = Script::cast(obj);
|
||||
SetInternalReference(obj, entry,
|
||||
"source", script->source(),
|
||||
Script::kSourceOffset);
|
||||
SetInternalReference(obj, entry,
|
||||
"name", script->name(),
|
||||
Script::kNameOffset);
|
||||
SetInternalReference(obj, entry,
|
||||
"data", script->data(),
|
||||
Script::kDataOffset);
|
||||
SetInternalReference(obj, entry,
|
||||
"context_data", script->context_data(),
|
||||
Script::kContextOffset);
|
||||
TagObject(script->line_ends(), "(script line ends)");
|
||||
SetInternalReference(obj, entry,
|
||||
"line_ends", script->line_ends(),
|
||||
Script::kLineEndsOffset);
|
||||
} else if (obj->IsDescriptorArray()) {
|
||||
DescriptorArray* desc_array = DescriptorArray::cast(obj);
|
||||
if (desc_array->length() > DescriptorArray::kContentArrayIndex) {
|
||||
Object* content_array =
|
||||
desc_array->get(DescriptorArray::kContentArrayIndex);
|
||||
TagObject(content_array, "(map descriptor content)");
|
||||
SetInternalReference(obj, entry,
|
||||
"content", content_array,
|
||||
FixedArray::OffsetOfElementAt(
|
||||
DescriptorArray::kContentArrayIndex));
|
||||
}
|
||||
} else if (obj->IsCodeCache()) {
|
||||
CodeCache* code_cache = CodeCache::cast(obj);
|
||||
TagObject(code_cache->default_cache(), "(default code cache)");
|
||||
SetInternalReference(obj, entry,
|
||||
"default_cache", code_cache->default_cache(),
|
||||
CodeCache::kDefaultCacheOffset);
|
||||
TagObject(code_cache->normal_type_cache(), "(code type cache)");
|
||||
SetInternalReference(obj, entry,
|
||||
"type_cache", code_cache->normal_type_cache(),
|
||||
CodeCache::kNormalTypeCacheOffset);
|
||||
} else if (obj->IsCode()) {
|
||||
Code* code = Code::cast(obj);
|
||||
TagObject(code->unchecked_relocation_info(), "(code relocation info)");
|
||||
TagObject(code->unchecked_deoptimization_data(), "(code deopt data)");
|
||||
}
|
||||
if (extract_indexed_refs) {
|
||||
SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
|
||||
IndexedReferencesExtractor refs_extractor(this, obj, entry);
|
||||
obj->Iterate(&refs_extractor);
|
||||
@ -2086,7 +2142,7 @@ bool V8HeapExplorer::IterateAndExtractReferences(
|
||||
}
|
||||
SetRootGcRootsReference();
|
||||
RootsReferencesExtractor extractor(this);
|
||||
HEAP->IterateRoots(&extractor, VISIT_ALL);
|
||||
heap_->IterateRoots(&extractor, VISIT_ALL);
|
||||
filler_ = NULL;
|
||||
return progress_->ProgressReport(false);
|
||||
}
|
||||
@ -2241,6 +2297,18 @@ void V8HeapExplorer::SetGcRootsReference(Object* child_obj) {
|
||||
}
|
||||
|
||||
|
||||
void V8HeapExplorer::TagObject(Object* obj, const char* tag) {
|
||||
if (obj->IsHeapObject() &&
|
||||
!obj->IsOddball() &&
|
||||
obj != heap_->raw_unchecked_empty_byte_array() &&
|
||||
obj != heap_->raw_unchecked_empty_fixed_array() &&
|
||||
obj != heap_->raw_unchecked_empty_fixed_double_array() &&
|
||||
obj != heap_->raw_unchecked_empty_descriptor_array()) {
|
||||
objects_tags_.SetTag(obj, tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class GlobalObjectsEnumerator : public ObjectVisitor {
|
||||
public:
|
||||
virtual void VisitPointers(Object** start, Object** end) {
|
||||
|
@ -973,9 +973,11 @@ class V8HeapExplorer : public HeapEntriesAllocator {
|
||||
void SetRootShortcutReference(Object* child);
|
||||
void SetRootGcRootsReference();
|
||||
void SetGcRootsReference(Object* child);
|
||||
void TagObject(Object* obj, const char* tag);
|
||||
|
||||
HeapEntry* GetEntry(Object* obj);
|
||||
|
||||
Heap* heap_;
|
||||
HeapSnapshot* snapshot_;
|
||||
HeapSnapshotsCollection* collection_;
|
||||
SnapshottingProgressReportingInterface* progress_;
|
||||
|
Loading…
Reference in New Issue
Block a user