OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 } | 78 } |
79 CHECK(!i::TokenEnumeratorTester::token_removed(&te)->at(2)); | 79 CHECK(!i::TokenEnumeratorTester::token_removed(&te)->at(2)); |
80 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); | 80 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
81 CHECK(i::TokenEnumeratorTester::token_removed(&te)->at(2)); | 81 CHECK(i::TokenEnumeratorTester::token_removed(&te)->at(2)); |
82 CHECK_EQ(1, te.GetTokenId(*v8::Utils::OpenHandle(*token2))); | 82 CHECK_EQ(1, te.GetTokenId(*v8::Utils::OpenHandle(*token2))); |
83 CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1))); | 83 CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1))); |
84 } | 84 } |
85 | 85 |
86 | 86 |
87 TEST(ProfileNodeFindOrAddChild) { | 87 TEST(ProfileNodeFindOrAddChild) { |
88 ProfileTree tree; | 88 ProfileNode node(NULL, NULL); |
89 ProfileNode node(&tree, NULL); | |
90 CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0, | 89 CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0, |
91 TokenEnumerator::kNoSecurityToken); | 90 TokenEnumerator::kNoSecurityToken); |
92 ProfileNode* childNode1 = node.FindOrAddChild(&entry1); | 91 ProfileNode* childNode1 = node.FindOrAddChild(&entry1); |
93 CHECK_NE(NULL, childNode1); | 92 CHECK_NE(NULL, childNode1); |
94 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); | 93 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); |
95 CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0, | 94 CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0, |
96 TokenEnumerator::kNoSecurityToken); | 95 TokenEnumerator::kNoSecurityToken); |
97 ProfileNode* childNode2 = node.FindOrAddChild(&entry2); | 96 ProfileNode* childNode2 = node.FindOrAddChild(&entry2); |
98 CHECK_NE(NULL, childNode2); | 97 CHECK_NE(NULL, childNode2); |
99 CHECK_NE(childNode1, childNode2); | 98 CHECK_NE(childNode1, childNode2); |
100 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); | 99 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); |
101 CHECK_EQ(childNode2, node.FindOrAddChild(&entry2)); | 100 CHECK_EQ(childNode2, node.FindOrAddChild(&entry2)); |
102 CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0, | 101 CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0, |
103 TokenEnumerator::kNoSecurityToken); | 102 TokenEnumerator::kNoSecurityToken); |
104 ProfileNode* childNode3 = node.FindOrAddChild(&entry3); | 103 ProfileNode* childNode3 = node.FindOrAddChild(&entry3); |
105 CHECK_NE(NULL, childNode3); | 104 CHECK_NE(NULL, childNode3); |
106 CHECK_NE(childNode1, childNode3); | 105 CHECK_NE(childNode1, childNode3); |
107 CHECK_NE(childNode2, childNode3); | 106 CHECK_NE(childNode2, childNode3); |
108 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); | 107 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); |
109 CHECK_EQ(childNode2, node.FindOrAddChild(&entry2)); | 108 CHECK_EQ(childNode2, node.FindOrAddChild(&entry2)); |
110 CHECK_EQ(childNode3, node.FindOrAddChild(&entry3)); | 109 CHECK_EQ(childNode3, node.FindOrAddChild(&entry3)); |
111 } | 110 } |
112 | 111 |
113 | 112 |
114 TEST(ProfileNodeFindOrAddChildForSameFunction) { | 113 TEST(ProfileNodeFindOrAddChildForSameFunction) { |
115 const char* empty = ""; | 114 const char* empty = ""; |
116 const char* aaa = "aaa"; | 115 const char* aaa = "aaa"; |
117 ProfileTree tree; | 116 ProfileNode node(NULL, NULL); |
118 ProfileNode node(&tree, NULL); | |
119 CodeEntry entry1(i::Logger::FUNCTION_TAG, empty, aaa, empty, 0, | 117 CodeEntry entry1(i::Logger::FUNCTION_TAG, empty, aaa, empty, 0, |
120 TokenEnumerator::kNoSecurityToken); | 118 TokenEnumerator::kNoSecurityToken); |
121 ProfileNode* childNode1 = node.FindOrAddChild(&entry1); | 119 ProfileNode* childNode1 = node.FindOrAddChild(&entry1); |
122 CHECK_NE(NULL, childNode1); | 120 CHECK_NE(NULL, childNode1); |
123 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); | 121 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); |
124 // The same function again. | 122 // The same function again. |
125 CodeEntry entry2(i::Logger::FUNCTION_TAG, empty, aaa, empty, 0, | 123 CodeEntry entry2(i::Logger::FUNCTION_TAG, empty, aaa, empty, 0, |
126 TokenEnumerator::kNoSecurityToken); | 124 TokenEnumerator::kNoSecurityToken); |
127 CHECK_EQ(childNode1, node.FindOrAddChild(&entry2)); | 125 CHECK_EQ(childNode1, node.FindOrAddChild(&entry2)); |
128 // Now with a different security token. | 126 // Now with a different security token. |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 | 600 |
603 private: | 601 private: |
604 bool old_flag_prof_browser_mode_; | 602 bool old_flag_prof_browser_mode_; |
605 }; | 603 }; |
606 | 604 |
607 } // namespace | 605 } // namespace |
608 | 606 |
609 TEST(RecordTickSample) { | 607 TEST(RecordTickSample) { |
610 TestSetup test_setup; | 608 TestSetup test_setup; |
611 CpuProfilesCollection profiles; | 609 CpuProfilesCollection profiles; |
612 profiles.StartProfiling("", 1, false); | 610 profiles.StartProfiling("", 1); |
613 ProfileGenerator generator(&profiles); | 611 ProfileGenerator generator(&profiles); |
614 CodeEntry* entry1 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa"); | 612 CodeEntry* entry1 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa"); |
615 CodeEntry* entry2 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb"); | 613 CodeEntry* entry2 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb"); |
616 CodeEntry* entry3 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "ccc"); | 614 CodeEntry* entry3 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "ccc"); |
617 generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200); | 615 generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200); |
618 generator.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100); | 616 generator.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100); |
619 generator.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50); | 617 generator.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50); |
620 | 618 |
621 // We are building the following calls tree: | 619 // We are building the following calls tree: |
622 // -> aaa - sample1 | 620 // -> aaa - sample1 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 calc3.UpdateMeasurements(time); | 706 calc3.UpdateMeasurements(time); |
709 // (1.0 + 0.5) / 2 | 707 // (1.0 + 0.5) / 2 |
710 CHECK_EQ(kSamplingIntervalMs * 0.75, calc3.ticks_per_ms()); | 708 CHECK_EQ(kSamplingIntervalMs * 0.75, calc3.ticks_per_ms()); |
711 time += SampleRateCalculator::kWallTimeQueryIntervalMs * 1.5; | 709 time += SampleRateCalculator::kWallTimeQueryIntervalMs * 1.5; |
712 calc3.UpdateMeasurements(time); | 710 calc3.UpdateMeasurements(time); |
713 // (1.0 + 0.5 + 0.5) / 3 | 711 // (1.0 + 0.5 + 0.5) / 3 |
714 CHECK_EQ(kSamplingIntervalMs * 2.0, floor(calc3.ticks_per_ms() * 3.0 + 0.5)); | 712 CHECK_EQ(kSamplingIntervalMs * 2.0, floor(calc3.ticks_per_ms() * 3.0 + 0.5)); |
715 } | 713 } |
716 | 714 |
717 | 715 |
718 static void CheckNodeIds(ProfileNode* node, int* expectedId) { | |
719 CHECK_EQ((*expectedId)++, node->id()); | |
720 for (int i = 0; i < node->children()->length(); i++) { | |
721 CheckNodeIds(node->children()->at(i), expectedId); | |
722 } | |
723 } | |
724 | |
725 TEST(SampleIds) { | |
726 TestSetup test_setup; | |
727 CpuProfilesCollection profiles; | |
728 profiles.StartProfiling("", 1, true); | |
729 ProfileGenerator generator(&profiles); | |
730 CodeEntry* entry1 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa"); | |
731 CodeEntry* entry2 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb"); | |
732 CodeEntry* entry3 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "ccc"); | |
733 generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200); | |
734 generator.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100); | |
735 generator.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50); | |
736 | |
737 // We are building the following calls tree: | |
738 // -> aaa #3 - sample1 | |
739 // (root)#1 -> aaa #2 -> bbb #4 -> ccc #5 - sample2 | |
740 // -> ccc #6 -> aaa #7 - sample3 | |
741 TickSample sample1; | |
742 sample1.pc = ToAddress(0x1600); | |
743 sample1.stack[0] = ToAddress(0x1510); | |
744 sample1.frames_count = 1; | |
745 generator.RecordTickSample(sample1); | |
746 TickSample sample2; | |
747 sample2.pc = ToAddress(0x1925); | |
748 sample2.stack[0] = ToAddress(0x1780); | |
749 sample2.stack[1] = ToAddress(0x10000); // non-existent. | |
750 sample2.stack[2] = ToAddress(0x1620); | |
751 sample2.frames_count = 3; | |
752 generator.RecordTickSample(sample2); | |
753 TickSample sample3; | |
754 sample3.pc = ToAddress(0x1510); | |
755 sample3.stack[0] = ToAddress(0x1910); | |
756 sample3.stack[1] = ToAddress(0x1610); | |
757 sample3.frames_count = 2; | |
758 generator.RecordTickSample(sample3); | |
759 | |
760 CpuProfile* profile = | |
761 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); | |
762 int nodeId = 1; | |
763 CheckNodeIds(profile->top_down()->root(), &nodeId); | |
764 CHECK_EQ(7, nodeId - 1); | |
765 | |
766 CHECK_EQ(3, profile->samples_count()); | |
767 int expected_id[] = {3, 5, 7}; | |
768 for (int i = 0; i < 3; i++) { | |
769 CHECK_EQ(expected_id[i], profile->sample(i)->id()); | |
770 } | |
771 } | |
772 | |
773 | |
774 TEST(NoSamples) { | |
775 TestSetup test_setup; | |
776 CpuProfilesCollection profiles; | |
777 profiles.StartProfiling("", 1, false); | |
778 ProfileGenerator generator(&profiles); | |
779 CodeEntry* entry1 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa"); | |
780 generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200); | |
781 | |
782 // We are building the following calls tree: | |
783 // (root)#1 -> aaa #2 -> aaa #3 - sample1 | |
784 TickSample sample1; | |
785 sample1.pc = ToAddress(0x1600); | |
786 sample1.stack[0] = ToAddress(0x1510); | |
787 sample1.frames_count = 1; | |
788 generator.RecordTickSample(sample1); | |
789 | |
790 CpuProfile* profile = | |
791 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); | |
792 int nodeId = 1; | |
793 CheckNodeIds(profile->top_down()->root(), &nodeId); | |
794 CHECK_EQ(3, nodeId - 1); | |
795 | |
796 CHECK_EQ(0, profile->samples_count()); | |
797 } | |
798 | |
799 | |
800 // --- P r o f i l e r E x t e n s i o n --- | 716 // --- P r o f i l e r E x t e n s i o n --- |
801 | 717 |
802 class ProfilerExtension : public v8::Extension { | 718 class ProfilerExtension : public v8::Extension { |
803 public: | 719 public: |
804 ProfilerExtension() : v8::Extension("v8/profiler", kSource) { } | 720 ProfilerExtension() : v8::Extension("v8/profiler", kSource) { } |
805 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 721 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
806 v8::Handle<v8::String> name); | 722 v8::Handle<v8::String> name); |
807 static v8::Handle<v8::Value> StartProfiling(const v8::Arguments& args); | 723 static v8::Handle<v8::Value> StartProfiling(const v8::Arguments& args); |
808 static v8::Handle<v8::Value> StopProfiling(const v8::Arguments& args); | 724 static v8::Handle<v8::Value> StopProfiling(const v8::Arguments& args); |
809 private: | 725 private: |
(...skipping 13 matching lines...) Expand all Loading... |
823 return v8::FunctionTemplate::New(ProfilerExtension::StopProfiling); | 739 return v8::FunctionTemplate::New(ProfilerExtension::StopProfiling); |
824 } else { | 740 } else { |
825 CHECK(false); | 741 CHECK(false); |
826 return v8::Handle<v8::FunctionTemplate>(); | 742 return v8::Handle<v8::FunctionTemplate>(); |
827 } | 743 } |
828 } | 744 } |
829 | 745 |
830 | 746 |
831 v8::Handle<v8::Value> ProfilerExtension::StartProfiling( | 747 v8::Handle<v8::Value> ProfilerExtension::StartProfiling( |
832 const v8::Arguments& args) { | 748 const v8::Arguments& args) { |
833 v8::CpuProfiler* cpu_profiler = args.GetIsolate()->GetCpuProfiler(); | |
834 if (args.Length() > 0) | 749 if (args.Length() > 0) |
835 cpu_profiler->StartCpuProfiling(args[0].As<v8::String>()); | 750 v8::CpuProfiler::StartProfiling(args[0].As<v8::String>()); |
836 else | 751 else |
837 cpu_profiler->StartCpuProfiling(v8::String::New("")); | 752 v8::CpuProfiler::StartProfiling(v8::String::New("")); |
838 return v8::Undefined(); | 753 return v8::Undefined(); |
839 } | 754 } |
840 | 755 |
841 | 756 |
842 v8::Handle<v8::Value> ProfilerExtension::StopProfiling( | 757 v8::Handle<v8::Value> ProfilerExtension::StopProfiling( |
843 const v8::Arguments& args) { | 758 const v8::Arguments& args) { |
844 v8::CpuProfiler* cpu_profiler = args.GetIsolate()->GetCpuProfiler(); | |
845 if (args.Length() > 0) | 759 if (args.Length() > 0) |
846 cpu_profiler->StopCpuProfiling(args[0].As<v8::String>()); | 760 v8::CpuProfiler::StopProfiling(args[0].As<v8::String>()); |
847 else | 761 else |
848 cpu_profiler->StopCpuProfiling(v8::String::New("")); | 762 v8::CpuProfiler::StopProfiling(v8::String::New("")); |
849 return v8::Undefined(); | 763 return v8::Undefined(); |
850 } | 764 } |
851 | 765 |
852 | 766 |
853 static ProfilerExtension kProfilerExtension; | 767 static ProfilerExtension kProfilerExtension; |
854 v8::DeclareExtension kProfilerExtensionDeclaration(&kProfilerExtension); | 768 v8::DeclareExtension kProfilerExtensionDeclaration(&kProfilerExtension); |
855 static v8::Persistent<v8::Context> env; | 769 static v8::Persistent<v8::Context> env; |
856 | 770 |
857 static const ProfileNode* PickChild(const ProfileNode* parent, | 771 static const ProfileNode* PickChild(const ProfileNode* parent, |
858 const char* name) { | 772 const char* name) { |
(...skipping 12 matching lines...) Expand all Loading... |
871 | 785 |
872 if (env.IsEmpty()) { | 786 if (env.IsEmpty()) { |
873 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 787 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
874 const char* extensions[] = { "v8/profiler" }; | 788 const char* extensions[] = { "v8/profiler" }; |
875 v8::ExtensionConfiguration config(1, extensions); | 789 v8::ExtensionConfiguration config(1, extensions); |
876 env = v8::Context::New(&config); | 790 env = v8::Context::New(&config); |
877 } | 791 } |
878 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 792 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
879 env->Enter(); | 793 env->Enter(); |
880 | 794 |
881 CpuProfiler* profiler = i::Isolate::Current()->cpu_profiler(); | 795 CHECK_EQ(0, CpuProfiler::GetProfilesCount()); |
882 CHECK_EQ(0, profiler->GetProfilesCount()); | |
883 CompileRun( | 796 CompileRun( |
884 "function c() { startProfiling(); }\n" | 797 "function c() { startProfiling(); }\n" |
885 "function b() { c(); }\n" | 798 "function b() { c(); }\n" |
886 "function a() { b(); }\n" | 799 "function a() { b(); }\n" |
887 "a();\n" | 800 "a();\n" |
888 "stopProfiling();"); | 801 "stopProfiling();"); |
889 CHECK_EQ(1, profiler->GetProfilesCount()); | 802 CHECK_EQ(1, CpuProfiler::GetProfilesCount()); |
890 CpuProfile* profile = profiler->GetProfile(NULL, 0); | 803 CpuProfile* profile = |
| 804 CpuProfiler::GetProfile(NULL, 0); |
891 const ProfileTree* topDown = profile->top_down(); | 805 const ProfileTree* topDown = profile->top_down(); |
892 const ProfileNode* current = topDown->root(); | 806 const ProfileNode* current = topDown->root(); |
893 const_cast<ProfileNode*>(current)->Print(0); | 807 const_cast<ProfileNode*>(current)->Print(0); |
894 // The tree should look like this: | 808 // The tree should look like this: |
895 // (root) | 809 // (root) |
896 // (anonymous function) | 810 // (anonymous function) |
897 // a | 811 // a |
898 // b | 812 // b |
899 // c | 813 // c |
900 // There can also be: | 814 // There can also be: |
(...skipping 16 matching lines...) Expand all Loading... |
917 } | 831 } |
918 | 832 |
919 | 833 |
920 TEST(Issue51919) { | 834 TEST(Issue51919) { |
921 CpuProfilesCollection collection; | 835 CpuProfilesCollection collection; |
922 i::EmbeddedVector<char*, | 836 i::EmbeddedVector<char*, |
923 CpuProfilesCollection::kMaxSimultaneousProfiles> titles; | 837 CpuProfilesCollection::kMaxSimultaneousProfiles> titles; |
924 for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) { | 838 for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) { |
925 i::Vector<char> title = i::Vector<char>::New(16); | 839 i::Vector<char> title = i::Vector<char>::New(16); |
926 i::OS::SNPrintF(title, "%d", i); | 840 i::OS::SNPrintF(title, "%d", i); |
927 // UID must be > 0. | 841 CHECK(collection.StartProfiling(title.start(), i + 1)); // UID must be > 0. |
928 CHECK(collection.StartProfiling(title.start(), i + 1, false)); | |
929 titles[i] = title.start(); | 842 titles[i] = title.start(); |
930 } | 843 } |
931 CHECK(!collection.StartProfiling( | 844 CHECK(!collection.StartProfiling( |
932 "maximum", CpuProfilesCollection::kMaxSimultaneousProfiles + 1, false)); | 845 "maximum", CpuProfilesCollection::kMaxSimultaneousProfiles + 1)); |
933 for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) | 846 for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) |
934 i::DeleteArray(titles[i]); | 847 i::DeleteArray(titles[i]); |
935 } | 848 } |
OLD | NEW |