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