Heap profiler: emit more descriptive names for system objects and properties.

BUG=none
TEST=none

Review URL: http://codereview.chromium.org/6776009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7438 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mikhail.naganov@gmail.com 2011-03-30 14:04:50 +00:00
parent 28323284c0
commit b64e85d241
3 changed files with 78 additions and 18 deletions

View File

@ -1690,7 +1690,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
: "",
children_count,
retainers_count);
} else if (object->IsFixedArray()) {
} else if (object->IsFixedArray() || object->IsByteArray()) {
return AddEntry(object,
HeapEntry::kArray,
"",
@ -1705,7 +1705,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
}
return AddEntry(object,
HeapEntry::kHidden,
"system",
GetSystemEntryName(object),
children_count,
retainers_count);
}
@ -1731,6 +1731,21 @@ void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
}
const char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) {
switch (object->map()->instance_type()) {
case MAP_TYPE: return "system / Map";
case JS_GLOBAL_PROPERTY_CELL_TYPE: return "system / JSGlobalPropertyCell";
case PROXY_TYPE: return "system / Proxy";
case ODDBALL_TYPE: return "system / Oddball";
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: return "system / "#Name;
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
default: return "system";
}
}
int V8HeapExplorer::EstimateObjectsCount() {
HeapIterator iterator(HeapIterator::kFilterUnreachable);
int objects_count = 0;
@ -1745,12 +1760,10 @@ class IndexedReferencesExtractor : public ObjectVisitor {
public:
IndexedReferencesExtractor(V8HeapExplorer* generator,
HeapObject* parent_obj,
HeapEntry* parent_entry,
bool process_field_marks = false)
HeapEntry* parent_entry)
: generator_(generator),
parent_obj_(parent_obj),
parent_(parent_entry),
process_field_marks_(process_field_marks),
next_index_(1) {
}
void VisitPointers(Object** start, Object** end) {
@ -1768,7 +1781,7 @@ class IndexedReferencesExtractor : public ObjectVisitor {
}
private:
bool CheckVisitedAndUnmark(Object** field) {
if (process_field_marks_ && (*field)->IsFailure()) {
if ((*field)->IsFailure()) {
intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask;
*field = reinterpret_cast<Object*>(untagged | kHeapObjectTag);
ASSERT((*field)->IsHeapObject());
@ -1779,7 +1792,6 @@ class IndexedReferencesExtractor : public ObjectVisitor {
V8HeapExplorer* generator_;
HeapObject* parent_obj_;
HeapEntry* parent_;
bool process_field_marks_;
int next_index_;
};
@ -1794,6 +1806,7 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
// 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()) {
@ -1806,10 +1819,6 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
obj, entry, HEAP->Proto_symbol(), js_obj->GetPrototype());
if (obj->IsJSFunction()) {
JSFunction* js_fun = JSFunction::cast(js_obj);
SetInternalReference(
js_fun, entry,
"code", js_fun->shared(),
JSFunction::kSharedFunctionInfoOffset);
Object* proto_or_map = js_fun->prototype_or_initial_map();
if (!proto_or_map->IsTheHole()) {
if (!proto_or_map->IsMap()) {
@ -1823,8 +1832,24 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
HEAP->prototype_symbol(), js_fun->prototype());
}
}
SetInternalReference(js_fun, entry,
"shared", js_fun->shared(),
JSFunction::kSharedFunctionInfoOffset);
SetInternalReference(js_fun, entry,
"context", js_fun->unchecked_context(),
JSFunction::kContextOffset);
SetInternalReference(js_fun, entry,
"literals", js_fun->literals(),
JSFunction::kLiteralsOffset);
}
IndexedReferencesExtractor refs_extractor(this, obj, entry, true);
SetInternalReference(obj, entry,
"properties", js_obj->properties(),
JSObject::kPropertiesOffset);
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()) {
@ -1832,7 +1857,41 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
SetInternalReference(obj, entry, 1, cs->first());
SetInternalReference(obj, entry, 2, cs->second());
}
} else if (obj->IsMap()) {
Map* map = Map::cast(obj);
SetInternalReference(obj, entry,
"prototype", map->prototype(), Map::kPrototypeOffset);
SetInternalReference(obj, entry,
"constructor", map->constructor(),
Map::kConstructorOffset);
SetInternalReference(obj, entry,
"descriptors", map->instance_descriptors(),
Map::kInstanceDescriptorsOffset);
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,
"name", shared->name(),
SharedFunctionInfo::kNameOffset);
SetInternalReference(obj, entry,
"code", shared->unchecked_code(),
SharedFunctionInfo::kCodeOffset);
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 {
SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
IndexedReferencesExtractor refs_extractor(this, obj, entry);
obj->Iterate(&refs_extractor);
}
@ -2307,7 +2366,7 @@ void NativeObjectsExplorer::SetWrapperNativeReferences(
ASSERT(info_entry != NULL);
filler_->SetNamedReference(HeapGraphEdge::kInternal,
wrapper, wrapper_entry,
"Native",
"native",
info, info_entry);
filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
info, info_entry,

View File

@ -930,6 +930,7 @@ class V8HeapExplorer : public HeapEntriesAllocator {
const char* name,
int children_count,
int retainers_count);
const char* GetSystemEntryName(HeapObject* object);
void ExtractReferences(HeapObject* obj);
void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry);
void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry);

View File

@ -574,10 +574,10 @@ TEST(HeapSnapshotCodeObjects) {
// Find references to code.
const v8::HeapGraphNode* compiled_code =
GetProperty(compiled, v8::HeapGraphEdge::kInternal, "code");
GetProperty(compiled, v8::HeapGraphEdge::kInternal, "shared");
CHECK_NE(NULL, compiled_code);
const v8::HeapGraphNode* lazy_code =
GetProperty(lazy, v8::HeapGraphEdge::kInternal, "code");
GetProperty(lazy, v8::HeapGraphEdge::kInternal, "shared");
CHECK_NE(NULL, lazy_code);
// Verify that non-compiled code doesn't contain references to "x"
@ -1257,9 +1257,9 @@ TEST(HeapSnapshotRetainedObjectInfo) {
ccc, v8::HeapGraphNode::kString, "CCC");
CHECK_NE(NULL, n_CCC);
CHECK_EQ(aaa, GetProperty(n_AAA, v8::HeapGraphEdge::kInternal, "Native"));
CHECK_EQ(aaa, GetProperty(n_BBB, v8::HeapGraphEdge::kInternal, "Native"));
CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "Native"));
CHECK_EQ(aaa, GetProperty(n_AAA, v8::HeapGraphEdge::kInternal, "native"));
CHECK_EQ(aaa, GetProperty(n_BBB, v8::HeapGraphEdge::kInternal, "native"));
CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "native"));
}