From 0411b14ffacfcfb25bed37a018db524e630a8f75 Mon Sep 17 00:00:00 2001 From: "mikhail.naganov@gmail.com" Date: Wed, 9 Sep 2009 11:46:09 +0000 Subject: [PATCH] Heap profiler: account primitive string objects as being constructed using 'String'. Also: - move constructor name getter near similar class name getter method; - if the constructor is not present, use 'Object', as for class name, this eliminates a special case. Review URL: http://codereview.chromium.org/202018 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2859 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap.cc | 41 +++++++++++++++++++++-------------------- src/log.cc | 4 +--- src/objects.cc | 18 +++++++++++++++++- src/objects.h | 4 ++++ 4 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/heap.cc b/src/heap.cc index 8498455..8768269 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -3554,7 +3554,7 @@ namespace { class JSConstructorProfile BASE_EMBEDDED { public: JSConstructorProfile() : zscope_(DELETE_ON_EXIT) {} - void CollectStats(JSObject* obj); + void CollectStats(HeapObject* obj); void PrintStats(); // Used by ZoneSplayTree::ForEach. void Call(String* name, const NumberAndSizeInfo& number_and_size); @@ -3599,33 +3599,36 @@ int JSConstructorProfile::CalculateJSObjectNetworkSize(JSObject* obj) { void JSConstructorProfile::Call(String* name, const NumberAndSizeInfo& number_and_size) { - SmartPointer s_name; - if (name != NULL) { - s_name = name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); - } + ASSERT(name != NULL); + SmartPointer s_name( + name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); LOG(HeapSampleJSConstructorEvent(*s_name, number_and_size.number(), number_and_size.bytes())); } -void JSConstructorProfile::CollectStats(JSObject* obj) { - String* constructor_func = NULL; - if (obj->map()->constructor()->IsJSFunction()) { - JSFunction* constructor = JSFunction::cast(obj->map()->constructor()); - SharedFunctionInfo* sfi = constructor->shared(); - String* name = String::cast(sfi->name()); - constructor_func = name->length() > 0 ? name : sfi->inferred_name(); - } else if (obj->IsJSFunction()) { - constructor_func = Heap::function_class_symbol(); +void JSConstructorProfile::CollectStats(HeapObject* obj) { + String* constructor = NULL; + int size; + if (obj->IsString()) { + constructor = Heap::String_symbol(); + size = obj->Size(); + } else if (obj->IsJSObject()) { + JSObject* js_obj = JSObject::cast(obj); + constructor = js_obj->constructor_name(); + size = CalculateJSObjectNetworkSize(js_obj); + } else { + return; } + JSObjectsInfoTree::Locator loc; - if (!js_objects_info_tree_.Find(constructor_func, &loc)) { - js_objects_info_tree_.Insert(constructor_func, &loc); + if (!js_objects_info_tree_.Find(constructor, &loc)) { + js_objects_info_tree_.Insert(constructor, &loc); } NumberAndSizeInfo number_and_size = loc.value(); number_and_size.increment_number(1); - number_and_size.increment_bytes(CalculateJSObjectNetworkSize(obj)); + number_and_size.increment_bytes(size); loc.set_value(number_and_size); } @@ -3667,9 +3670,7 @@ void HeapProfiler::WriteSample() { while (iterator.has_next()) { HeapObject* obj = iterator.next(); CollectStats(obj, info); - if (obj->IsJSObject()) { - js_cons_profile.CollectStats(JSObject::cast(obj)); - } + js_cons_profile.CollectStats(obj); } // Lump all the string types together. diff --git a/src/log.cc b/src/log.cc index 5680820..6bbefbc 100644 --- a/src/log.cc +++ b/src/log.cc @@ -890,9 +890,7 @@ void Logger::HeapSampleJSConstructorEvent(const char* constructor, if (!Log::IsEnabled() || !FLAG_log_gc) return; LogMessageBuilder msg; msg.Append("heap-js-cons-item,%s,%d,%d\n", - constructor != NULL ? - (constructor[0] != '\0' ? constructor : "(anonymous)") : - "(no_constructor)", + constructor[0] != '\0' ? constructor : "(anonymous)", number, bytes); msg.WriteToLogFile(); #endif diff --git a/src/objects.cc b/src/objects.cc index 9ea131f..583af7c 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1186,7 +1186,9 @@ void HeapNumber::HeapNumberPrint(StringStream* accumulator) { String* JSObject::class_name() { - if (IsJSFunction()) return Heap::function_class_symbol(); + if (IsJSFunction()) { + return Heap::function_class_symbol(); + } if (map()->constructor()->IsJSFunction()) { JSFunction* constructor = JSFunction::cast(map()->constructor()); return String::cast(constructor->shared()->instance_class_name()); @@ -1196,6 +1198,20 @@ String* JSObject::class_name() { } +String* JSObject::constructor_name() { + if (IsJSFunction()) { + return Heap::function_class_symbol(); + } + 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 the constructor is not present, return "Object". + return Heap::Object_symbol(); +} + + void JSObject::JSObjectIterateBody(int object_size, ObjectVisitor* v) { // Iterate over all fields in the body. Assumes all are Object*. IteratePointers(v, kPropertiesOffset, object_size); diff --git a/src/objects.h b/src/objects.h index bd8ca51..ca9c6b1 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1392,6 +1392,10 @@ class JSObject: public HeapObject { // Returns the class name ([[Class]] property in the specification). String* class_name(); + // Returns the constructor name (the name (possibly, inferred name) of the + // function that was used to instantiate the object). + String* constructor_name(); + // Retrieve interceptors. InterceptorInfo* GetNamedInterceptor(); InterceptorInfo* GetIndexedInterceptor(); -- 2.7.4