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

Side by Side Diff: src/heap-profiler.cc

Issue 3197010: Version 2.3.10... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 4 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/heap-profiler.h ('k') | src/ia32/builtins-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 JSObjectsClusterTree dest_tree_; 273 JSObjectsClusterTree dest_tree_;
274 RetainersAggregator retainers_aggregator(coarser_, &dest_tree_); 274 RetainersAggregator retainers_aggregator(coarser_, &dest_tree_);
275 tree->ForEach(&retainers_aggregator); 275 tree->ForEach(&retainers_aggregator);
276 HeapStringAllocator allocator; 276 HeapStringAllocator allocator;
277 StringStream stream(&allocator); 277 StringStream stream(&allocator);
278 ClusterTreePrinter retainers_printer(&stream); 278 ClusterTreePrinter retainers_printer(&stream);
279 dest_tree_.ForEach(&retainers_printer); 279 dest_tree_.ForEach(&retainers_printer);
280 printer_->PrintRetainers(cluster, stream); 280 printer_->PrintRetainers(cluster, stream);
281 } 281 }
282 282
283 } // namespace
284
283 285
284 // A helper class for building a retainers tree, that aggregates 286 // A helper class for building a retainers tree, that aggregates
285 // all equivalent clusters. 287 // all equivalent clusters.
286 class RetainerTreeAggregator BASE_EMBEDDED { 288 class RetainerTreeAggregator {
287 public: 289 public:
288 explicit RetainerTreeAggregator(ClustersCoarser* coarser) 290 explicit RetainerTreeAggregator(ClustersCoarser* coarser)
289 : coarser_(coarser) {} 291 : coarser_(coarser) {}
290 void Process(JSObjectsRetainerTree* input_tree) { 292 void Process(JSObjectsRetainerTree* input_tree) {
291 input_tree->ForEach(this); 293 input_tree->ForEach(this);
292 } 294 }
293 void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree); 295 void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree);
294 JSObjectsRetainerTree& output_tree() { return output_tree_; } 296 JSObjectsRetainerTree& output_tree() { return output_tree_; }
295 297
296 private: 298 private:
297 ClustersCoarser* coarser_; 299 ClustersCoarser* coarser_;
298 JSObjectsRetainerTree output_tree_; 300 JSObjectsRetainerTree output_tree_;
299 }; 301 };
300 302
301 303
302 void RetainerTreeAggregator::Call(const JSObjectsCluster& cluster, 304 void RetainerTreeAggregator::Call(const JSObjectsCluster& cluster,
303 JSObjectsClusterTree* tree) { 305 JSObjectsClusterTree* tree) {
304 JSObjectsCluster eq = coarser_->GetCoarseEquivalent(cluster); 306 JSObjectsCluster eq = coarser_->GetCoarseEquivalent(cluster);
305 if (eq.is_null()) return; 307 if (eq.is_null()) return;
306 JSObjectsRetainerTree::Locator loc; 308 JSObjectsRetainerTree::Locator loc;
307 if (output_tree_.Insert(eq, &loc)) { 309 if (output_tree_.Insert(eq, &loc)) {
308 loc.set_value(new JSObjectsClusterTree()); 310 loc.set_value(new JSObjectsClusterTree());
309 } 311 }
310 RetainersAggregator retainers_aggregator(coarser_, loc.value()); 312 RetainersAggregator retainers_aggregator(coarser_, loc.value());
311 tree->ForEach(&retainers_aggregator); 313 tree->ForEach(&retainers_aggregator);
312 } 314 }
313 315
314 } // namespace
315
316 316
317 HeapProfiler* HeapProfiler::singleton_ = NULL; 317 HeapProfiler* HeapProfiler::singleton_ = NULL;
318 318
319 HeapProfiler::HeapProfiler() 319 HeapProfiler::HeapProfiler()
320 : snapshots_(new HeapSnapshotsCollection()), 320 : snapshots_(new HeapSnapshotsCollection()),
321 next_snapshot_uid_(1) { 321 next_snapshot_uid_(1) {
322 } 322 }
323 323
324 324
325 HeapProfiler::~HeapProfiler() { 325 HeapProfiler::~HeapProfiler() {
(...skipping 14 matching lines...) Expand all
340 void HeapProfiler::TearDown() { 340 void HeapProfiler::TearDown() {
341 #ifdef ENABLE_LOGGING_AND_PROFILING 341 #ifdef ENABLE_LOGGING_AND_PROFILING
342 delete singleton_; 342 delete singleton_;
343 singleton_ = NULL; 343 singleton_ = NULL;
344 #endif 344 #endif
345 } 345 }
346 346
347 347
348 #ifdef ENABLE_LOGGING_AND_PROFILING 348 #ifdef ENABLE_LOGGING_AND_PROFILING
349 349
350 HeapSnapshot* HeapProfiler::TakeSnapshot(const char* name) { 350 HeapSnapshot* HeapProfiler::TakeSnapshot(const char* name, int type) {
351 ASSERT(singleton_ != NULL); 351 ASSERT(singleton_ != NULL);
352 return singleton_->TakeSnapshotImpl(name); 352 return singleton_->TakeSnapshotImpl(name, type);
353 } 353 }
354 354
355 355
356 HeapSnapshot* HeapProfiler::TakeSnapshot(String* name) { 356 HeapSnapshot* HeapProfiler::TakeSnapshot(String* name, int type) {
357 ASSERT(singleton_ != NULL); 357 ASSERT(singleton_ != NULL);
358 return singleton_->TakeSnapshotImpl(name); 358 return singleton_->TakeSnapshotImpl(name, type);
359 } 359 }
360 360
361 361
362 HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name) { 362 HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name, int type) {
363 Heap::CollectAllGarbage(true); 363 Heap::CollectAllGarbage(true);
364 HeapSnapshot* result = snapshots_->NewSnapshot(name, next_snapshot_uid_++); 364 HeapSnapshot::Type s_type = static_cast<HeapSnapshot::Type>(type);
365 HeapSnapshotGenerator generator(result); 365 HeapSnapshot* result =
366 generator.GenerateSnapshot(); 366 snapshots_->NewSnapshot(s_type, name, next_snapshot_uid_++);
367 switch (s_type) {
368 case HeapSnapshot::kFull: {
369 HeapSnapshotGenerator generator(result);
370 generator.GenerateSnapshot();
371 break;
372 }
373 case HeapSnapshot::kAggregated: {
374 AggregatedHeapSnapshot agg_snapshot;
375 AggregatedHeapSnapshotGenerator generator(&agg_snapshot);
376 generator.GenerateSnapshot();
377 generator.FillHeapSnapshot(result);
378 break;
379 }
380 default:
381 UNREACHABLE();
382 }
367 snapshots_->SnapshotGenerationFinished(); 383 snapshots_->SnapshotGenerationFinished();
368 return result; 384 return result;
369 } 385 }
370 386
371 387
372 HeapSnapshot* HeapProfiler::TakeSnapshotImpl(String* name) { 388 HeapSnapshot* HeapProfiler::TakeSnapshotImpl(String* name, int type) {
373 return TakeSnapshotImpl(snapshots_->GetName(name)); 389 return TakeSnapshotImpl(snapshots_->GetName(name), type);
374 } 390 }
375 391
376 392
377 int HeapProfiler::GetSnapshotsCount() { 393 int HeapProfiler::GetSnapshotsCount() {
378 ASSERT(singleton_ != NULL); 394 ASSERT(singleton_ != NULL);
379 return singleton_->snapshots_->snapshots()->length(); 395 return singleton_->snapshots_->snapshots()->length();
380 } 396 }
381 397
382 398
383 HeapSnapshot* HeapProfiler::GetSnapshot(int index) { 399 HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 void ConstructorHeapProfile::PrintStats() { 442 void ConstructorHeapProfile::PrintStats() {
427 js_objects_info_tree_.ForEach(this); 443 js_objects_info_tree_.ForEach(this);
428 } 444 }
429 445
430 446
431 static const char* GetConstructorName(const char* name) { 447 static const char* GetConstructorName(const char* name) {
432 return name[0] != '\0' ? name : "(anonymous)"; 448 return name[0] != '\0' ? name : "(anonymous)";
433 } 449 }
434 450
435 451
452 const char* JSObjectsCluster::GetSpecialCaseName() const {
453 if (constructor_ == FromSpecialCase(ROOTS)) {
454 return "(roots)";
455 } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) {
456 return "(global property)";
457 } else if (constructor_ == FromSpecialCase(CODE)) {
458 return "(code)";
459 } else if (constructor_ == FromSpecialCase(SELF)) {
460 return "(self)";
461 }
462 return NULL;
463 }
464
465
436 void JSObjectsCluster::Print(StringStream* accumulator) const { 466 void JSObjectsCluster::Print(StringStream* accumulator) const {
437 ASSERT(!is_null()); 467 ASSERT(!is_null());
438 if (constructor_ == FromSpecialCase(ROOTS)) { 468 const char* special_case_name = GetSpecialCaseName();
439 accumulator->Add("(roots)"); 469 if (special_case_name != NULL) {
440 } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) { 470 accumulator->Add(special_case_name);
441 accumulator->Add("(global property)");
442 } else if (constructor_ == FromSpecialCase(CODE)) {
443 accumulator->Add("(code)");
444 } else if (constructor_ == FromSpecialCase(SELF)) {
445 accumulator->Add("(self)");
446 } else { 471 } else {
447 SmartPointer<char> s_name( 472 SmartPointer<char> s_name(
448 constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); 473 constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
449 accumulator->Add("%s", GetConstructorName(*s_name)); 474 accumulator->Add("%s", GetConstructorName(*s_name));
450 if (instance_ != NULL) { 475 if (instance_ != NULL) {
451 accumulator->Add(":%p", static_cast<void*>(instance_)); 476 accumulator->Add(":%p", static_cast<void*>(instance_));
452 } 477 }
453 } 478 }
454 } 479 }
455 480
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 636
612 637
613 const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoKey; 638 const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoKey;
614 const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoValue; 639 const JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoValue;
615 const JSObjectsRetainerTreeConfig::Key JSObjectsRetainerTreeConfig::kNoKey; 640 const JSObjectsRetainerTreeConfig::Key JSObjectsRetainerTreeConfig::kNoKey;
616 const JSObjectsRetainerTreeConfig::Value JSObjectsRetainerTreeConfig::kNoValue = 641 const JSObjectsRetainerTreeConfig::Value JSObjectsRetainerTreeConfig::kNoValue =
617 NULL; 642 NULL;
618 643
619 644
620 RetainerHeapProfile::RetainerHeapProfile() 645 RetainerHeapProfile::RetainerHeapProfile()
621 : zscope_(DELETE_ON_EXIT) { 646 : zscope_(DELETE_ON_EXIT),
647 aggregator_(NULL) {
622 JSObjectsCluster roots(JSObjectsCluster::ROOTS); 648 JSObjectsCluster roots(JSObjectsCluster::ROOTS);
623 ReferencesExtractor extractor(roots, this); 649 ReferencesExtractor extractor(roots, this);
624 Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); 650 Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG);
625 } 651 }
626 652
627 653
654 RetainerHeapProfile::~RetainerHeapProfile() {
655 delete aggregator_;
656 }
657
658
628 void RetainerHeapProfile::StoreReference(const JSObjectsCluster& cluster, 659 void RetainerHeapProfile::StoreReference(const JSObjectsCluster& cluster,
629 HeapObject* ref) { 660 HeapObject* ref) {
630 JSObjectsCluster ref_cluster = Clusterizer::Clusterize(ref); 661 JSObjectsCluster ref_cluster = Clusterizer::Clusterize(ref);
631 if (ref_cluster.is_null()) return; 662 if (ref_cluster.is_null()) return;
632 JSObjectsRetainerTree::Locator ref_loc; 663 JSObjectsRetainerTree::Locator ref_loc;
633 if (retainers_tree_.Insert(ref_cluster, &ref_loc)) { 664 if (retainers_tree_.Insert(ref_cluster, &ref_loc)) {
634 ref_loc.set_value(new JSObjectsClusterTree()); 665 ref_loc.set_value(new JSObjectsClusterTree());
635 } 666 }
636 JSObjectsClusterTree* referenced_by = ref_loc.value(); 667 JSObjectsClusterTree* referenced_by = ref_loc.value();
637 Clusterizer::InsertReferenceIntoTree(referenced_by, cluster); 668 Clusterizer::InsertReferenceIntoTree(referenced_by, cluster);
638 } 669 }
639 670
640 671
641 void RetainerHeapProfile::CollectStats(HeapObject* obj) { 672 void RetainerHeapProfile::CollectStats(HeapObject* obj) {
642 const JSObjectsCluster cluster = Clusterizer::Clusterize(obj); 673 const JSObjectsCluster cluster = Clusterizer::Clusterize(obj);
643 if (cluster.is_null()) return; 674 if (cluster.is_null()) return;
644 ReferencesExtractor extractor(cluster, this); 675 ReferencesExtractor extractor(cluster, this);
645 obj->Iterate(&extractor); 676 obj->Iterate(&extractor);
646 } 677 }
647 678
648 679
680 void RetainerHeapProfile::CoarseAndAggregate() {
681 coarser_.Process(&retainers_tree_);
682 ASSERT(aggregator_ == NULL);
683 aggregator_ = new RetainerTreeAggregator(&coarser_);
684 aggregator_->Process(&retainers_tree_);
685 }
686
687
649 void RetainerHeapProfile::DebugPrintStats( 688 void RetainerHeapProfile::DebugPrintStats(
650 RetainerHeapProfile::Printer* printer) { 689 RetainerHeapProfile::Printer* printer) {
651 coarser_.Process(&retainers_tree_);
652 // Print clusters that have no equivalents, aggregating their retainers. 690 // Print clusters that have no equivalents, aggregating their retainers.
653 AggregatingRetainerTreePrinter agg_printer(&coarser_, printer); 691 AggregatingRetainerTreePrinter agg_printer(&coarser_, printer);
654 retainers_tree_.ForEach(&agg_printer); 692 retainers_tree_.ForEach(&agg_printer);
655 // Now aggregate clusters that have equivalents... 693 // Print clusters that have equivalents.
656 RetainerTreeAggregator aggregator(&coarser_);
657 aggregator.Process(&retainers_tree_);
658 // ...and print them.
659 SimpleRetainerTreePrinter s_printer(printer); 694 SimpleRetainerTreePrinter s_printer(printer);
660 aggregator.output_tree().ForEach(&s_printer); 695 aggregator_->output_tree().ForEach(&s_printer);
661 } 696 }
662 697
663 698
664 void RetainerHeapProfile::PrintStats() { 699 void RetainerHeapProfile::PrintStats() {
665 RetainersPrinter printer; 700 RetainersPrinter printer;
666 DebugPrintStats(&printer); 701 DebugPrintStats(&printer);
667 } 702 }
668 703
669 704
670 // 705 //
671 // HeapProfiler class implementation. 706 // HeapProfiler class implementation.
672 // 707 //
673 void HeapProfiler::CollectStats(HeapObject* obj, HistogramInfo* info) {
674 InstanceType type = obj->map()->instance_type();
675 ASSERT(0 <= type && type <= LAST_TYPE);
676 if (!FreeListNode::IsFreeListNode(obj)) {
677 info[type].increment_number(1);
678 info[type].increment_bytes(obj->Size());
679 }
680 }
681
682
683 static void StackWeakReferenceCallback(Persistent<Value> object, 708 static void StackWeakReferenceCallback(Persistent<Value> object,
684 void* trace) { 709 void* trace) {
685 DeleteArray(static_cast<Address*>(trace)); 710 DeleteArray(static_cast<Address*>(trace));
686 object.Dispose(); 711 object.Dispose();
687 } 712 }
688 713
689 714
690 static void PrintProducerStackTrace(Object* obj, void* trace) { 715 static void PrintProducerStackTrace(Object* obj, void* trace) {
691 if (!obj->IsJSObject()) return; 716 if (!obj->IsJSObject()) return;
692 String* constructor = JSObject::cast(obj)->constructor_name(); 717 String* constructor = JSObject::cast(obj)->constructor_name();
693 SmartPointer<char> s_name( 718 SmartPointer<char> s_name(
694 constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); 719 constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
695 LOG(HeapSampleJSProducerEvent(GetConstructorName(*s_name), 720 LOG(HeapSampleJSProducerEvent(GetConstructorName(*s_name),
696 reinterpret_cast<Address*>(trace))); 721 reinterpret_cast<Address*>(trace)));
697 } 722 }
698 723
699 724
700 void HeapProfiler::WriteSample() { 725 void HeapProfiler::WriteSample() {
701 LOG(HeapSampleBeginEvent("Heap", "allocated")); 726 LOG(HeapSampleBeginEvent("Heap", "allocated"));
702 LOG(HeapSampleStats( 727 LOG(HeapSampleStats(
703 "Heap", "allocated", Heap::CommittedMemory(), Heap::SizeOfObjects())); 728 "Heap", "allocated", Heap::CommittedMemory(), Heap::SizeOfObjects()));
704 729
705 HistogramInfo info[LAST_TYPE+1]; 730 AggregatedHeapSnapshot snapshot;
706 #define DEF_TYPE_NAME(name) info[name].set_name(#name); 731 AggregatedHeapSnapshotGenerator generator(&snapshot);
707 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) 732 generator.GenerateSnapshot();
708 #undef DEF_TYPE_NAME 733
709 734 HistogramInfo* info = snapshot.info();
710 ConstructorHeapProfile js_cons_profile; 735 for (int i = FIRST_NONSTRING_TYPE;
711 RetainerHeapProfile js_retainer_profile; 736 i <= AggregatedHeapSnapshotGenerator::kAllStringsType;
712 HeapIterator iterator; 737 ++i) {
713 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
714 CollectStats(obj, info);
715 js_cons_profile.CollectStats(obj);
716 js_retainer_profile.CollectStats(obj);
717 }
718
719 // Lump all the string types together.
720 int string_number = 0;
721 int string_bytes = 0;
722 #define INCREMENT_SIZE(type, size, name, camel_name) \
723 string_number += info[type].number(); \
724 string_bytes += info[type].bytes();
725 STRING_TYPE_LIST(INCREMENT_SIZE)
726 #undef INCREMENT_SIZE
727 if (string_bytes > 0) {
728 LOG(HeapSampleItemEvent("STRING_TYPE", string_number, string_bytes));
729 }
730
731 for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) {
732 if (info[i].bytes() > 0) { 738 if (info[i].bytes() > 0) {
733 LOG(HeapSampleItemEvent(info[i].name(), info[i].number(), 739 LOG(HeapSampleItemEvent(info[i].name(), info[i].number(),
734 info[i].bytes())); 740 info[i].bytes()));
735 } 741 }
736 } 742 }
737 743
738 js_cons_profile.PrintStats(); 744 snapshot.js_cons_profile()->PrintStats();
739 js_retainer_profile.PrintStats(); 745 snapshot.js_retainer_profile()->PrintStats();
740 746
741 GlobalHandles::IterateWeakRoots(PrintProducerStackTrace, 747 GlobalHandles::IterateWeakRoots(PrintProducerStackTrace,
742 StackWeakReferenceCallback); 748 StackWeakReferenceCallback);
743 749
744 LOG(HeapSampleEndEvent("Heap", "allocated")); 750 LOG(HeapSampleEndEvent("Heap", "allocated"));
745 } 751 }
746 752
747 753
754 AggregatedHeapSnapshot::AggregatedHeapSnapshot()
755 : info_(NewArray<HistogramInfo>(
756 AggregatedHeapSnapshotGenerator::kAllStringsType + 1)) {
757 #define DEF_TYPE_NAME(name) info_[name].set_name(#name);
758 INSTANCE_TYPE_LIST(DEF_TYPE_NAME);
759 #undef DEF_TYPE_NAME
760 info_[AggregatedHeapSnapshotGenerator::kAllStringsType].set_name(
761 "STRING_TYPE");
762 }
763
764
765 AggregatedHeapSnapshot::~AggregatedHeapSnapshot() {
766 DeleteArray(info_);
767 }
768
769
770 AggregatedHeapSnapshotGenerator::AggregatedHeapSnapshotGenerator(
771 AggregatedHeapSnapshot* agg_snapshot)
772 : agg_snapshot_(agg_snapshot) {
773 }
774
775
776 void AggregatedHeapSnapshotGenerator::CalculateStringsStats() {
777 HistogramInfo* info = agg_snapshot_->info();
778 HistogramInfo& strings = info[kAllStringsType];
779 // Lump all the string types together.
780 #define INCREMENT_SIZE(type, size, name, camel_name) \
781 strings.increment_number(info[type].number()); \
782 strings.increment_bytes(info[type].bytes());
783 STRING_TYPE_LIST(INCREMENT_SIZE);
784 #undef INCREMENT_SIZE
785 }
786
787
788 void AggregatedHeapSnapshotGenerator::CollectStats(HeapObject* obj) {
789 InstanceType type = obj->map()->instance_type();
790 ASSERT(0 <= type && type <= LAST_TYPE);
791 if (!FreeListNode::IsFreeListNode(obj)) {
792 agg_snapshot_->info()[type].increment_number(1);
793 agg_snapshot_->info()[type].increment_bytes(obj->Size());
794 }
795 }
796
797
798 void AggregatedHeapSnapshotGenerator::GenerateSnapshot() {
799 HeapIterator iterator;
800 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
801 CollectStats(obj);
802 agg_snapshot_->js_cons_profile()->CollectStats(obj);
803 agg_snapshot_->js_retainer_profile()->CollectStats(obj);
804 }
805 CalculateStringsStats();
806 agg_snapshot_->js_retainer_profile()->CoarseAndAggregate();
807 }
808
809
810 class CountingConstructorHeapProfileIterator {
811 public:
812 CountingConstructorHeapProfileIterator()
813 : entities_count_(0), children_count_(0) {
814 }
815
816 void Call(const JSObjectsCluster& cluster,
817 const NumberAndSizeInfo& number_and_size) {
818 ++entities_count_;
819 children_count_ += number_and_size.number();
820 }
821
822 int entities_count() { return entities_count_; }
823 int children_count() { return children_count_; }
824
825 private:
826 int entities_count_;
827 int children_count_;
828 };
829
830
831 static HeapEntry* AddEntryFromAggregatedSnapshot(HeapSnapshot* snapshot,
832 int* root_child_index,
833 HeapEntry::Type type,
834 const char* name,
835 int count,
836 int size,
837 int children_count,
838 int retainers_count) {
839 HeapEntry* entry = snapshot->AddEntry(
840 type, name, count, size, children_count, retainers_count);
841 ASSERT(entry != NULL);
842 snapshot->root()->SetUnidirElementReference(*root_child_index,
843 *root_child_index + 1,
844 entry);
845 *root_child_index = *root_child_index + 1;
846 return entry;
847 }
848
849
850 class AllocatingConstructorHeapProfileIterator {
851 public:
852 AllocatingConstructorHeapProfileIterator(HeapSnapshot* snapshot,
853 int* root_child_index)
854 : snapshot_(snapshot),
855 root_child_index_(root_child_index) {
856 }
857
858 void Call(const JSObjectsCluster& cluster,
859 const NumberAndSizeInfo& number_and_size) {
860 const char* name = cluster.GetSpecialCaseName();
861 if (name == NULL) {
862 name = snapshot_->collection()->GetFunctionName(cluster.constructor());
863 }
864 AddEntryFromAggregatedSnapshot(snapshot_,
865 root_child_index_,
866 HeapEntry::kObject,
867 name,
868 number_and_size.number(),
869 number_and_size.bytes(),
870 0,
871 0);
872 }
873
874 private:
875 HeapSnapshot* snapshot_;
876 int* root_child_index_;
877 };
878
879
880 static HeapObject* ClusterAsHeapObject(const JSObjectsCluster& cluster) {
881 return cluster.can_be_coarsed() ?
882 reinterpret_cast<HeapObject*>(cluster.instance()) : cluster.constructor();
883 }
884
885
886 static JSObjectsCluster HeapObjectAsCluster(HeapObject* object) {
887 if (object->IsString()) {
888 return JSObjectsCluster(String::cast(object));
889 } else {
890 JSObject* js_obj = JSObject::cast(object);
891 String* constructor = JSObject::cast(js_obj)->constructor_name();
892 return JSObjectsCluster(constructor, object);
893 }
894 }
895
896
897 class CountingRetainersIterator {
898 public:
899 CountingRetainersIterator(const JSObjectsCluster& child_cluster,
900 HeapEntriesMap* map)
901 : child_(ClusterAsHeapObject(child_cluster)), map_(map) {
902 if (map_->Map(child_) == NULL)
903 map_->Pair(child_, HeapEntriesMap::kHeapEntryPlaceholder);
904 }
905
906 void Call(const JSObjectsCluster& cluster,
907 const NumberAndSizeInfo& number_and_size) {
908 if (map_->Map(ClusterAsHeapObject(cluster)) == NULL)
909 map_->Pair(ClusterAsHeapObject(cluster),
910 HeapEntriesMap::kHeapEntryPlaceholder);
911 map_->CountReference(ClusterAsHeapObject(cluster), child_);
912 }
913
914 private:
915 HeapObject* child_;
916 HeapEntriesMap* map_;
917 };
918
919
920 class AllocatingRetainersIterator {
921 public:
922 AllocatingRetainersIterator(const JSObjectsCluster& child_cluster,
923 HeapEntriesMap* map)
924 : child_(ClusterAsHeapObject(child_cluster)), map_(map) {
925 child_entry_ = map_->Map(child_);
926 ASSERT(child_entry_ != NULL);
927 }
928
929 void Call(const JSObjectsCluster& cluster,
930 const NumberAndSizeInfo& number_and_size) {
931 int child_index, retainer_index;
932 map_->CountReference(ClusterAsHeapObject(cluster), child_,
933 &child_index, &retainer_index);
934 map_->Map(ClusterAsHeapObject(cluster))->SetElementReference(
935 child_index, number_and_size.number(), child_entry_, retainer_index);
936 }
937
938 private:
939 HeapObject* child_;
940 HeapEntriesMap* map_;
941 HeapEntry* child_entry_;
942 };
943
944
945 template<class RetainersIterator>
946 class AggregatingRetainerTreeIterator {
947 public:
948 explicit AggregatingRetainerTreeIterator(ClustersCoarser* coarser,
949 HeapEntriesMap* map)
950 : coarser_(coarser), map_(map) {
951 }
952
953 void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree) {
954 if (coarser_ != NULL &&
955 !coarser_->GetCoarseEquivalent(cluster).is_null()) return;
956 JSObjectsClusterTree* tree_to_iterate = tree;
957 ZoneScope zs(DELETE_ON_EXIT);
958 JSObjectsClusterTree dest_tree_;
959 if (coarser_ != NULL) {
960 RetainersAggregator retainers_aggregator(coarser_, &dest_tree_);
961 tree->ForEach(&retainers_aggregator);
962 tree_to_iterate = &dest_tree_;
963 }
964 RetainersIterator iterator(cluster, map_);
965 tree_to_iterate->ForEach(&iterator);
966 }
967
968 private:
969 ClustersCoarser* coarser_;
970 HeapEntriesMap* map_;
971 };
972
973
974 class AggregatedRetainerTreeAllocator {
975 public:
976 AggregatedRetainerTreeAllocator(HeapSnapshot* snapshot,
977 int* root_child_index)
978 : snapshot_(snapshot), root_child_index_(root_child_index) {
979 }
980
981 HeapEntry* GetEntry(
982 HeapObject* obj, int children_count, int retainers_count) {
983 JSObjectsCluster cluster = HeapObjectAsCluster(obj);
984 const char* name = cluster.GetSpecialCaseName();
985 if (name == NULL) {
986 name = snapshot_->collection()->GetFunctionName(cluster.constructor());
987 }
988 return AddEntryFromAggregatedSnapshot(
989 snapshot_, root_child_index_, HeapEntry::kObject, name,
990 0, 0, children_count, retainers_count);
991 }
992
993 private:
994 HeapSnapshot* snapshot_;
995 int* root_child_index_;
996 };
997
998
999 template<class Iterator>
1000 void AggregatedHeapSnapshotGenerator::IterateRetainers(
1001 HeapEntriesMap* entries_map) {
1002 RetainerHeapProfile* p = agg_snapshot_->js_retainer_profile();
1003 AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_1(
1004 p->coarser(), entries_map);
1005 p->retainers_tree()->ForEach(&agg_ret_iter_1);
1006 AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_2(NULL, entries_map);
1007 p->aggregator()->output_tree().ForEach(&agg_ret_iter_2);
1008 }
1009
1010
1011 void AggregatedHeapSnapshotGenerator::FillHeapSnapshot(HeapSnapshot* snapshot) {
1012 // Count the number of entities.
1013 int histogram_entities_count = 0;
1014 int histogram_children_count = 0;
1015 int histogram_retainers_count = 0;
1016 for (int i = FIRST_NONSTRING_TYPE; i <= kAllStringsType; ++i) {
1017 if (agg_snapshot_->info()[i].bytes() > 0) {
1018 ++histogram_entities_count;
1019 }
1020 }
1021 CountingConstructorHeapProfileIterator counting_cons_iter;
1022 agg_snapshot_->js_cons_profile()->ForEach(&counting_cons_iter);
1023 histogram_entities_count += counting_cons_iter.entities_count();
1024 HeapEntriesMap entries_map;
1025 IterateRetainers<CountingRetainersIterator>(&entries_map);
1026 histogram_entities_count += entries_map.entries_count();
1027 histogram_children_count += entries_map.total_children_count();
1028 histogram_retainers_count += entries_map.total_retainers_count();
1029
1030 // Root entry references all other entries.
1031 histogram_children_count += histogram_entities_count;
1032 int root_children_count = histogram_entities_count;
1033 ++histogram_entities_count;
1034
1035 // Allocate and fill entries in the snapshot, allocate references.
1036 snapshot->AllocateEntries(histogram_entities_count,
1037 histogram_children_count,
1038 histogram_retainers_count);
1039 snapshot->AddEntry(HeapSnapshot::kInternalRootObject,
1040 root_children_count,
1041 0);
1042 int root_child_index = 0;
1043 for (int i = FIRST_NONSTRING_TYPE; i <= kAllStringsType; ++i) {
1044 if (agg_snapshot_->info()[i].bytes() > 0) {
1045 AddEntryFromAggregatedSnapshot(snapshot,
1046 &root_child_index,
1047 HeapEntry::kInternal,
1048 agg_snapshot_->info()[i].name(),
1049 agg_snapshot_->info()[i].number(),
1050 agg_snapshot_->info()[i].bytes(),
1051 0,
1052 0);
1053 }
1054 }
1055 AllocatingConstructorHeapProfileIterator alloc_cons_iter(
1056 snapshot, &root_child_index);
1057 agg_snapshot_->js_cons_profile()->ForEach(&alloc_cons_iter);
1058 AggregatedRetainerTreeAllocator allocator(snapshot, &root_child_index);
1059 entries_map.UpdateEntries(&allocator);
1060
1061 // Fill up references.
1062 IterateRetainers<AllocatingRetainersIterator>(&entries_map);
1063 }
1064
1065
748 bool ProducerHeapProfile::can_log_ = false; 1066 bool ProducerHeapProfile::can_log_ = false;
749 1067
750 void ProducerHeapProfile::Setup() { 1068 void ProducerHeapProfile::Setup() {
751 can_log_ = true; 1069 can_log_ = true;
752 } 1070 }
753 1071
754 void ProducerHeapProfile::DoRecordJSObjectAllocation(Object* obj) { 1072 void ProducerHeapProfile::DoRecordJSObjectAllocation(Object* obj) {
755 ASSERT(FLAG_log_producers); 1073 ASSERT(FLAG_log_producers);
756 if (!can_log_) return; 1074 if (!can_log_) return;
757 int framesCount = 0; 1075 int framesCount = 0;
(...skipping 12 matching lines...) Expand all
770 GlobalHandles::MakeWeak(handle.location(), 1088 GlobalHandles::MakeWeak(handle.location(),
771 static_cast<void*>(stack.start()), 1089 static_cast<void*>(stack.start()),
772 StackWeakReferenceCallback); 1090 StackWeakReferenceCallback);
773 } 1091 }
774 1092
775 1093
776 #endif // ENABLE_LOGGING_AND_PROFILING 1094 #endif // ENABLE_LOGGING_AND_PROFILING
777 1095
778 1096
779 } } // namespace v8::internal 1097 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap-profiler.h ('k') | src/ia32/builtins-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698