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
This commit is contained in:
parent
4e259f81aa
commit
788c5e344d
@ -245,7 +245,8 @@ class V8EXPORT HeapGraphNode {
|
||||
kString = 2, // A string.
|
||||
kObject = 3, // A JS object (except for arrays and strings).
|
||||
kCode = 4, // Compiled code.
|
||||
kClosure = 5 // Function closure.
|
||||
kClosure = 5, // Function closure.
|
||||
kRegExp = 6 // RegExp.
|
||||
};
|
||||
|
||||
/** Returns node type (see HeapGraphNode::Type). */
|
||||
|
@ -1180,7 +1180,11 @@ String* JSObject::constructor_name() {
|
||||
if (map()->constructor()->IsJSFunction()) {
|
||||
JSFunction* constructor = JSFunction::cast(map()->constructor());
|
||||
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".
|
||||
return Heap::Object_symbol();
|
||||
|
@ -1001,6 +1001,7 @@ const char* HeapEntry::TypeAsString() {
|
||||
case kString: return "/string/";
|
||||
case kCode: return "/code/";
|
||||
case kArray: return "/array/";
|
||||
case kRegExp: return "/regexp/";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
@ -1284,11 +1285,16 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
|
||||
} else if (object->IsJSFunction()) {
|
||||
JSFunction* func = JSFunction::cast(object);
|
||||
SharedFunctionInfo* shared = func->shared();
|
||||
String* name = String::cast(shared->name())->length() > 0 ?
|
||||
String::cast(shared->name()) : shared->inferred_name();
|
||||
return AddEntry(object,
|
||||
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,
|
||||
retainers_count);
|
||||
} else if (object->IsJSObject()) {
|
||||
@ -1342,6 +1348,7 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
|
||||
bool HeapSnapshot::WillAddEntry(HeapObject* object) {
|
||||
return object == kInternalRootObject
|
||||
|| object->IsJSFunction()
|
||||
|| object->IsJSRegExp()
|
||||
|| object->IsJSObject()
|
||||
|| object->IsString()
|
||||
|| object->IsCode()
|
||||
@ -1905,12 +1912,19 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
|
||||
ExtractPropertyReferences(js_obj, entry);
|
||||
ExtractElementReferences(js_obj, entry);
|
||||
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()) {
|
||||
if (obj->IsConsString()) {
|
||||
ConsString* cs = ConsString::cast(obj);
|
||||
SetElementReference(obj, entry, 0, cs->first());
|
||||
SetElementReference(obj, entry, 1, cs->second());
|
||||
SetInternalReference(obj, entry, "1", cs->first());
|
||||
SetInternalReference(obj, entry, "2", cs->second());
|
||||
}
|
||||
} else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
|
||||
IndexedReferencesExtractor refs_extractor(this, obj, entry);
|
||||
@ -2055,7 +2069,9 @@ void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
|
||||
Object* child_obj) {
|
||||
HeapEntry* child_entry = GetEntry(child_obj);
|
||||
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_entry,
|
||||
collection_->GetName(reference_name),
|
||||
@ -2351,7 +2367,8 @@ void HeapSnapshotJSONSerializer::SerializeNodes() {
|
||||
"," JSON_S("string")
|
||||
"," JSON_S("object")
|
||||
"," JSON_S("code")
|
||||
"," JSON_S("closure"))
|
||||
"," JSON_S("closure")
|
||||
"," JSON_S("regexp"))
|
||||
"," JSON_S("string")
|
||||
"," JSON_S("number")
|
||||
"," JSON_S("number")
|
||||
|
@ -502,7 +502,8 @@ class HeapEntry BASE_EMBEDDED {
|
||||
kString = v8::HeapGraphNode::kString,
|
||||
kObject = v8::HeapGraphNode::kObject,
|
||||
kCode = v8::HeapGraphNode::kCode,
|
||||
kClosure = v8::HeapGraphNode::kClosure
|
||||
kClosure = v8::HeapGraphNode::kClosure,
|
||||
kRegExp = v8::HeapGraphNode::kRegExp
|
||||
};
|
||||
|
||||
HeapEntry() { }
|
||||
|
@ -594,7 +594,7 @@ TEST(HeapSnapshotObjectSizes) {
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "x");
|
||||
CHECK_NE(NULL, x);
|
||||
const v8::HeapGraphNode* x_prototype =
|
||||
GetProperty(x, v8::HeapGraphEdge::kProperty, "prototype");
|
||||
GetProperty(x, v8::HeapGraphEdge::kProperty, "__proto__");
|
||||
CHECK_NE(NULL, x_prototype);
|
||||
const v8::HeapGraphNode* x1 =
|
||||
GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
|
||||
@ -606,7 +606,7 @@ TEST(HeapSnapshotObjectSizes) {
|
||||
x->GetSelfSize() * 3,
|
||||
x->GetReachableSize() - x_prototype->GetReachableSize());
|
||||
CHECK_EQ(
|
||||
x->GetSelfSize() * 3 + x_prototype->GetSelfSize(), x->GetRetainedSize());
|
||||
x->GetSelfSize() * 3, x->GetRetainedSize());
|
||||
CHECK_EQ(
|
||||
x1->GetSelfSize() * 2,
|
||||
x1->GetReachableSize() - x_prototype->GetReachableSize());
|
||||
@ -651,7 +651,6 @@ TEST(HeapSnapshotCodeObjects) {
|
||||
CompileAndRunScript(
|
||||
"function lazy(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"
|
||||
"compiled(1)");
|
||||
const v8::HeapSnapshot* snapshot =
|
||||
@ -666,18 +665,12 @@ TEST(HeapSnapshotCodeObjects) {
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy");
|
||||
CHECK_NE(NULL, lazy);
|
||||
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 =
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous");
|
||||
CHECK_NE(NULL, anonymous);
|
||||
CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
|
||||
v8::String::AsciiValue anonymous_name(anonymous->GetName());
|
||||
CHECK_EQ("(anonymous function)", *anonymous_name);
|
||||
CHECK_EQ("", *anonymous_name);
|
||||
|
||||
// Find references to code.
|
||||
const v8::HeapGraphNode* compiled_code =
|
||||
|
Loading…
Reference in New Issue
Block a user