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:
parent
28323284c0
commit
b64e85d241
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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"));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user