Revision: 9000
Author:   [email protected]
Date:     Tue Aug 23 05:24:54 2011
Log:      Heap profiler: for objects of class "Object", try to lookup name
from the constructor function. This works well for binding objects,
and this matches DevTools' algorithm for name assignment.

[email protected]
BUG=none
TEST=test-heap-profiler/GetConstructorName

Review URL: http://codereview.chromium.org/7709026
http://code.google.com/p/v8/source/detail?r=9000

Modified:
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/profile-generator.h
 /branches/bleeding_edge/test/cctest/test-heap-profiler.cc

=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Wed Jul 13 02:09:04 2011 +++ /branches/bleeding_edge/src/profile-generator.cc Tue Aug 23 05:24:54 2011
@@ -1663,7 +1663,7 @@
   } else if (object->IsJSGlobalObject()) {
     const char* tag = objects_tags_.GetTag(object);
     const char* name = collection_->names()->GetName(
-        GetConstructorNameForHeapProfile(JSObject::cast(object)));
+        GetConstructorName(JSObject::cast(object)));
     if (tag != NULL) {
       name = collection_->names()->GetFormatted("%s / %s", name, tag);
     }
@@ -1691,8 +1691,7 @@
     return AddEntry(object,
                     HeapEntry::kObject,
                     collection_->names()->GetName(
-                        GetConstructorNameForHeapProfile(
-                            JSObject::cast(object))),
+                        GetConstructorName(JSObject::cast(object))),
                     children_count,
                     retainers_count);
   } else if (object->IsString()) {
@@ -2099,6 +2098,31 @@
         js_obj, entry, i, o, js_obj->GetInternalFieldOffset(i));
   }
 }
+
+
+String* V8HeapExplorer::GetConstructorName(JSObject* object) {
+  if (object->IsJSFunction()) return HEAP->closure_symbol();
+  String* constructor_name = object->constructor_name();
+  if (constructor_name == HEAP->Object_symbol()) {
+    // Look up an immediate "constructor" property, if it is a function,
+    // return its name. This is for instances of binding objects, which
+    // have prototype constructor type "Object".
+    Object* constructor_prop = NULL;
+    LookupResult result;
+ object->LocalLookupRealNamedProperty(HEAP->constructor_symbol(), &result);
+    if (result.IsProperty()) {
+      constructor_prop = result.GetLazyValue();
+    }
+    if (constructor_prop->IsJSFunction()) {
+ Object* maybe_name = JSFunction::cast(constructor_prop)->shared()->name();
+      if (maybe_name->IsString()) {
+        String* name = String::cast(maybe_name);
+        if (name->length() > 0) return name;
+      }
+    }
+  }
+  return object->constructor_name();
+}


 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) {
@@ -3249,11 +3273,5 @@
     sorted_entries->Add(p);
   sorted_entries->Sort(SortUsingEntryValue);
 }
-
-
-String* GetConstructorNameForHeapProfile(JSObject* object) {
-  if (object->IsJSFunction()) return HEAP->closure_symbol();
-  return object->constructor_name();
-}

 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/profile-generator.h     Wed Jul 13 02:09:04 2011
+++ /branches/bleeding_edge/src/profile-generator.h     Tue Aug 23 05:24:54 2011
@@ -921,6 +921,8 @@
   bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
   void TagGlobalObjects();

+  static String* GetConstructorName(JSObject* object);
+
   static HeapObject* const kInternalRootObject;

  private:
@@ -1119,9 +1121,6 @@
   DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
 };

-
-String* GetConstructorNameForHeapProfile(JSObject* object);
-
 } }  // namespace v8::internal

 #endif  // V8_PROFILE_GENERATOR_H_
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Fri Aug 12 02:49:55 2011 +++ /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Tue Aug 23 05:24:54 2011
@@ -889,3 +889,59 @@
   }
   CHECK_EQ(1, count);
 }
+
+
+static int StringCmp(const char* ref, i::String* act) {
+  i::SmartPointer<char> s_act = act->ToCString();
+  int result = strcmp(ref, *s_act);
+  if (result != 0)
+    fprintf(stderr, "Expected: \"%s\", Actual: \"%s\"\n", ref, *s_act);
+  return result;
+}
+
+
+TEST(GetConstructorName) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CompileRun(
+      "function Constructor1() {};\n"
+      "var obj1 = new Constructor1();\n"
+      "var Constructor2 = function() {};\n"
+      "var obj2 = new Constructor2();\n"
+      "var obj3 = {};\n"
+      "obj3.constructor = function Constructor3() {};\n"
+      "var obj4 = {};\n"
+      "// Slow properties\n"
+      "for (var i=0; i<2000; ++i) obj4[\"p\" + i] = i;\n"
+      "obj4.constructor = function Constructor4() {};\n"
+      "var obj5 = {};\n"
+      "var obj6 = {};\n"
+      "obj6.constructor = 6;");
+  v8::Local<v8::Object> js_global =
+      env->Global()->GetPrototype().As<v8::Object>();
+ v8::Local<v8::Object> obj1 = js_global->Get(v8_str("obj1")).As<v8::Object>();
+  i::Handle<i::JSObject> js_obj1 = v8::Utils::OpenHandle(*obj1);
+  CHECK_EQ(0, StringCmp(
+      "Constructor1", i::V8HeapExplorer::GetConstructorName(*js_obj1)));
+ v8::Local<v8::Object> obj2 = js_global->Get(v8_str("obj2")).As<v8::Object>();
+  i::Handle<i::JSObject> js_obj2 = v8::Utils::OpenHandle(*obj2);
+  CHECK_EQ(0, StringCmp(
+      "Constructor2", i::V8HeapExplorer::GetConstructorName(*js_obj2)));
+ v8::Local<v8::Object> obj3 = js_global->Get(v8_str("obj3")).As<v8::Object>();
+  i::Handle<i::JSObject> js_obj3 = v8::Utils::OpenHandle(*obj3);
+  CHECK_EQ(0, StringCmp(
+      "Constructor3", i::V8HeapExplorer::GetConstructorName(*js_obj3)));
+ v8::Local<v8::Object> obj4 = js_global->Get(v8_str("obj4")).As<v8::Object>();
+  i::Handle<i::JSObject> js_obj4 = v8::Utils::OpenHandle(*obj4);
+  CHECK_EQ(0, StringCmp(
+      "Constructor4", i::V8HeapExplorer::GetConstructorName(*js_obj4)));
+ v8::Local<v8::Object> obj5 = js_global->Get(v8_str("obj5")).As<v8::Object>();
+  i::Handle<i::JSObject> js_obj5 = v8::Utils::OpenHandle(*obj5);
+  CHECK_EQ(0, StringCmp(
+      "Object", i::V8HeapExplorer::GetConstructorName(*js_obj5)));
+ v8::Local<v8::Object> obj6 = js_global->Get(v8_str("obj6")).As<v8::Object>();
+  i::Handle<i::JSObject> js_obj6 = v8::Utils::OpenHandle(*obj6);
+  CHECK_EQ(0, StringCmp(
+      "Object", i::V8HeapExplorer::GetConstructorName(*js_obj6)));
+}

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to