whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 1 | // Copyright 2010 the V8 project authors. All rights reserved. |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions are |
| 4 | // met: |
| 5 | // |
| 6 | // * Redistributions of source code must retain the above copyright |
| 7 | // notice, this list of conditions and the following disclaimer. |
| 8 | // * Redistributions in binary form must reproduce the above |
| 9 | // copyright notice, this list of conditions and the following |
| 10 | // disclaimer in the documentation and/or other materials provided |
| 11 | // with the distribution. |
| 12 | // * Neither the name of Google Inc. nor the names of its |
| 13 | // contributors may be used to endorse or promote products derived |
| 14 | // from this software without specific prior written permission. |
| 15 | // |
| 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 27 | // |
| 28 | // Tests of profiles generator and utilities. |
| 29 | |
| 30 | #include "v8.h" |
| 31 | #include "cpu-profiler-inl.h" |
| 32 | #include "cctest.h" |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame^] | 33 | #include "utils.h" |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 34 | #include "../include/v8-profiler.h" |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 35 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 36 | using i::CodeEntry; |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 37 | using i::CpuProfile; |
vegorov@chromium.org | 26c16f8 | 2010-08-11 13:41:03 +0000 | [diff] [blame] | 38 | using i::CpuProfiler; |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 39 | using i::CpuProfilesCollection; |
| 40 | using i::ProfileGenerator; |
| 41 | using i::ProfileNode; |
| 42 | using i::ProfilerEventsProcessor; |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame^] | 43 | using i::ScopedVector; |
vegorov@chromium.org | 2356e6f | 2010-06-09 09:38:56 +0000 | [diff] [blame] | 44 | using i::TokenEnumerator; |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame^] | 45 | using i::Vector; |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 46 | |
| 47 | |
| 48 | TEST(StartStop) { |
| 49 | CpuProfilesCollection profiles; |
| 50 | ProfileGenerator generator(&profiles); |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 51 | ProfilerEventsProcessor processor(&generator); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 52 | processor.Start(); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 53 | processor.Stop(); |
| 54 | processor.Join(); |
| 55 | } |
| 56 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 57 | static inline i::Address ToAddress(int n) { |
| 58 | return reinterpret_cast<i::Address>(n); |
| 59 | } |
| 60 | |
mmassi@chromium.org | 49a4467 | 2012-12-04 13:52:03 +0000 | [diff] [blame] | 61 | static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc, |
| 62 | i::Address frame1, |
| 63 | i::Address frame2 = NULL, |
| 64 | i::Address frame3 = NULL) { |
| 65 | i::TickSample* sample = proc->TickSampleEvent(); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 66 | sample->pc = frame1; |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 67 | sample->frames_count = 0; |
| 68 | if (frame2 != NULL) { |
| 69 | sample->stack[0] = frame2; |
| 70 | sample->frames_count = 1; |
| 71 | } |
| 72 | if (frame3 != NULL) { |
| 73 | sample->stack[1] = frame3; |
| 74 | sample->frames_count = 2; |
| 75 | } |
| 76 | } |
| 77 | |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 78 | namespace { |
| 79 | |
| 80 | class TestSetup { |
| 81 | public: |
| 82 | TestSetup() |
| 83 | : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) { |
| 84 | i::FLAG_prof_browser_mode = false; |
| 85 | } |
| 86 | |
| 87 | ~TestSetup() { |
| 88 | i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_; |
| 89 | } |
| 90 | |
| 91 | private: |
| 92 | bool old_flag_prof_browser_mode_; |
| 93 | }; |
| 94 | |
| 95 | } // namespace |
| 96 | |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 97 | TEST(CodeEvents) { |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame^] | 98 | CcTest::InitializeVM(); |
yangguo@chromium.org | c03a192 | 2013-02-19 13:55:47 +0000 | [diff] [blame] | 99 | i::Isolate* isolate = i::Isolate::Current(); |
| 100 | i::Heap* heap = isolate->heap(); |
| 101 | i::Factory* factory = isolate->factory(); |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 102 | TestSetup test_setup; |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 103 | CpuProfilesCollection profiles; |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 104 | profiles.StartProfiling("", 1, false); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 105 | ProfileGenerator generator(&profiles); |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 106 | ProfilerEventsProcessor processor(&generator); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 107 | processor.Start(); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 108 | |
| 109 | // Enqueue code creation events. |
yangguo@chromium.org | c03a192 | 2013-02-19 13:55:47 +0000 | [diff] [blame] | 110 | i::HandleScope scope(isolate); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 111 | const char* aaa_str = "aaa"; |
yangguo@chromium.org | c03a192 | 2013-02-19 13:55:47 +0000 | [diff] [blame] | 112 | i::Handle<i::String> aaa_name = factory->NewStringFromAscii( |
whesse@chromium.org | b6e43bb | 2010-04-14 09:36:28 +0000 | [diff] [blame] | 113 | i::Vector<const char>(aaa_str, i::StrLength(aaa_str))); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 114 | processor.CodeCreateEvent(i::Logger::FUNCTION_TAG, |
| 115 | *aaa_name, |
yangguo@chromium.org | c03a192 | 2013-02-19 13:55:47 +0000 | [diff] [blame] | 116 | heap->empty_string(), |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 117 | 0, |
| 118 | ToAddress(0x1000), |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 119 | 0x100, |
| 120 | ToAddress(0x10000)); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 121 | processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 122 | "bbb", |
| 123 | ToAddress(0x1200), |
| 124 | 0x80); |
| 125 | processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10); |
| 126 | processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 127 | "ddd", |
| 128 | ToAddress(0x1400), |
| 129 | 0x80); |
| 130 | processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500)); |
| 131 | processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10); |
lrn@chromium.org | 34e6078 | 2011-09-15 07:25:40 +0000 | [diff] [blame] | 132 | processor.CodeCreateEvent(i::Logger::STUB_TAG, 4, ToAddress(0x1605), 0x10); |
mmassi@chromium.org | 49a4467 | 2012-12-04 13:52:03 +0000 | [diff] [blame] | 133 | // Enqueue a tick event to enable code events processing. |
| 134 | EnqueueTickSampleEvent(&processor, ToAddress(0x1000)); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 135 | |
| 136 | processor.Stop(); |
| 137 | processor.Join(); |
| 138 | |
| 139 | // Check the state of profile generator. |
| 140 | CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000)); |
| 141 | CHECK_NE(NULL, entry1); |
| 142 | CHECK_EQ(aaa_str, entry1->name()); |
| 143 | CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200)); |
| 144 | CHECK_NE(NULL, entry2); |
| 145 | CHECK_EQ("bbb", entry2->name()); |
| 146 | CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300)); |
| 147 | CHECK_NE(NULL, entry3); |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 148 | CHECK_EQ("5", entry3->name()); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 149 | CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400))); |
| 150 | CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500)); |
| 151 | CHECK_NE(NULL, entry4); |
| 152 | CHECK_EQ("ddd", entry4->name()); |
| 153 | CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600))); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 154 | } |
| 155 | |
| 156 | |
| 157 | template<typename T> |
| 158 | static int CompareProfileNodes(const T* p1, const T* p2) { |
| 159 | return strcmp((*p1)->entry()->name(), (*p2)->entry()->name()); |
| 160 | } |
| 161 | |
| 162 | TEST(TickEvents) { |
ager@chromium.org | 357bf65 | 2010-04-12 11:30:10 +0000 | [diff] [blame] | 163 | TestSetup test_setup; |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 164 | CpuProfilesCollection profiles; |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 165 | profiles.StartProfiling("", 1, false); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 166 | ProfileGenerator generator(&profiles); |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 167 | ProfilerEventsProcessor processor(&generator); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 168 | processor.Start(); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 169 | |
| 170 | processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 171 | "bbb", |
| 172 | ToAddress(0x1200), |
| 173 | 0x80); |
| 174 | processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10); |
| 175 | processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 176 | "ddd", |
| 177 | ToAddress(0x1400), |
| 178 | 0x80); |
mmassi@chromium.org | 49a4467 | 2012-12-04 13:52:03 +0000 | [diff] [blame] | 179 | EnqueueTickSampleEvent(&processor, ToAddress(0x1210)); |
| 180 | EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220)); |
| 181 | EnqueueTickSampleEvent(&processor, |
| 182 | ToAddress(0x1404), |
| 183 | ToAddress(0x1305), |
| 184 | ToAddress(0x1230)); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 185 | |
| 186 | processor.Stop(); |
| 187 | processor.Join(); |
erik.corry@gmail.com | 9dfbea4 | 2010-05-21 12:58:28 +0000 | [diff] [blame] | 188 | CpuProfile* profile = |
vegorov@chromium.org | 2356e6f | 2010-06-09 09:38:56 +0000 | [diff] [blame] | 189 | profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 190 | CHECK_NE(NULL, profile); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 191 | |
| 192 | // Check call trees. |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 193 | const i::List<ProfileNode*>* top_down_root_children = |
| 194 | profile->top_down()->root()->children(); |
| 195 | CHECK_EQ(1, top_down_root_children->length()); |
| 196 | CHECK_EQ("bbb", top_down_root_children->last()->entry()->name()); |
| 197 | const i::List<ProfileNode*>* top_down_bbb_children = |
| 198 | top_down_root_children->last()->children(); |
| 199 | CHECK_EQ(1, top_down_bbb_children->length()); |
| 200 | CHECK_EQ("5", top_down_bbb_children->last()->entry()->name()); |
| 201 | const i::List<ProfileNode*>* top_down_stub_children = |
| 202 | top_down_bbb_children->last()->children(); |
| 203 | CHECK_EQ(1, top_down_stub_children->length()); |
| 204 | CHECK_EQ("ddd", top_down_stub_children->last()->entry()->name()); |
| 205 | const i::List<ProfileNode*>* top_down_ddd_children = |
| 206 | top_down_stub_children->last()->children(); |
| 207 | CHECK_EQ(0, top_down_ddd_children->length()); |
whesse@chromium.org | cec079d | 2010-03-22 14:44:04 +0000 | [diff] [blame] | 208 | } |
lrn@chromium.org | 25156de | 2010-04-06 13:10:27 +0000 | [diff] [blame] | 209 | |
vegorov@chromium.org | 26c16f8 | 2010-08-11 13:41:03 +0000 | [diff] [blame] | 210 | |
| 211 | // http://crbug/51594 |
| 212 | // This test must not crash. |
| 213 | TEST(CrashIfStoppingLastNonExistentProfile) { |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame^] | 214 | CcTest::InitializeVM(); |
vegorov@chromium.org | 26c16f8 | 2010-08-11 13:41:03 +0000 | [diff] [blame] | 215 | TestSetup test_setup; |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 216 | CpuProfiler* profiler = i::Isolate::Current()->cpu_profiler(); |
| 217 | profiler->StartProfiling("1"); |
| 218 | profiler->StopProfiling("2"); |
| 219 | profiler->StartProfiling("1"); |
| 220 | profiler->StopProfiling(""); |
vegorov@chromium.org | 26c16f8 | 2010-08-11 13:41:03 +0000 | [diff] [blame] | 221 | } |
| 222 | |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 223 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 224 | // http://code.google.com/p/v8/issues/detail?id=1398 |
| 225 | // Long stacks (exceeding max frames limit) must not be erased. |
| 226 | TEST(Issue1398) { |
| 227 | TestSetup test_setup; |
| 228 | CpuProfilesCollection profiles; |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 229 | profiles.StartProfiling("", 1, false); |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 230 | ProfileGenerator generator(&profiles); |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 231 | ProfilerEventsProcessor processor(&generator); |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 232 | processor.Start(); |
| 233 | |
| 234 | processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 235 | "bbb", |
| 236 | ToAddress(0x1200), |
| 237 | 0x80); |
| 238 | |
mmassi@chromium.org | 49a4467 | 2012-12-04 13:52:03 +0000 | [diff] [blame] | 239 | i::TickSample* sample = processor.TickSampleEvent(); |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 240 | sample->pc = ToAddress(0x1200); |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 241 | sample->frames_count = i::TickSample::kMaxFramesCount; |
| 242 | for (int i = 0; i < sample->frames_count; ++i) { |
| 243 | sample->stack[i] = ToAddress(0x1200); |
| 244 | } |
| 245 | |
| 246 | processor.Stop(); |
| 247 | processor.Join(); |
| 248 | CpuProfile* profile = |
| 249 | profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); |
| 250 | CHECK_NE(NULL, profile); |
| 251 | |
| 252 | int actual_depth = 0; |
| 253 | const ProfileNode* node = profile->top_down()->root(); |
| 254 | while (node->children()->length() > 0) { |
| 255 | node = node->children()->last(); |
| 256 | ++actual_depth; |
| 257 | } |
| 258 | |
| 259 | CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC. |
| 260 | } |
| 261 | |
| 262 | |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 263 | TEST(DeleteAllCpuProfiles) { |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame^] | 264 | CcTest::InitializeVM(); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 265 | TestSetup test_setup; |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 266 | CpuProfiler* profiler = i::Isolate::Current()->cpu_profiler(); |
| 267 | CHECK_EQ(0, profiler->GetProfilesCount()); |
| 268 | profiler->DeleteAllProfiles(); |
| 269 | CHECK_EQ(0, profiler->GetProfilesCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 270 | |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 271 | profiler->StartProfiling("1"); |
| 272 | profiler->StopProfiling("1"); |
| 273 | CHECK_EQ(1, profiler->GetProfilesCount()); |
| 274 | profiler->DeleteAllProfiles(); |
| 275 | CHECK_EQ(0, profiler->GetProfilesCount()); |
| 276 | profiler->StartProfiling("1"); |
| 277 | profiler->StartProfiling("2"); |
| 278 | profiler->StopProfiling("2"); |
| 279 | profiler->StopProfiling("1"); |
| 280 | CHECK_EQ(2, profiler->GetProfilesCount()); |
| 281 | profiler->DeleteAllProfiles(); |
| 282 | CHECK_EQ(0, profiler->GetProfilesCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 283 | |
| 284 | // Test profiling cancellation by the 'delete' command. |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 285 | profiler->StartProfiling("1"); |
| 286 | profiler->StartProfiling("2"); |
| 287 | CHECK_EQ(0, profiler->GetProfilesCount()); |
| 288 | profiler->DeleteAllProfiles(); |
| 289 | CHECK_EQ(0, profiler->GetProfilesCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 290 | } |
| 291 | |
| 292 | |
| 293 | TEST(DeleteCpuProfile) { |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 294 | LocalContext env; |
svenpanne@chromium.org | 2bda543 | 2013-03-15 12:39:50 +0000 | [diff] [blame] | 295 | v8::HandleScope scope(env->GetIsolate()); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 296 | v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 297 | |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 298 | CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 299 | v8::Local<v8::String> name1 = v8::String::New("1"); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 300 | cpu_profiler->StartCpuProfiling(name1); |
| 301 | const v8::CpuProfile* p1 = cpu_profiler->StopCpuProfiling(name1); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 302 | CHECK_NE(NULL, p1); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 303 | CHECK_EQ(1, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 304 | unsigned uid1 = p1->GetUid(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 305 | CHECK_EQ(p1, cpu_profiler->FindCpuProfile(uid1)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 306 | const_cast<v8::CpuProfile*>(p1)->Delete(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 307 | CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
| 308 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 309 | |
| 310 | v8::Local<v8::String> name2 = v8::String::New("2"); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 311 | cpu_profiler->StartCpuProfiling(name2); |
| 312 | const v8::CpuProfile* p2 = cpu_profiler->StopCpuProfiling(name2); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 313 | CHECK_NE(NULL, p2); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 314 | CHECK_EQ(1, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 315 | unsigned uid2 = p2->GetUid(); |
| 316 | CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2)); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 317 | CHECK_EQ(p2, cpu_profiler->FindCpuProfile(uid2)); |
| 318 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 319 | v8::Local<v8::String> name3 = v8::String::New("3"); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 320 | cpu_profiler->StartCpuProfiling(name3); |
| 321 | const v8::CpuProfile* p3 = cpu_profiler->StopCpuProfiling(name3); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 322 | CHECK_NE(NULL, p3); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 323 | CHECK_EQ(2, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 324 | unsigned uid3 = p3->GetUid(); |
| 325 | CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3)); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 326 | CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); |
| 327 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 328 | const_cast<v8::CpuProfile*>(p2)->Delete(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 329 | CHECK_EQ(1, cpu_profiler->GetProfileCount()); |
| 330 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); |
| 331 | CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 332 | const_cast<v8::CpuProfile*>(p3)->Delete(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 333 | CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
| 334 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid3)); |
| 335 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); |
| 336 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 337 | } |
| 338 | |
| 339 | |
| 340 | TEST(DeleteCpuProfileDifferentTokens) { |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 341 | LocalContext env; |
svenpanne@chromium.org | 2bda543 | 2013-03-15 12:39:50 +0000 | [diff] [blame] | 342 | v8::HandleScope scope(env->GetIsolate()); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 343 | v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 344 | |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 345 | CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 346 | v8::Local<v8::String> name1 = v8::String::New("1"); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 347 | cpu_profiler->StartCpuProfiling(name1); |
| 348 | const v8::CpuProfile* p1 = cpu_profiler->StopCpuProfiling(name1); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 349 | CHECK_NE(NULL, p1); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 350 | CHECK_EQ(1, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 351 | unsigned uid1 = p1->GetUid(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 352 | CHECK_EQ(p1, cpu_profiler->FindCpuProfile(uid1)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 353 | v8::Local<v8::String> token1 = v8::String::New("token1"); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 354 | const v8::CpuProfile* p1_t1 = cpu_profiler->FindCpuProfile(uid1, token1); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 355 | CHECK_NE(NULL, p1_t1); |
| 356 | CHECK_NE(p1, p1_t1); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 357 | CHECK_EQ(1, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 358 | const_cast<v8::CpuProfile*>(p1)->Delete(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 359 | CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
| 360 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1)); |
| 361 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1, token1)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 362 | const_cast<v8::CpuProfile*>(p1_t1)->Delete(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 363 | CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 364 | |
| 365 | v8::Local<v8::String> name2 = v8::String::New("2"); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 366 | cpu_profiler->StartCpuProfiling(name2); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 367 | v8::Local<v8::String> token2 = v8::String::New("token2"); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 368 | const v8::CpuProfile* p2_t2 = cpu_profiler->StopCpuProfiling(name2, token2); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 369 | CHECK_NE(NULL, p2_t2); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 370 | CHECK_EQ(1, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 371 | unsigned uid2 = p2_t2->GetUid(); |
| 372 | CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2)); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 373 | const v8::CpuProfile* p2 = cpu_profiler->FindCpuProfile(uid2); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 374 | CHECK_NE(p2_t2, p2); |
| 375 | v8::Local<v8::String> name3 = v8::String::New("3"); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 376 | cpu_profiler->StartCpuProfiling(name3); |
| 377 | const v8::CpuProfile* p3 = cpu_profiler->StopCpuProfiling(name3); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 378 | CHECK_NE(NULL, p3); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 379 | CHECK_EQ(2, cpu_profiler->GetProfileCount()); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 380 | unsigned uid3 = p3->GetUid(); |
| 381 | CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3)); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 382 | CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 383 | const_cast<v8::CpuProfile*>(p2_t2)->Delete(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 384 | CHECK_EQ(1, cpu_profiler->GetProfileCount()); |
| 385 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); |
| 386 | CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 387 | const_cast<v8::CpuProfile*>(p2)->Delete(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 388 | CHECK_EQ(1, cpu_profiler->GetProfileCount()); |
| 389 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); |
| 390 | CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 391 | const_cast<v8::CpuProfile*>(p3)->Delete(); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 392 | CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
| 393 | CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid3)); |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 394 | } |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame^] | 395 | |
| 396 | |
| 397 | static bool ContainsString(v8::Handle<v8::String> string, |
| 398 | const Vector<v8::Handle<v8::String> >& vector) { |
| 399 | for (int i = 0; i < vector.length(); i++) { |
| 400 | if (string->Equals(vector[i])) |
| 401 | return true; |
| 402 | } |
| 403 | return false; |
| 404 | } |
| 405 | |
| 406 | |
| 407 | static void CheckChildrenNames(const v8::CpuProfileNode* node, |
| 408 | const Vector<v8::Handle<v8::String> >& names) { |
| 409 | int count = node->GetChildrenCount(); |
| 410 | for (int i = 0; i < count; i++) { |
| 411 | v8::Handle<v8::String> name = node->GetChild(i)->GetFunctionName(); |
| 412 | CHECK(ContainsString(name, names)); |
| 413 | // Check that there are no duplicates. |
| 414 | for (int j = 0; j < count; j++) { |
| 415 | if (j == i) continue; |
| 416 | CHECK_NE(name, node->GetChild(j)->GetFunctionName()); |
| 417 | } |
| 418 | } |
| 419 | } |
| 420 | |
| 421 | |
| 422 | static const v8::CpuProfileNode* FindChild(const v8::CpuProfileNode* node, |
| 423 | const char* name) { |
| 424 | int count = node->GetChildrenCount(); |
| 425 | v8::Handle<v8::String> nameHandle = v8::String::New(name); |
| 426 | for (int i = 0; i < count; i++) { |
| 427 | const v8::CpuProfileNode* child = node->GetChild(i); |
| 428 | if (nameHandle->Equals(child->GetFunctionName())) return child; |
| 429 | } |
| 430 | CHECK(false); |
| 431 | return NULL; |
| 432 | } |
| 433 | |
| 434 | |
| 435 | static void CheckSimpleBranch(const v8::CpuProfileNode* node, |
| 436 | const char* names[], int length) { |
| 437 | for (int i = 0; i < length; i++) { |
| 438 | const char* name = names[i]; |
| 439 | node = FindChild(node, name); |
| 440 | CHECK(node); |
| 441 | int expectedChildrenCount = (i == length - 1) ? 0 : 1; |
| 442 | CHECK_EQ(expectedChildrenCount, node->GetChildrenCount()); |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | |
| 447 | static const char* cpu_profiler_test_source = "function loop(timeout) {\n" |
| 448 | " this.mmm = 0;\n" |
| 449 | " var start = Date.now();\n" |
| 450 | " while (Date.now() - start < timeout) {\n" |
| 451 | " var n = 100*1000;\n" |
| 452 | " while(n > 1) {\n" |
| 453 | " n--;\n" |
| 454 | " this.mmm += n * n * n;\n" |
| 455 | " }\n" |
| 456 | " }\n" |
| 457 | "}\n" |
| 458 | "function delay() { try { loop(10); } catch(e) { } }\n" |
| 459 | "function bar() { delay(); }\n" |
| 460 | "function baz() { delay(); }\n" |
| 461 | "function foo() {\n" |
| 462 | " try {\n" |
| 463 | " delay();\n" |
| 464 | " bar();\n" |
| 465 | " delay();\n" |
| 466 | " baz();\n" |
| 467 | " } catch (e) { }\n" |
| 468 | "}\n" |
| 469 | "function start(timeout) {\n" |
| 470 | " var start = Date.now();\n" |
| 471 | " do {\n" |
| 472 | " foo();\n" |
| 473 | " var duration = Date.now() - start;\n" |
| 474 | " } while (duration < timeout);\n" |
| 475 | " return duration;\n" |
| 476 | "}\n"; |
| 477 | |
| 478 | |
| 479 | // Check that the profile tree for the script above will look like the |
| 480 | // following: |
| 481 | // |
| 482 | // [Top down]: |
| 483 | // 1062 0 (root) [-1] |
| 484 | // 1054 0 start [-1] |
| 485 | // 1054 1 foo [-1] |
| 486 | // 265 0 baz [-1] |
| 487 | // 265 1 delay [-1] |
| 488 | // 264 264 loop [-1] |
| 489 | // 525 3 delay [-1] |
| 490 | // 522 522 loop [-1] |
| 491 | // 263 0 bar [-1] |
| 492 | // 263 1 delay [-1] |
| 493 | // 262 262 loop [-1] |
| 494 | // 2 2 (program) [-1] |
| 495 | // 6 6 (garbage collector) [-1] |
| 496 | TEST(CollectCpuProfile) { |
| 497 | LocalContext env; |
| 498 | v8::HandleScope scope(env->GetIsolate()); |
| 499 | |
| 500 | v8::Script::Compile(v8::String::New(cpu_profiler_test_source))->Run(); |
| 501 | v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( |
| 502 | env->Global()->Get(v8::String::New("start"))); |
| 503 | |
| 504 | v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); |
| 505 | v8::Local<v8::String> profile_name = v8::String::New("my_profile"); |
| 506 | |
| 507 | cpu_profiler->StartCpuProfiling(profile_name); |
| 508 | int32_t profiling_interval_ms = 200; |
| 509 | #if defined(_WIN32) || defined(_WIN64) |
| 510 | // 200ms is not enough on Windows. See |
| 511 | // https://code.google.com/p/v8/issues/detail?id=2628 |
| 512 | profiling_interval_ms = 500; |
| 513 | #endif |
| 514 | v8::Handle<v8::Value> args[] = { v8::Integer::New(profiling_interval_ms) }; |
| 515 | function->Call(env->Global(), ARRAY_SIZE(args), args); |
| 516 | const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); |
| 517 | |
| 518 | CHECK_NE(NULL, profile); |
| 519 | // Dump collected profile to have a better diagnostic in case of failure. |
| 520 | reinterpret_cast<i::CpuProfile*>( |
| 521 | const_cast<v8::CpuProfile*>(profile))->Print(); |
| 522 | |
| 523 | const v8::CpuProfileNode* root = profile->GetTopDownRoot(); |
| 524 | |
| 525 | ScopedVector<v8::Handle<v8::String> > names(3); |
| 526 | names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName); |
| 527 | names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); |
| 528 | names[2] = v8::String::New("start"); |
| 529 | CheckChildrenNames(root, names); |
| 530 | |
| 531 | const v8::CpuProfileNode* startNode = FindChild(root, "start"); |
| 532 | CHECK_EQ(1, startNode->GetChildrenCount()); |
| 533 | |
| 534 | const v8::CpuProfileNode* fooNode = FindChild(startNode, "foo"); |
| 535 | CHECK_EQ(3, fooNode->GetChildrenCount()); |
| 536 | |
| 537 | const char* barBranch[] = { "bar", "delay", "loop" }; |
| 538 | CheckSimpleBranch(fooNode, barBranch, ARRAY_SIZE(barBranch)); |
| 539 | const char* bazBranch[] = { "baz", "delay", "loop" }; |
| 540 | CheckSimpleBranch(fooNode, bazBranch, ARRAY_SIZE(bazBranch)); |
| 541 | const char* delayBranch[] = { "delay", "loop" }; |
| 542 | CheckSimpleBranch(fooNode, delayBranch, ARRAY_SIZE(delayBranch)); |
| 543 | |
| 544 | cpu_profiler->DeleteAllCpuProfiles(); |
| 545 | } |