Better align heap snapshots contents with debugger info.

I created a heap snapshot in Chromium, and then started comparing
it side-by-side with representations of objects provided by
the debugger, fixing discrepancies.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5612 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4e259f81
...@@ -245,7 +245,8 @@ class V8EXPORT HeapGraphNode { ...@@ -245,7 +245,8 @@ class V8EXPORT HeapGraphNode {
kString = 2, // A string. kString = 2, // A string.
kObject = 3, // A JS object (except for arrays and strings). kObject = 3, // A JS object (except for arrays and strings).
kCode = 4, // Compiled code. kCode = 4, // Compiled code.
kClosure = 5 // Function closure. kClosure = 5, // Function closure.
kRegExp = 6 // RegExp.
}; };
/** Returns node type (see HeapGraphNode::Type). */ /** Returns node type (see HeapGraphNode::Type). */
......
...@@ -1180,7 +1180,11 @@ String* JSObject::constructor_name() { ...@@ -1180,7 +1180,11 @@ String* JSObject::constructor_name() {
if (map()->constructor()->IsJSFunction()) { if (map()->constructor()->IsJSFunction()) {
JSFunction* constructor = JSFunction::cast(map()->constructor()); JSFunction* constructor = JSFunction::cast(map()->constructor());
String* name = String::cast(constructor->shared()->name()); String* name = String::cast(constructor->shared()->name());
return name->length() > 0 ? name : constructor->shared()->inferred_name(); if (name->length() > 0) return name;
String* inferred_name = constructor->shared()->inferred_name();
if (inferred_name->length() > 0) return inferred_name;
Object* proto = GetPrototype();
if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
} }
// If the constructor is not present, return "Object". // If the constructor is not present, return "Object".
return Heap::Object_symbol(); return Heap::Object_symbol();
......
...@@ -1001,6 +1001,7 @@ const char* HeapEntry::TypeAsString() { ...@@ -1001,6 +1001,7 @@ const char* HeapEntry::TypeAsString() {
case kString: return "/string/"; case kString: return "/string/";
case kCode: return "/code/"; case kCode: return "/code/";
case kArray: return "/array/"; case kArray: return "/array/";
case kRegExp: return "/regexp/";
default: return "???"; default: return "???";
} }
} }
...@@ -1284,11 +1285,16 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, ...@@ -1284,11 +1285,16 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
} else if (object->IsJSFunction()) { } else if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(object); JSFunction* func = JSFunction::cast(object);
SharedFunctionInfo* shared = func->shared(); SharedFunctionInfo* shared = func->shared();
String* name = String::cast(shared->name())->length() > 0 ?
String::cast(shared->name()) : shared->inferred_name();
return AddEntry(object, return AddEntry(object,
HeapEntry::kClosure, HeapEntry::kClosure,
collection_->GetFunctionName(name), collection_->GetName(String::cast(shared->name())),
children_count,
retainers_count);
} else if (object->IsJSRegExp()) {
JSRegExp* re = JSRegExp::cast(object);
return AddEntry(object,
HeapEntry::kRegExp,
collection_->GetName(re->Pattern()),
children_count, children_count,
retainers_count); retainers_count);
} else if (object->IsJSObject()) { } else if (object->IsJSObject()) {
...@@ -1342,6 +1348,7 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, ...@@ -1342,6 +1348,7 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
bool HeapSnapshot::WillAddEntry(HeapObject* object) { bool HeapSnapshot::WillAddEntry(HeapObject* object) {
return object == kInternalRootObject return object == kInternalRootObject
|| object->IsJSFunction() || object->IsJSFunction()
|| object->IsJSRegExp()
|| object->IsJSObject() || object->IsJSObject()
|| object->IsString() || object->IsString()
|| object->IsCode() || object->IsCode()
...@@ -1905,12 +1912,19 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { ...@@ -1905,12 +1912,19 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
ExtractPropertyReferences(js_obj, entry); ExtractPropertyReferences(js_obj, entry);
ExtractElementReferences(js_obj, entry); ExtractElementReferences(js_obj, entry);
SetPropertyReference( SetPropertyReference(
obj, entry, Heap::prototype_symbol(), js_obj->map()->prototype()); obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype());
if (obj->IsJSFunction()) {
JSFunction* js_fun = JSFunction::cast(obj);
if (js_fun->has_prototype()) {
SetPropertyReference(
obj, entry, Heap::prototype_symbol(), js_fun->prototype());
}
}
} else if (obj->IsString()) { } else if (obj->IsString()) {
if (obj->IsConsString()) { if (obj->IsConsString()) {
ConsString* cs = ConsString::cast(obj); ConsString* cs = ConsString::cast(obj);
SetElementReference(obj, entry, 0, cs->first()); SetInternalReference(obj, entry, "1", cs->first());
SetElementReference(obj, entry, 1, cs->second()); SetInternalReference(obj, entry, "2", cs->second());
} }
} else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) { } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
IndexedReferencesExtractor refs_extractor(this, obj, entry); IndexedReferencesExtractor refs_extractor(this, obj, entry);
...@@ -2055,7 +2069,9 @@ void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj, ...@@ -2055,7 +2069,9 @@ void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
Object* child_obj) { Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) { if (child_entry != NULL) {
filler_->SetNamedReference(HeapGraphEdge::kProperty, HeapGraphEdge::Type type = reference_name->length() > 0 ?
HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
filler_->SetNamedReference(type,
parent_obj, parent_obj,
parent_entry, parent_entry,
collection_->GetName(reference_name), collection_->GetName(reference_name),
...@@ -2351,7 +2367,8 @@ void HeapSnapshotJSONSerializer::SerializeNodes() { ...@@ -2351,7 +2367,8 @@ void HeapSnapshotJSONSerializer::SerializeNodes() {
"," JSON_S("string") "," JSON_S("string")
"," JSON_S("object") "," JSON_S("object")
"," JSON_S("code") "," JSON_S("code")
"," JSON_S("closure")) "," JSON_S("closure")
"," JSON_S("regexp"))
"," JSON_S("string") "," JSON_S("string")
"," JSON_S("number") "," JSON_S("number")
"," JSON_S("number") "," JSON_S("number")
......
...@@ -502,7 +502,8 @@ class HeapEntry BASE_EMBEDDED { ...@@ -502,7 +502,8 @@ class HeapEntry BASE_EMBEDDED {
kString = v8::HeapGraphNode::kString, kString = v8::HeapGraphNode::kString,
kObject = v8::HeapGraphNode::kObject, kObject = v8::HeapGraphNode::kObject,
kCode = v8::HeapGraphNode::kCode, kCode = v8::HeapGraphNode::kCode,
kClosure = v8::HeapGraphNode::kClosure kClosure = v8::HeapGraphNode::kClosure,
kRegExp = v8::HeapGraphNode::kRegExp
}; };
HeapEntry() { } HeapEntry() { }
......
...@@ -594,7 +594,7 @@ TEST(HeapSnapshotObjectSizes) { ...@@ -594,7 +594,7 @@ TEST(HeapSnapshotObjectSizes) {
GetProperty(global, v8::HeapGraphEdge::kProperty, "x"); GetProperty(global, v8::HeapGraphEdge::kProperty, "x");
CHECK_NE(NULL, x); CHECK_NE(NULL, x);
const v8::HeapGraphNode* x_prototype = const v8::HeapGraphNode* x_prototype =
GetProperty(x, v8::HeapGraphEdge::kProperty, "prototype"); GetProperty(x, v8::HeapGraphEdge::kProperty, "__proto__");
CHECK_NE(NULL, x_prototype); CHECK_NE(NULL, x_prototype);
const v8::HeapGraphNode* x1 = const v8::HeapGraphNode* x1 =
GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
...@@ -606,7 +606,7 @@ TEST(HeapSnapshotObjectSizes) { ...@@ -606,7 +606,7 @@ TEST(HeapSnapshotObjectSizes) {
x->GetSelfSize() * 3, x->GetSelfSize() * 3,
x->GetReachableSize() - x_prototype->GetReachableSize()); x->GetReachableSize() - x_prototype->GetReachableSize());
CHECK_EQ( CHECK_EQ(
x->GetSelfSize() * 3 + x_prototype->GetSelfSize(), x->GetRetainedSize()); x->GetSelfSize() * 3, x->GetRetainedSize());
CHECK_EQ( CHECK_EQ(
x1->GetSelfSize() * 2, x1->GetSelfSize() * 2,
x1->GetReachableSize() - x_prototype->GetReachableSize()); x1->GetReachableSize() - x_prototype->GetReachableSize());
...@@ -651,7 +651,6 @@ TEST(HeapSnapshotCodeObjects) { ...@@ -651,7 +651,6 @@ TEST(HeapSnapshotCodeObjects) {
CompileAndRunScript( CompileAndRunScript(
"function lazy(x) { return x - 1; }\n" "function lazy(x) { return x - 1; }\n"
"function compiled(x) { return x + 1; }\n" "function compiled(x) { return x + 1; }\n"
"var inferred = function(x) { return x; }\n"
"var anonymous = (function() { return function() { return 0; } })();\n" "var anonymous = (function() { return function() { return 0; } })();\n"
"compiled(1)"); "compiled(1)");
const v8::HeapSnapshot* snapshot = const v8::HeapSnapshot* snapshot =
...@@ -666,18 +665,12 @@ TEST(HeapSnapshotCodeObjects) { ...@@ -666,18 +665,12 @@ TEST(HeapSnapshotCodeObjects) {
GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy"); GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy");
CHECK_NE(NULL, lazy); CHECK_NE(NULL, lazy);
CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType()); CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType());
const v8::HeapGraphNode* inferred =
GetProperty(global, v8::HeapGraphEdge::kProperty, "inferred");
CHECK_NE(NULL, inferred);
CHECK_EQ(v8::HeapGraphNode::kClosure, inferred->GetType());
v8::String::AsciiValue inferred_name(inferred->GetName());
CHECK_EQ("inferred", *inferred_name);
const v8::HeapGraphNode* anonymous = const v8::HeapGraphNode* anonymous =
GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous"); GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous");
CHECK_NE(NULL, anonymous); CHECK_NE(NULL, anonymous);
CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType()); CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
v8::String::AsciiValue anonymous_name(anonymous->GetName()); v8::String::AsciiValue anonymous_name(anonymous->GetName());
CHECK_EQ("(anonymous function)", *anonymous_name); CHECK_EQ("", *anonymous_name);
// Find references to code. // Find references to code.
const v8::HeapGraphNode* compiled_code = const v8::HeapGraphNode* compiled_code =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment