Better align heap snapshots contents with debugger info.
authormikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 13 Oct 2010 14:57:00 +0000 (14:57 +0000)
committermikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 13 Oct 2010 14:57:00 +0000 (14:57 +0000)
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

include/v8-profiler.h
src/objects.cc
src/profile-generator.cc
src/profile-generator.h
test/cctest/test-heap-profiler.cc

index 27da418..b59d155 100644 (file)
@@ -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). */
index 883d789..32649bd 100644 (file)
@@ -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();
index 08ee046..fe3bc66 100644 (file)
@@ -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")
index 4206d29..3b67204 100644 (file)
@@ -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() { }
index 6340da5..59b0b5b 100644 (file)
@@ -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 =