From: mikhail.naganov@gmail.com Date: Wed, 13 Oct 2010 14:57:00 +0000 (+0000) Subject: Better align heap snapshots contents with debugger info. X-Git-Tag: upstream/4.7.83~21096 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=788c5e344dada75adba69d20f59c0f7972e25f33;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/include/v8-profiler.h b/include/v8-profiler.h index 27da418..b59d155 100644 --- a/include/v8-profiler.h +++ b/include/v8-profiler.h @@ -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). */ diff --git a/src/objects.cc b/src/objects.cc index 883d789..32649bd 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -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(); diff --git a/src/profile-generator.cc b/src/profile-generator.cc index 08ee046..fe3bc66 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -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") diff --git a/src/profile-generator.h b/src/profile-generator.h index 4206d29..3b67204 100644 --- a/src/profile-generator.h +++ b/src/profile-generator.h @@ -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() { } diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 6340da5..59b0b5b 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -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 =