Index: src/heap-profiler.cc |
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc |
index bfd378dda831e352f3c0957c8f390d8f91115cf2..4f9456e174663625a8b4c5faaade1395cc0362c8 100644 |
--- a/src/heap-profiler.cc |
+++ b/src/heap-profiler.cc |
@@ -78,6 +78,10 @@ JSObjectsCluster Clusterizer::Clusterize(HeapObject* obj, bool fine_grain) { |
} |
} else if (obj->IsString()) { |
return JSObjectsCluster(Heap::String_symbol()); |
+ } else if (obj->IsJSGlobalPropertyCell()) { |
+ return JSObjectsCluster(JSObjectsCluster::GLOBAL_PROPERTY); |
+ } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) { |
+ return JSObjectsCluster(JSObjectsCluster::CODE); |
} |
return JSObjectsCluster(); |
} |
@@ -112,6 +116,16 @@ int Clusterizer::CalculateNetworkSize(JSObject* obj) { |
if (FixedArray::cast(obj->elements())->length() != 0) { |
size += obj->elements()->Size(); |
} |
+ // For functions, also account non-empty context and literals sizes. |
+ if (obj->IsJSFunction()) { |
+ JSFunction* f = JSFunction::cast(obj); |
+ if (f->unchecked_context()->IsContext()) { |
+ size += f->context()->Size(); |
+ } |
+ if (f->literals()->length() != 0) { |
+ size += f->literals()->Size(); |
+ } |
+ } |
return size; |
} |
@@ -127,15 +141,15 @@ class ReferencesExtractor : public ObjectVisitor { |
} |
void VisitPointer(Object** o) { |
- if ((*o)->IsJSObject() || (*o)->IsString()) { |
- profile_->StoreReference(cluster_, HeapObject::cast(*o)); |
- } else if ((*o)->IsFixedArray() && !inside_array_) { |
+ if ((*o)->IsFixedArray() && !inside_array_) { |
// Traverse one level deep for data members that are fixed arrays. |
// This covers the case of 'elements' and 'properties' of JSObject, |
// and function contexts. |
inside_array_ = true; |
FixedArray::cast(*o)->Iterate(this); |
inside_array_ = false; |
+ } else { |
+ profile_->StoreReference(cluster_, HeapObject::cast(*o)); |
} |
} |
@@ -340,6 +354,8 @@ void JSObjectsCluster::Print(StringStream* accumulator) const { |
accumulator->Add("(roots)"); |
} else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) { |
accumulator->Add("(global property)"); |
+ } else if (constructor_ == FromSpecialCase(CODE)) { |
+ accumulator->Add("(code)"); |
} else if (constructor_ == FromSpecialCase(SELF)) { |
accumulator->Add("(self)"); |
} else { |
@@ -527,6 +543,7 @@ RetainerHeapProfile::RetainerHeapProfile() |
void RetainerHeapProfile::StoreReference(const JSObjectsCluster& cluster, |
HeapObject* ref) { |
JSObjectsCluster ref_cluster = Clusterizer::Clusterize(ref); |
+ if (ref_cluster.is_null()) return; |
JSObjectsRetainerTree::Locator ref_loc; |
if (retainers_tree_.Insert(ref_cluster, &ref_loc)) { |
ref_loc.set_value(new JSObjectsClusterTree()); |
@@ -537,15 +554,10 @@ void RetainerHeapProfile::StoreReference(const JSObjectsCluster& cluster, |
void RetainerHeapProfile::CollectStats(HeapObject* obj) { |
- if (obj->IsJSObject()) { |
- const JSObjectsCluster cluster = Clusterizer::Clusterize(obj); |
- ReferencesExtractor extractor(cluster, this); |
- obj->Iterate(&extractor); |
- } else if (obj->IsJSGlobalPropertyCell()) { |
- JSObjectsCluster global_prop(JSObjectsCluster::GLOBAL_PROPERTY); |
- ReferencesExtractor extractor(global_prop, this); |
- obj->Iterate(&extractor); |
- } |
+ const JSObjectsCluster cluster = Clusterizer::Clusterize(obj); |
+ if (cluster.is_null()) return; |
+ ReferencesExtractor extractor(cluster, this); |
+ obj->Iterate(&extractor); |
} |