Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. | 
| 2 // | 2 // | 
| 3 // Tests for heap profiler | 3 // Tests for heap profiler | 
| 4 | 4 | 
| 5 #include "v8.h" | 5 #include "v8.h" | 
| 6 | 6 | 
| 7 #include "cctest.h" | 7 #include "cctest.h" | 
| 8 #include "heap-profiler.h" | 8 #include "heap-profiler.h" | 
| 9 #include "snapshot.h" | 9 #include "snapshot.h" | 
| 10 #include "utils-inl.h" | 10 #include "utils-inl.h" | 
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 550 virtual ~TestJSONStream() {} | 550 virtual ~TestJSONStream() {} | 
| 551 virtual void EndOfStream() { ++eos_signaled_; } | 551 virtual void EndOfStream() { ++eos_signaled_; } | 
| 552 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { | 552 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { | 
| 553 if (abort_countdown_ > 0) --abort_countdown_; | 553 if (abort_countdown_ > 0) --abort_countdown_; | 
| 554 if (abort_countdown_ == 0) return kAbort; | 554 if (abort_countdown_ == 0) return kAbort; | 
| 555 CHECK_GT(chars_written, 0); | 555 CHECK_GT(chars_written, 0); | 
| 556 i::Vector<char> chunk = buffer_.AddBlock(chars_written, '\0'); | 556 i::Vector<char> chunk = buffer_.AddBlock(chars_written, '\0'); | 
| 557 memcpy(chunk.start(), buffer, chars_written); | 557 memcpy(chunk.start(), buffer, chars_written); | 
| 558 return kContinue; | 558 return kContinue; | 
| 559 } | 559 } | 
| 560 virtual WriteResult WriteUint32Chunk(uint32_t* buffer, int chars_written) { | |
| 561 ASSERT(false); | |
| 562 return kAbort; | |
| 563 } | |
| 560 void WriteTo(i::Vector<char> dest) { buffer_.WriteTo(dest); } | 564 void WriteTo(i::Vector<char> dest) { buffer_.WriteTo(dest); } | 
| 561 int eos_signaled() { return eos_signaled_; } | 565 int eos_signaled() { return eos_signaled_; } | 
| 562 int size() { return buffer_.size(); } | 566 int size() { return buffer_.size(); } | 
| 567 | |
| 563 private: | 568 private: | 
| 564 i::Collector<char> buffer_; | 569 i::Collector<char> buffer_; | 
| 565 int eos_signaled_; | 570 int eos_signaled_; | 
| 566 int abort_countdown_; | 571 int abort_countdown_; | 
| 567 }; | 572 }; | 
| 568 | 573 | 
| 569 class AsciiResource: public v8::String::ExternalAsciiStringResource { | 574 class AsciiResource: public v8::String::ExternalAsciiStringResource { | 
| 570 public: | 575 public: | 
| 571 explicit AsciiResource(i::Vector<char> string): data_(string.start()) { | 576 explicit AsciiResource(i::Vector<char> string): data_(string.start()) { | 
| 572 length_ = string.length(); | 577 length_ = string.length(); | 
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 684 v8::HandleScope scope; | 689 v8::HandleScope scope; | 
| 685 LocalContext env; | 690 LocalContext env; | 
| 686 const v8::HeapSnapshot* snapshot = | 691 const v8::HeapSnapshot* snapshot = | 
| 687 v8::HeapProfiler::TakeSnapshot(v8_str("abort")); | 692 v8::HeapProfiler::TakeSnapshot(v8_str("abort")); | 
| 688 TestJSONStream stream(5); | 693 TestJSONStream stream(5); | 
| 689 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); | 694 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); | 
| 690 CHECK_GT(stream.size(), 0); | 695 CHECK_GT(stream.size(), 0); | 
| 691 CHECK_EQ(0, stream.eos_signaled()); | 696 CHECK_EQ(0, stream.eos_signaled()); | 
| 692 } | 697 } | 
| 693 | 698 | 
| 699 namespace { | |
| 700 | |
| 701 class TestStatsStream : public v8::OutputStream { | |
| 702 public: | |
| 703 TestStatsStream() | |
| 704 : eos_signaled_(0), | |
| 705 numbers_written_(0), | |
| 706 entries_count_(0), | |
| 707 fragments_count_(0), | |
| 708 first_fragment_index_(-1) { } | |
| 709 TestStatsStream(const TestStatsStream& stream) | |
| 710 : eos_signaled_(stream.eos_signaled_), | |
| 711 numbers_written_(stream.numbers_written_), | |
| 712 entries_count_(stream.entries_count_), | |
| 713 fragments_count_(stream.fragments_count_), | |
| 714 first_fragment_index_(stream.first_fragment_index_) { } | |
| 715 virtual ~TestStatsStream() {} | |
| 716 virtual void EndOfStream() { ++eos_signaled_; } | |
| 717 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { | |
| 718 ASSERT(false); | |
| 719 return kAbort; | |
| 720 } | |
| 721 virtual WriteResult WriteUint32Chunk(uint32_t* buffer, int numbers_written) { | |
| 722 ++fragments_count_; | |
| 723 ASSERT(numbers_written); | |
| 724 numbers_written_ += numbers_written; | |
| 725 entries_count_ = 0; | |
| 726 if (first_fragment_index_ == -1 && numbers_written != 0) | |
| 727 first_fragment_index_ = buffer[0]; | |
| 728 for (int i = 1; i < numbers_written; i += 2) | |
| 729 entries_count_ += buffer[i]; | |
| 730 | |
| 731 return kContinue; | |
| 732 } | |
| 733 int eos_signaled() { return eos_signaled_; } | |
| 734 int numbers_written() { return numbers_written_; } | |
| 735 uint32_t entries_count() const { return entries_count_; } | |
| 736 int fragments_count() const { return fragments_count_; } | |
| 737 int first_fragment_index() const { return first_fragment_index_; } | |
| 738 private: | |
| 739 int eos_signaled_; | |
| 740 int numbers_written_; | |
| 741 uint32_t entries_count_; | |
| 742 int fragments_count_; | |
| 743 int first_fragment_index_; | |
| 744 }; | |
| 745 | |
| 746 } // namespace | |
| 747 | |
| 748 static TestStatsStream GetHeapStatsUpdate() { | |
| 749 TestStatsStream stream; | |
| 750 v8::HeapProfiler::PushHeapObjectsStats(&stream); | |
| 751 CHECK_EQ(1, stream.eos_signaled()); | |
| 752 return stream; | |
| 753 } | |
| 754 | |
| 755 | |
| 756 TEST(HeapSnapshotObjectsStats) { | |
| 757 v8::HandleScope scope; | |
| 758 LocalContext env; | |
| 759 | |
| 760 v8::HeapProfiler::StartHeapObjectsTracking(); | |
| 761 for (int i = 0; i < 5; ++i) { | |
| 762 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); | |
| 763 } | |
| 764 | |
| 765 { | |
| 766 // Single chunk of data expected in update. Initial data. | |
| 767 TestStatsStream stats_update = GetHeapStatsUpdate(); | |
| 768 CHECK_EQ(1, stats_update.fragments_count()); | |
| 769 CHECK_EQ(2, stats_update.numbers_written()); | |
| 770 CHECK_EQ(0, stats_update.first_fragment_index()); | |
| 771 } | |
| 772 | |
| 773 // No data expected in update because nothing has happened. | |
| 774 CHECK_EQ(0, GetHeapStatsUpdate().numbers_written()); | |
| 775 { | |
| 776 v8::HandleScope inner_scope_1; | |
| 777 v8::Local<v8::String> string1 = v8_str("string1"); | |
| 778 { | |
| 779 // Single chunk of data with one new entry expected in update. | |
| 780 TestStatsStream stats_update = GetHeapStatsUpdate(); | |
| 781 CHECK_EQ(1, stats_update.fragments_count()); | |
| 782 CHECK_EQ(2, stats_update.numbers_written()); | |
| 783 CHECK_EQ(1, stats_update.entries_count()); | |
| 784 CHECK_EQ(2, stats_update.first_fragment_index()); | |
| 785 } | |
| 786 | |
| 787 // No data expected in update because nothing happened. | |
| 788 CHECK_EQ(0, GetHeapStatsUpdate().numbers_written()); | |
| 789 | |
| 790 { | |
| 791 v8::HandleScope inner_scope_2; | |
| 792 v8::Local<v8::String> string2 = v8_str("string2"); | |
| 793 | |
| 794 { | |
| 795 v8::HandleScope inner_scope_3; | |
| 796 v8::Handle<v8::String> string3 = v8::String::New("string3"); | |
| 797 v8::Handle<v8::String> string4 = v8::String::New("string4"); | |
| 798 | |
| 799 { | |
| 800 // Single chunk of data with three new entries expected in update. | |
| 801 TestStatsStream stats_update = GetHeapStatsUpdate(); | |
| 802 CHECK_EQ(1, stats_update.fragments_count()); | |
| 803 CHECK_EQ(2, stats_update.numbers_written()); | |
| 804 CHECK_EQ(3, stats_update.entries_count()); | |
| 805 CHECK_EQ(4, stats_update.first_fragment_index()); | |
| 806 } | |
| 807 } | |
| 808 | |
| 809 { | |
| 810 // Single chunk of data with two left entries expected in update. | |
| 811 TestStatsStream stats_update = GetHeapStatsUpdate(); | |
| 812 CHECK_EQ(1, stats_update.fragments_count()); | |
| 813 CHECK_EQ(2, stats_update.numbers_written()); | |
| 814 CHECK_EQ(1, stats_update.entries_count()); | |
| 815 // Two strings from forth fragment were released. | |
| 816 CHECK_EQ(4, stats_update.first_fragment_index()); | |
| 817 } | |
| 818 } | |
| 819 | |
| 820 { | |
| 821 // Single chunk of data with 0 left entries expected in update. | |
| 822 TestStatsStream stats_update = GetHeapStatsUpdate(); | |
| 823 CHECK_EQ(1, stats_update.fragments_count()); | |
| 824 CHECK_EQ(2, stats_update.numbers_written()); | |
| 
 
mnaganov (inactive)
2012/04/12 13:32:26
Why no check for entries_count?
 
 | |
| 825 // The last string from forth fragment was released. | |
| 826 CHECK_EQ(4, stats_update.first_fragment_index()); | |
| 827 } | |
| 828 | |
| 829 } | |
| 830 { | |
| 831 // Single chunk of data with 0 left entries expected in update. | |
| 832 TestStatsStream stats_update = GetHeapStatsUpdate(); | |
| 833 CHECK_EQ(1, stats_update.fragments_count()); | |
| 834 CHECK_EQ(2, stats_update.numbers_written()); | |
| 835 CHECK_EQ(0, stats_update.entries_count()); | |
| 836 // The only string from the second fragment was released. | |
| 837 CHECK_EQ(2, stats_update.first_fragment_index()); | |
| 838 } | |
| 839 | |
| 840 v8::HeapProfiler::StopHeapObjectsTracking(); | |
| 841 } | |
| 842 | |
| 694 | 843 | 
| 695 static void CheckChildrenIds(const v8::HeapSnapshot* snapshot, | 844 static void CheckChildrenIds(const v8::HeapSnapshot* snapshot, | 
| 696 const v8::HeapGraphNode* node, | 845 const v8::HeapGraphNode* node, | 
| 697 int level, int max_level) { | 846 int level, int max_level) { | 
| 698 if (level > max_level) return; | 847 if (level > max_level) return; | 
| 699 CHECK_EQ(node, snapshot->GetNodeById(node->GetId())); | 848 CHECK_EQ(node, snapshot->GetNodeById(node->GetId())); | 
| 700 for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { | 849 for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { | 
| 701 const v8::HeapGraphEdge* prop = node->GetChild(i); | 850 const v8::HeapGraphEdge* prop = node->GetChild(i); | 
| 702 const v8::HeapGraphNode* child = | 851 const v8::HeapGraphNode* child = | 
| 703 snapshot->GetNodeById(prop->GetToNode()->GetId()); | 852 snapshot->GetNodeById(prop->GetToNode()->GetId()); | 
| (...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1365 // Dipose the persistent handles in a different order. | 1514 // Dipose the persistent handles in a different order. | 
| 1366 p_AAA.Dispose(); | 1515 p_AAA.Dispose(); | 
| 1367 CHECK_EQ(global_handle_count + 2, | 1516 CHECK_EQ(global_handle_count + 2, | 
| 1368 v8::HeapProfiler::GetPersistentHandleCount()); | 1517 v8::HeapProfiler::GetPersistentHandleCount()); | 
| 1369 p_CCC.Dispose(); | 1518 p_CCC.Dispose(); | 
| 1370 CHECK_EQ(global_handle_count + 1, | 1519 CHECK_EQ(global_handle_count + 1, | 
| 1371 v8::HeapProfiler::GetPersistentHandleCount()); | 1520 v8::HeapProfiler::GetPersistentHandleCount()); | 
| 1372 p_BBB.Dispose(); | 1521 p_BBB.Dispose(); | 
| 1373 CHECK_EQ(global_handle_count, v8::HeapProfiler::GetPersistentHandleCount()); | 1522 CHECK_EQ(global_handle_count, v8::HeapProfiler::GetPersistentHandleCount()); | 
| 1374 } | 1523 } | 
| OLD | NEW |