Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(316)

Unified Diff: src/heap-profiler.cc

Issue 7247018: Remove obsolete aggregating and non-working producers heap profilers. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/api.cc ('K') | « src/heap-profiler.h ('k') | src/isolate.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap-profiler.cc
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index ec078ed1f70ece6477e85efcfebf4628aa838f53..fb1ea8a641e926bf3e108cf715366e46979586bb 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -28,294 +28,13 @@
#include "v8.h"
#include "heap-profiler.h"
-#include "frames-inl.h"
-#include "global-handles.h"
#include "profile-generator.h"
-#include "string-stream.h"
namespace v8 {
namespace internal {
#ifdef ENABLE_LOGGING_AND_PROFILING
-namespace {
-
-// Clusterizer is a set of helper functions for converting
-// object references into clusters.
-class Clusterizer : public AllStatic {
- public:
- static JSObjectsCluster Clusterize(HeapObject* obj) {
- return Clusterize(obj, true);
- }
- static void InsertIntoTree(JSObjectsClusterTree* tree,
- HeapObject* obj, bool fine_grain);
- static void InsertReferenceIntoTree(JSObjectsClusterTree* tree,
- const JSObjectsCluster& cluster) {
- InsertIntoTree(tree, cluster, 0);
- }
-
- private:
- static JSObjectsCluster Clusterize(HeapObject* obj, bool fine_grain);
- static int CalculateNetworkSize(JSObject* obj);
- static int GetObjectSize(HeapObject* obj) {
- return obj->IsJSObject() ?
- CalculateNetworkSize(JSObject::cast(obj)) : obj->Size();
- }
- static void InsertIntoTree(JSObjectsClusterTree* tree,
- const JSObjectsCluster& cluster, int size);
-};
-
-
-JSObjectsCluster Clusterizer::Clusterize(HeapObject* obj, bool fine_grain) {
- if (obj->IsJSObject()) {
- JSObject* js_obj = JSObject::cast(obj);
- String* constructor = GetConstructorNameForHeapProfile(
- JSObject::cast(js_obj));
- // Differentiate Object and Array instances.
- if (fine_grain && (constructor == HEAP->Object_symbol() ||
- constructor == HEAP->Array_symbol())) {
- return JSObjectsCluster(constructor, obj);
- } else {
- return JSObjectsCluster(constructor);
- }
- } 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();
-}
-
-
-void Clusterizer::InsertIntoTree(JSObjectsClusterTree* tree,
- HeapObject* obj, bool fine_grain) {
- JSObjectsCluster cluster = Clusterize(obj, fine_grain);
- if (cluster.is_null()) return;
- InsertIntoTree(tree, cluster, GetObjectSize(obj));
-}
-
-
-void Clusterizer::InsertIntoTree(JSObjectsClusterTree* tree,
- const JSObjectsCluster& cluster, int size) {
- JSObjectsClusterTree::Locator loc;
- tree->Insert(cluster, &loc);
- NumberAndSizeInfo number_and_size = loc.value();
- number_and_size.increment_number(1);
- number_and_size.increment_bytes(size);
- loc.set_value(number_and_size);
-}
-
-
-int Clusterizer::CalculateNetworkSize(JSObject* obj) {
- int size = obj->Size();
- // If 'properties' and 'elements' are non-empty (thus, non-shared),
- // take their size into account.
- if (obj->properties() != HEAP->empty_fixed_array()) {
- size += obj->properties()->Size();
- }
- if (obj->elements() != HEAP->empty_fixed_array()) {
- 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;
-}
-
-
-// A helper class for recording back references.
-class ReferencesExtractor : public ObjectVisitor {
- public:
- ReferencesExtractor(const JSObjectsCluster& cluster,
- RetainerHeapProfile* profile)
- : cluster_(cluster),
- profile_(profile),
- inside_array_(false) {
- }
-
- void VisitPointer(Object** o) {
- 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 if ((*o)->IsHeapObject()) {
- profile_->StoreReference(cluster_, HeapObject::cast(*o));
- }
- }
-
- void VisitPointers(Object** start, Object** end) {
- for (Object** p = start; p < end; p++) VisitPointer(p);
- }
-
- private:
- const JSObjectsCluster& cluster_;
- RetainerHeapProfile* profile_;
- bool inside_array_;
-};
-
-
-// A printer interface implementation for the Retainers profile.
-class RetainersPrinter : public RetainerHeapProfile::Printer {
- public:
- void PrintRetainers(const JSObjectsCluster& cluster,
- const StringStream& retainers) {
- HeapStringAllocator allocator;
- StringStream stream(&allocator);
- cluster.Print(&stream);
- LOG(ISOLATE,
- HeapSampleJSRetainersEvent(
- *(stream.ToCString()), *(retainers.ToCString())));
- }
-};
-
-
-// Visitor for printing a cluster tree.
-class ClusterTreePrinter BASE_EMBEDDED {
- public:
- explicit ClusterTreePrinter(StringStream* stream) : stream_(stream) {}
- void Call(const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size) {
- Print(stream_, cluster, number_and_size);
- }
- static void Print(StringStream* stream,
- const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size);
-
- private:
- StringStream* stream_;
-};
-
-
-void ClusterTreePrinter::Print(StringStream* stream,
- const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size) {
- stream->Put(',');
- cluster.Print(stream);
- stream->Add(";%d", number_and_size.number());
-}
-
-
-// Visitor for printing a retainer tree.
-class SimpleRetainerTreePrinter BASE_EMBEDDED {
- public:
- explicit SimpleRetainerTreePrinter(RetainerHeapProfile::Printer* printer)
- : printer_(printer) {}
- void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree);
-
- private:
- RetainerHeapProfile::Printer* printer_;
-};
-
-
-void SimpleRetainerTreePrinter::Call(const JSObjectsCluster& cluster,
- JSObjectsClusterTree* tree) {
- HeapStringAllocator allocator;
- StringStream stream(&allocator);
- ClusterTreePrinter retainers_printer(&stream);
- tree->ForEach(&retainers_printer);
- printer_->PrintRetainers(cluster, stream);
-}
-
-
-// Visitor for aggregating references count of equivalent clusters.
-class RetainersAggregator BASE_EMBEDDED {
- public:
- RetainersAggregator(ClustersCoarser* coarser, JSObjectsClusterTree* dest_tree)
- : coarser_(coarser), dest_tree_(dest_tree) {}
- void Call(const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size);
-
- private:
- ClustersCoarser* coarser_;
- JSObjectsClusterTree* dest_tree_;
-};
-
-
-void RetainersAggregator::Call(const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size) {
- JSObjectsCluster eq = coarser_->GetCoarseEquivalent(cluster);
- if (eq.is_null()) eq = cluster;
- JSObjectsClusterTree::Locator loc;
- dest_tree_->Insert(eq, &loc);
- NumberAndSizeInfo aggregated_number = loc.value();
- aggregated_number.increment_number(number_and_size.number());
- loc.set_value(aggregated_number);
-}
-
-
-// Visitor for printing retainers tree. Aggregates equivalent retainer clusters.
-class AggregatingRetainerTreePrinter BASE_EMBEDDED {
- public:
- AggregatingRetainerTreePrinter(ClustersCoarser* coarser,
- RetainerHeapProfile::Printer* printer)
- : coarser_(coarser), printer_(printer) {}
- void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree);
-
- private:
- ClustersCoarser* coarser_;
- RetainerHeapProfile::Printer* printer_;
-};
-
-
-void AggregatingRetainerTreePrinter::Call(const JSObjectsCluster& cluster,
- JSObjectsClusterTree* tree) {
- if (!coarser_->GetCoarseEquivalent(cluster).is_null()) return;
- JSObjectsClusterTree dest_tree_;
- RetainersAggregator retainers_aggregator(coarser_, &dest_tree_);
- tree->ForEach(&retainers_aggregator);
- HeapStringAllocator allocator;
- StringStream stream(&allocator);
- ClusterTreePrinter retainers_printer(&stream);
- dest_tree_.ForEach(&retainers_printer);
- printer_->PrintRetainers(cluster, stream);
-}
-
-} // namespace
-
-
-// A helper class for building a retainers tree, that aggregates
-// all equivalent clusters.
-class RetainerTreeAggregator {
- public:
- explicit RetainerTreeAggregator(ClustersCoarser* coarser)
- : coarser_(coarser) {}
- void Process(JSObjectsRetainerTree* input_tree) {
- input_tree->ForEach(this);
- }
- void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree);
- JSObjectsRetainerTree& output_tree() { return output_tree_; }
-
- private:
- ClustersCoarser* coarser_;
- JSObjectsRetainerTree output_tree_;
-};
-
-
-void RetainerTreeAggregator::Call(const JSObjectsCluster& cluster,
- JSObjectsClusterTree* tree) {
- JSObjectsCluster eq = coarser_->GetCoarseEquivalent(cluster);
- if (eq.is_null()) return;
- JSObjectsRetainerTree::Locator loc;
- if (output_tree_.Insert(eq, &loc)) {
- loc.set_value(new JSObjectsClusterTree());
- }
- RetainersAggregator retainers_aggregator(coarser_, loc.value());
- tree->ForEach(&retainers_aggregator);
-}
-
-
HeapProfiler::HeapProfiler()
: snapshots_(new HeapSnapshotsCollection()),
next_snapshot_uid_(1) {
@@ -409,14 +128,6 @@ HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name,
generation_completed = generator.GenerateSnapshot();
break;
}
- case HeapSnapshot::kAggregated: {
- HEAP->CollectAllGarbage(true);
- AggregatedHeapSnapshot agg_snapshot;
- AggregatedHeapSnapshotGenerator generator(&agg_snapshot);
- generator.GenerateSnapshot();
- generator.FillHeapSnapshot(result);
- break;
- }
default:
UNREACHABLE();
}
@@ -468,705 +179,6 @@ void HeapProfiler::ObjectMoveEvent(Address from, Address to) {
snapshots_->ObjectMoveEvent(from, to);
}
-
-const JSObjectsClusterTreeConfig::Key JSObjectsClusterTreeConfig::kNoKey;
-const JSObjectsClusterTreeConfig::Value JSObjectsClusterTreeConfig::kNoValue;
-
-
-ConstructorHeapProfile::ConstructorHeapProfile()
- : zscope_(Isolate::Current(), DELETE_ON_EXIT) {
-}
-
-
-void ConstructorHeapProfile::Call(const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size) {
- HeapStringAllocator allocator;
- StringStream stream(&allocator);
- cluster.Print(&stream);
- LOG(ISOLATE,
- HeapSampleJSConstructorEvent(*(stream.ToCString()),
- number_and_size.number(),
- number_and_size.bytes()));
-}
-
-
-void ConstructorHeapProfile::CollectStats(HeapObject* obj) {
- Clusterizer::InsertIntoTree(&js_objects_info_tree_, obj, false);
-}
-
-
-void ConstructorHeapProfile::PrintStats() {
- js_objects_info_tree_.ForEach(this);
-}
-
-
-static const char* GetConstructorName(const char* name) {
- return name[0] != '\0' ? name : "(anonymous)";
-}
-
-
-const char* JSObjectsCluster::GetSpecialCaseName() const {
- if (constructor_ == FromSpecialCase(ROOTS)) {
- return "(roots)";
- } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) {
- return "(global property)";
- } else if (constructor_ == FromSpecialCase(CODE)) {
- return "(code)";
- } else if (constructor_ == FromSpecialCase(SELF)) {
- return "(self)";
- }
- return NULL;
-}
-
-
-void JSObjectsCluster::Print(StringStream* accumulator) const {
- ASSERT(!is_null());
- const char* special_case_name = GetSpecialCaseName();
- if (special_case_name != NULL) {
- accumulator->Add(special_case_name);
- } else {
- SmartPointer<char> s_name(
- constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
- accumulator->Add("%s", GetConstructorName(*s_name));
- if (instance_ != NULL) {
- accumulator->Add(":%p", static_cast<void*>(instance_));
- }
- }
-}
-
-
-void JSObjectsCluster::DebugPrint(StringStream* accumulator) const {
- if (!is_null()) {
- Print(accumulator);
- } else {
- accumulator->Add("(null cluster)");
- }
-}
-
-
-inline ClustersCoarser::ClusterBackRefs::ClusterBackRefs(
- const JSObjectsCluster& cluster_)
- : cluster(cluster_), refs(kInitialBackrefsListCapacity) {
-}
-
-
-inline ClustersCoarser::ClusterBackRefs::ClusterBackRefs(
- const ClustersCoarser::ClusterBackRefs& src)
- : cluster(src.cluster), refs(src.refs.capacity()) {
- refs.AddAll(src.refs);
-}
-
-
-inline ClustersCoarser::ClusterBackRefs&
- ClustersCoarser::ClusterBackRefs::operator=(
- const ClustersCoarser::ClusterBackRefs& src) {
- if (this == &src) return *this;
- cluster = src.cluster;
- refs.Clear();
- refs.AddAll(src.refs);
- return *this;
-}
-
-
-inline int ClustersCoarser::ClusterBackRefs::Compare(
- const ClustersCoarser::ClusterBackRefs& a,
- const ClustersCoarser::ClusterBackRefs& b) {
- int cmp = JSObjectsCluster::CompareConstructors(a.cluster, b.cluster);
- if (cmp != 0) return cmp;
- if (a.refs.length() < b.refs.length()) return -1;
- if (a.refs.length() > b.refs.length()) return 1;
- for (int i = 0; i < a.refs.length(); ++i) {
- int cmp = JSObjectsCluster::Compare(a.refs[i], b.refs[i]);
- if (cmp != 0) return cmp;
- }
- return 0;
-}
-
-
-ClustersCoarser::ClustersCoarser()
- : zscope_(Isolate::Current(), DELETE_ON_EXIT),
- sim_list_(ClustersCoarser::kInitialSimilarityListCapacity),
- current_pair_(NULL),
- current_set_(NULL),
- self_(NULL) {
-}
-
-
-void ClustersCoarser::Call(const JSObjectsCluster& cluster,
- JSObjectsClusterTree* tree) {
- if (!cluster.can_be_coarsed()) return;
- ClusterBackRefs pair(cluster);
- ASSERT(current_pair_ == NULL);
- current_pair_ = &pair;
- current_set_ = new JSObjectsRetainerTree();
- self_ = &cluster;
- tree->ForEach(this);
- sim_list_.Add(pair);
- current_pair_ = NULL;
- current_set_ = NULL;
- self_ = NULL;
-}
-
-
-void ClustersCoarser::Call(const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size) {
- ASSERT(current_pair_ != NULL);
- ASSERT(current_set_ != NULL);
- ASSERT(self_ != NULL);
- JSObjectsRetainerTree::Locator loc;
- if (JSObjectsCluster::Compare(*self_, cluster) == 0) {
- current_pair_->refs.Add(JSObjectsCluster(JSObjectsCluster::SELF));
- return;
- }
- JSObjectsCluster eq = GetCoarseEquivalent(cluster);
- if (!eq.is_null()) {
- if (current_set_->Find(eq, &loc)) return;
- current_pair_->refs.Add(eq);
- current_set_->Insert(eq, &loc);
- } else {
- current_pair_->refs.Add(cluster);
- }
-}
-
-
-void ClustersCoarser::Process(JSObjectsRetainerTree* tree) {
- int last_eq_clusters = -1;
- for (int i = 0; i < kMaxPassesCount; ++i) {
- sim_list_.Clear();
- const int curr_eq_clusters = DoProcess(tree);
- // If no new cluster equivalents discovered, abort processing.
- if (last_eq_clusters == curr_eq_clusters) break;
- last_eq_clusters = curr_eq_clusters;
- }
-}
-
-
-int ClustersCoarser::DoProcess(JSObjectsRetainerTree* tree) {
- tree->ForEach(this);
- sim_list_.Iterate(ClusterBackRefs::SortRefsIterator);
- sim_list_.Sort(ClusterBackRefsCmp);
- return FillEqualityTree();
-}
-
-
-JSObjectsCluster ClustersCoarser::GetCoarseEquivalent(
- const JSObjectsCluster& cluster) {
- if (!cluster.can_be_coarsed()) return JSObjectsCluster();
- EqualityTree::Locator loc;
- return eq_tree_.Find(cluster, &loc) ? loc.value() : JSObjectsCluster();
-}
-
-
-bool ClustersCoarser::HasAnEquivalent(const JSObjectsCluster& cluster) {
- // Return true for coarsible clusters that have a non-identical equivalent.
- if (!cluster.can_be_coarsed()) return false;
- JSObjectsCluster eq = GetCoarseEquivalent(cluster);
- return !eq.is_null() && JSObjectsCluster::Compare(cluster, eq) != 0;
-}
-
-
-int ClustersCoarser::FillEqualityTree() {
- int eq_clusters_count = 0;
- int eq_to = 0;
- bool first_added = false;
- for (int i = 1; i < sim_list_.length(); ++i) {
- if (ClusterBackRefs::Compare(sim_list_[i], sim_list_[eq_to]) == 0) {
- EqualityTree::Locator loc;
- if (!first_added) {
- // Add self-equivalence, if we have more than one item in this
- // equivalence class.
- eq_tree_.Insert(sim_list_[eq_to].cluster, &loc);
- loc.set_value(sim_list_[eq_to].cluster);
- first_added = true;
- }
- eq_tree_.Insert(sim_list_[i].cluster, &loc);
- loc.set_value(sim_list_[eq_to].cluster);
- ++eq_clusters_count;
- } else {
- eq_to = i;
- first_added = false;
- }
- }
- return eq_clusters_count;
-}
-
-
-const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoKey;
-const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoValue;
-const JSObjectsRetainerTreeConfig::Key JSObjectsRetainerTreeConfig::kNoKey;
-const JSObjectsRetainerTreeConfig::Value JSObjectsRetainerTreeConfig::kNoValue =
- NULL;
-
-
-RetainerHeapProfile::RetainerHeapProfile()
- : zscope_(Isolate::Current(), DELETE_ON_EXIT),
- aggregator_(NULL) {
- JSObjectsCluster roots(JSObjectsCluster::ROOTS);
- ReferencesExtractor extractor(roots, this);
- HEAP->IterateRoots(&extractor, VISIT_ONLY_STRONG);
-}
-
-
-RetainerHeapProfile::~RetainerHeapProfile() {
- delete aggregator_;
-}
-
-
-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());
- }
- JSObjectsClusterTree* referenced_by = ref_loc.value();
- Clusterizer::InsertReferenceIntoTree(referenced_by, cluster);
-}
-
-
-void RetainerHeapProfile::CollectStats(HeapObject* obj) {
- const JSObjectsCluster cluster = Clusterizer::Clusterize(obj);
- if (cluster.is_null()) return;
- ReferencesExtractor extractor(cluster, this);
- obj->Iterate(&extractor);
-}
-
-
-void RetainerHeapProfile::CoarseAndAggregate() {
- coarser_.Process(&retainers_tree_);
- ASSERT(aggregator_ == NULL);
- aggregator_ = new RetainerTreeAggregator(&coarser_);
- aggregator_->Process(&retainers_tree_);
-}
-
-
-void RetainerHeapProfile::DebugPrintStats(
- RetainerHeapProfile::Printer* printer) {
- // Print clusters that have no equivalents, aggregating their retainers.
- AggregatingRetainerTreePrinter agg_printer(&coarser_, printer);
- retainers_tree_.ForEach(&agg_printer);
- // Print clusters that have equivalents.
- SimpleRetainerTreePrinter s_printer(printer);
- aggregator_->output_tree().ForEach(&s_printer);
-}
-
-
-void RetainerHeapProfile::PrintStats() {
- RetainersPrinter printer;
- DebugPrintStats(&printer);
-}
-
-
-//
-// HeapProfiler class implementation.
-//
-static void StackWeakReferenceCallback(Persistent<Value> object,
- void* trace) {
- DeleteArray(static_cast<Address*>(trace));
- object.Dispose();
-}
-
-
-static void PrintProducerStackTrace(Object* obj, void* trace) {
- if (!obj->IsJSObject()) return;
- String* constructor = GetConstructorNameForHeapProfile(JSObject::cast(obj));
- SmartPointer<char> s_name(
- constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
- LOG(ISOLATE,
- HeapSampleJSProducerEvent(GetConstructorName(*s_name),
- reinterpret_cast<Address*>(trace)));
-}
-
-
-void HeapProfiler::WriteSample() {
- Isolate* isolate = Isolate::Current();
- LOG(isolate, HeapSampleBeginEvent("Heap", "allocated"));
- LOG(isolate,
- HeapSampleStats(
- "Heap", "allocated", HEAP->CommittedMemory(), HEAP->SizeOfObjects()));
-
- AggregatedHeapSnapshot snapshot;
- AggregatedHeapSnapshotGenerator generator(&snapshot);
- generator.GenerateSnapshot();
-
- HistogramInfo* info = snapshot.info();
- for (int i = FIRST_NONSTRING_TYPE;
- i <= AggregatedHeapSnapshotGenerator::kAllStringsType;
- ++i) {
- if (info[i].bytes() > 0) {
- LOG(isolate,
- HeapSampleItemEvent(info[i].name(), info[i].number(),
- info[i].bytes()));
- }
- }
-
- snapshot.js_cons_profile()->PrintStats();
- snapshot.js_retainer_profile()->PrintStats();
-
- isolate->global_handles()->IterateWeakRoots(PrintProducerStackTrace,
- StackWeakReferenceCallback);
-
- LOG(isolate, HeapSampleEndEvent("Heap", "allocated"));
-}
-
-
-AggregatedHeapSnapshot::AggregatedHeapSnapshot()
- : info_(NewArray<HistogramInfo>(
- AggregatedHeapSnapshotGenerator::kAllStringsType + 1)) {
-#define DEF_TYPE_NAME(name) info_[name].set_name(#name);
- INSTANCE_TYPE_LIST(DEF_TYPE_NAME);
-#undef DEF_TYPE_NAME
- info_[AggregatedHeapSnapshotGenerator::kAllStringsType].set_name(
- "STRING_TYPE");
-}
-
-
-AggregatedHeapSnapshot::~AggregatedHeapSnapshot() {
- DeleteArray(info_);
-}
-
-
-AggregatedHeapSnapshotGenerator::AggregatedHeapSnapshotGenerator(
- AggregatedHeapSnapshot* agg_snapshot)
- : agg_snapshot_(agg_snapshot) {
-}
-
-
-void AggregatedHeapSnapshotGenerator::CalculateStringsStats() {
- HistogramInfo* info = agg_snapshot_->info();
- HistogramInfo& strings = info[kAllStringsType];
- // Lump all the string types together.
-#define INCREMENT_SIZE(type, size, name, camel_name) \
- strings.increment_number(info[type].number()); \
- strings.increment_bytes(info[type].bytes());
- STRING_TYPE_LIST(INCREMENT_SIZE);
-#undef INCREMENT_SIZE
-}
-
-
-void AggregatedHeapSnapshotGenerator::CollectStats(HeapObject* obj) {
- InstanceType type = obj->map()->instance_type();
- ASSERT(0 <= type && type <= LAST_TYPE);
- agg_snapshot_->info()[type].increment_number(1);
- agg_snapshot_->info()[type].increment_bytes(obj->Size());
-}
-
-
-void AggregatedHeapSnapshotGenerator::GenerateSnapshot() {
- HeapIterator iterator(HeapIterator::kFilterUnreachable);
- for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
- CollectStats(obj);
- agg_snapshot_->js_cons_profile()->CollectStats(obj);
- agg_snapshot_->js_retainer_profile()->CollectStats(obj);
- }
- CalculateStringsStats();
- agg_snapshot_->js_retainer_profile()->CoarseAndAggregate();
-}
-
-
-class CountingConstructorHeapProfileIterator {
- public:
- CountingConstructorHeapProfileIterator()
- : entities_count_(0), children_count_(0) {
- }
-
- void Call(const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size) {
- ++entities_count_;
- children_count_ += number_and_size.number();
- }
-
- int entities_count() { return entities_count_; }
- int children_count() { return children_count_; }
-
- private:
- int entities_count_;
- int children_count_;
-};
-
-
-static HeapEntry* AddEntryFromAggregatedSnapshot(HeapSnapshot* snapshot,
- int* root_child_index,
- HeapEntry::Type type,
- const char* name,
- int count,
- int size,
- int children_count,
- int retainers_count) {
- HeapEntry* entry = snapshot->AddEntry(
- type, name, count, size, children_count, retainers_count);
- ASSERT(entry != NULL);
- snapshot->root()->SetUnidirElementReference(*root_child_index,
- *root_child_index + 1,
- entry);
- *root_child_index = *root_child_index + 1;
- return entry;
-}
-
-
-class AllocatingConstructorHeapProfileIterator {
- public:
- AllocatingConstructorHeapProfileIterator(HeapSnapshot* snapshot,
- int* root_child_index)
- : snapshot_(snapshot),
- root_child_index_(root_child_index) {
- }
-
- void Call(const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size) {
- const char* name = cluster.GetSpecialCaseName();
- if (name == NULL) {
- name = snapshot_->collection()->names()->GetFunctionName(
- cluster.constructor());
- }
- AddEntryFromAggregatedSnapshot(snapshot_,
- root_child_index_,
- HeapEntry::kObject,
- name,
- number_and_size.number(),
- number_and_size.bytes(),
- 0,
- 0);
- }
-
- private:
- HeapSnapshot* snapshot_;
- int* root_child_index_;
-};
-
-
-static HeapObject* ClusterAsHeapObject(const JSObjectsCluster& cluster) {
- return cluster.can_be_coarsed() ?
- reinterpret_cast<HeapObject*>(cluster.instance()) : cluster.constructor();
-}
-
-
-static JSObjectsCluster HeapObjectAsCluster(HeapObject* object) {
- if (object->IsString()) {
- return JSObjectsCluster(String::cast(object));
- } else {
- JSObject* js_obj = JSObject::cast(object);
- String* constructor = GetConstructorNameForHeapProfile(
- JSObject::cast(js_obj));
- return JSObjectsCluster(constructor, object);
- }
-}
-
-
-class CountingRetainersIterator {
- public:
- CountingRetainersIterator(const JSObjectsCluster& child_cluster,
- HeapEntriesAllocator* allocator,
- HeapEntriesMap* map)
- : child_(ClusterAsHeapObject(child_cluster)),
- allocator_(allocator),
- map_(map) {
- if (map_->Map(child_) == NULL)
- map_->Pair(child_, allocator_, HeapEntriesMap::kHeapEntryPlaceholder);
- }
-
- void Call(const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size) {
- if (map_->Map(ClusterAsHeapObject(cluster)) == NULL)
- map_->Pair(ClusterAsHeapObject(cluster),
- allocator_,
- HeapEntriesMap::kHeapEntryPlaceholder);
- map_->CountReference(ClusterAsHeapObject(cluster), child_);
- }
-
- private:
- HeapObject* child_;
- HeapEntriesAllocator* allocator_;
- HeapEntriesMap* map_;
-};
-
-
-class AllocatingRetainersIterator {
- public:
- AllocatingRetainersIterator(const JSObjectsCluster& child_cluster,
- HeapEntriesAllocator*,
- HeapEntriesMap* map)
- : child_(ClusterAsHeapObject(child_cluster)), map_(map) {
- child_entry_ = map_->Map(child_);
- ASSERT(child_entry_ != NULL);
- }
-
- void Call(const JSObjectsCluster& cluster,
- const NumberAndSizeInfo& number_and_size) {
- int child_index, retainer_index;
- map_->CountReference(ClusterAsHeapObject(cluster),
- child_,
- &child_index,
- &retainer_index);
- map_->Map(ClusterAsHeapObject(cluster))->SetIndexedReference(
- HeapGraphEdge::kElement,
- child_index,
- number_and_size.number(),
- child_entry_,
- retainer_index);
- }
-
- private:
- HeapObject* child_;
- HeapEntriesMap* map_;
- HeapEntry* child_entry_;
-};
-
-
-template<class RetainersIterator>
-class AggregatingRetainerTreeIterator {
- public:
- explicit AggregatingRetainerTreeIterator(ClustersCoarser* coarser,
- HeapEntriesAllocator* allocator,
- HeapEntriesMap* map)
- : coarser_(coarser), allocator_(allocator), map_(map) {
- }
-
- void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree) {
- if (coarser_ != NULL &&
- !coarser_->GetCoarseEquivalent(cluster).is_null()) return;
- JSObjectsClusterTree* tree_to_iterate = tree;
- ZoneScope zs(Isolate::Current(), DELETE_ON_EXIT);
- JSObjectsClusterTree dest_tree_;
- if (coarser_ != NULL) {
- RetainersAggregator retainers_aggregator(coarser_, &dest_tree_);
- tree->ForEach(&retainers_aggregator);
- tree_to_iterate = &dest_tree_;
- }
- RetainersIterator iterator(cluster, allocator_, map_);
- tree_to_iterate->ForEach(&iterator);
- }
-
- private:
- ClustersCoarser* coarser_;
- HeapEntriesAllocator* allocator_;
- HeapEntriesMap* map_;
-};
-
-
-class AggregatedRetainerTreeAllocator : public HeapEntriesAllocator {
- public:
- AggregatedRetainerTreeAllocator(HeapSnapshot* snapshot,
- int* root_child_index)
- : snapshot_(snapshot), root_child_index_(root_child_index) {
- }
- ~AggregatedRetainerTreeAllocator() { }
-
- HeapEntry* AllocateEntry(
- HeapThing ptr, int children_count, int retainers_count) {
- HeapObject* obj = reinterpret_cast<HeapObject*>(ptr);
- JSObjectsCluster cluster = HeapObjectAsCluster(obj);
- const char* name = cluster.GetSpecialCaseName();
- if (name == NULL) {
- name = snapshot_->collection()->names()->GetFunctionName(
- cluster.constructor());
- }
- return AddEntryFromAggregatedSnapshot(
- snapshot_, root_child_index_, HeapEntry::kObject, name,
- 0, 0, children_count, retainers_count);
- }
-
- private:
- HeapSnapshot* snapshot_;
- int* root_child_index_;
-};
-
-
-template<class Iterator>
-void AggregatedHeapSnapshotGenerator::IterateRetainers(
- HeapEntriesAllocator* allocator, HeapEntriesMap* entries_map) {
- RetainerHeapProfile* p = agg_snapshot_->js_retainer_profile();
- AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_1(
- p->coarser(), allocator, entries_map);
- p->retainers_tree()->ForEach(&agg_ret_iter_1);
- AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_2(
- NULL, allocator, entries_map);
- p->aggregator()->output_tree().ForEach(&agg_ret_iter_2);
-}
-
-
-void AggregatedHeapSnapshotGenerator::FillHeapSnapshot(HeapSnapshot* snapshot) {
- // Count the number of entities.
- int histogram_entities_count = 0;
- int histogram_children_count = 0;
- int histogram_retainers_count = 0;
- for (int i = FIRST_NONSTRING_TYPE; i <= kAllStringsType; ++i) {
- if (agg_snapshot_->info()[i].bytes() > 0) {
- ++histogram_entities_count;
- }
- }
- CountingConstructorHeapProfileIterator counting_cons_iter;
- agg_snapshot_->js_cons_profile()->ForEach(&counting_cons_iter);
- histogram_entities_count += counting_cons_iter.entities_count();
- HeapEntriesMap entries_map;
- int root_child_index = 0;
- AggregatedRetainerTreeAllocator allocator(snapshot, &root_child_index);
- IterateRetainers<CountingRetainersIterator>(&allocator, &entries_map);
- histogram_entities_count += entries_map.entries_count();
- histogram_children_count += entries_map.total_children_count();
- histogram_retainers_count += entries_map.total_retainers_count();
-
- // Root entry references all other entries.
- histogram_children_count += histogram_entities_count;
- int root_children_count = histogram_entities_count;
- ++histogram_entities_count;
-
- // Allocate and fill entries in the snapshot, allocate references.
- snapshot->AllocateEntries(histogram_entities_count,
- histogram_children_count,
- histogram_retainers_count);
- snapshot->AddRootEntry(root_children_count);
- for (int i = FIRST_NONSTRING_TYPE; i <= kAllStringsType; ++i) {
- if (agg_snapshot_->info()[i].bytes() > 0) {
- AddEntryFromAggregatedSnapshot(snapshot,
- &root_child_index,
- HeapEntry::kHidden,
- agg_snapshot_->info()[i].name(),
- agg_snapshot_->info()[i].number(),
- agg_snapshot_->info()[i].bytes(),
- 0,
- 0);
- }
- }
- AllocatingConstructorHeapProfileIterator alloc_cons_iter(
- snapshot, &root_child_index);
- agg_snapshot_->js_cons_profile()->ForEach(&alloc_cons_iter);
- entries_map.AllocateEntries();
-
- // Fill up references.
- IterateRetainers<AllocatingRetainersIterator>(&allocator, &entries_map);
-
- snapshot->SetDominatorsToSelf();
-}
-
-
-void ProducerHeapProfile::Setup() {
- can_log_ = true;
-}
-
-void ProducerHeapProfile::DoRecordJSObjectAllocation(Object* obj) {
- ASSERT(FLAG_log_producers);
- if (!can_log_) return;
- int framesCount = 0;
- for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
- ++framesCount;
- }
- if (framesCount == 0) return;
- ++framesCount; // Reserve place for the terminator item.
- Vector<Address> stack(NewArray<Address>(framesCount), framesCount);
- int i = 0;
- for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
- stack[i++] = it.frame()->pc();
- }
- stack[i] = NULL;
- Handle<Object> handle = isolate_->global_handles()->Create(obj);
- isolate_->global_handles()->MakeWeak(handle.location(),
- static_cast<void*>(stack.start()),
- StackWeakReferenceCallback);
-}
-
-
#endif // ENABLE_LOGGING_AND_PROFILING
« src/api.cc ('K') | « src/heap-profiler.h ('k') | src/isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698