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.

R=sgjesse@chromium.org
BUG=none
TEST=test-heap-profiler/GetConstructorName

Review URL: http://codereview.chromium.org/7709026

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9000 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mikhail.naganov@gmail.com 2011-08-23 12:24:54 +00:00
parent 9eb7d4a53c
commit 2e1e5fc09c
3 changed files with 85 additions and 12 deletions

View File

@ -1663,7 +1663,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
} 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 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
return AddEntry(object,
HeapEntry::kObject,
collection_->names()->GetName(
GetConstructorNameForHeapProfile(
JSObject::cast(object))),
GetConstructorName(JSObject::cast(object))),
children_count,
retainers_count);
} else if (object->IsString()) {
@ -2101,6 +2100,31 @@ void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
}
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) {
if (!obj->IsHeapObject()) return NULL;
return filler_->FindOrAddEntry(obj, this);
@ -3250,10 +3274,4 @@ void HeapSnapshotJSONSerializer::SortHashMap(
sorted_entries->Sort(SortUsingEntryValue);
}
String* GetConstructorNameForHeapProfile(JSObject* object) {
if (object->IsJSFunction()) return HEAP->closure_symbol();
return object->constructor_name();
}
} } // namespace v8::internal

View File

@ -921,6 +921,8 @@ class V8HeapExplorer : public HeapEntriesAllocator {
bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
void TagGlobalObjects();
static String* GetConstructorName(JSObject* object);
static HeapObject* const kInternalRootObject;
private:
@ -1119,9 +1121,6 @@ class HeapSnapshotJSONSerializer {
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
};
String* GetConstructorNameForHeapProfile(JSObject* object);
} } // namespace v8::internal
#endif // V8_PROFILE_GENERATOR_H_

View File

@ -889,3 +889,59 @@ TEST(NodesIteration) {
}
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)));
}