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 13 matching lines...) Expand all Loading... |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 // | 27 // |
28 // Tests of profiles generator and utilities. | 28 // Tests of profiles generator and utilities. |
29 | 29 |
30 #define V8_DISABLE_DEPRECATIONS 1 | 30 #define V8_DISABLE_DEPRECATIONS 1 |
31 #include "v8.h" | 31 #include "v8.h" |
32 #include "cpu-profiler-inl.h" | 32 #include "cpu-profiler-inl.h" |
33 #include "cctest.h" | 33 #include "cctest.h" |
| 34 #include "platform.h" |
34 #include "utils.h" | 35 #include "utils.h" |
35 #include "../include/v8-profiler.h" | 36 #include "../include/v8-profiler.h" |
36 #undef V8_DISABLE_DEPRECATIONS | 37 #undef V8_DISABLE_DEPRECATIONS |
37 | 38 |
38 using i::CodeEntry; | 39 using i::CodeEntry; |
39 using i::CpuProfile; | 40 using i::CpuProfile; |
40 using i::CpuProfiler; | 41 using i::CpuProfiler; |
41 using i::CpuProfilesCollection; | 42 using i::CpuProfilesCollection; |
42 using i::ProfileGenerator; | 43 using i::ProfileGenerator; |
43 using i::ProfileNode; | 44 using i::ProfileNode; |
44 using i::ProfilerEventsProcessor; | 45 using i::ProfilerEventsProcessor; |
45 using i::ScopedVector; | 46 using i::ScopedVector; |
46 using i::TokenEnumerator; | |
47 using i::Vector; | 47 using i::Vector; |
48 | 48 |
49 | 49 |
50 TEST(StartStop) { | 50 TEST(StartStop) { |
51 CpuProfilesCollection profiles; | 51 CpuProfilesCollection profiles; |
52 ProfileGenerator generator(&profiles); | 52 ProfileGenerator generator(&profiles); |
53 ProfilerEventsProcessor processor(&generator, &profiles); | 53 ProfilerEventsProcessor processor(&generator); |
54 processor.Start(); | 54 processor.Start(); |
55 processor.Stop(); | 55 processor.StopSynchronously(); |
56 processor.Join(); | 56 processor.Join(); |
57 } | 57 } |
58 | 58 |
| 59 |
59 static inline i::Address ToAddress(int n) { | 60 static inline i::Address ToAddress(int n) { |
60 return reinterpret_cast<i::Address>(n); | 61 return reinterpret_cast<i::Address>(n); |
61 } | 62 } |
62 | 63 |
63 static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc, | 64 static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc, |
64 i::Address frame1, | 65 i::Address frame1, |
65 i::Address frame2 = NULL, | 66 i::Address frame2 = NULL, |
66 i::Address frame3 = NULL) { | 67 i::Address frame3 = NULL) { |
67 i::TickSample* sample = proc->TickSampleEvent(); | 68 i::TickSample* sample = proc->TickSampleEvent(); |
68 sample->pc = frame1; | 69 sample->pc = frame1; |
(...skipping 21 matching lines...) Expand all Loading... |
90 ~TestSetup() { | 91 ~TestSetup() { |
91 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_; | 92 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_; |
92 } | 93 } |
93 | 94 |
94 private: | 95 private: |
95 bool old_flag_prof_browser_mode_; | 96 bool old_flag_prof_browser_mode_; |
96 }; | 97 }; |
97 | 98 |
98 } // namespace | 99 } // namespace |
99 | 100 |
| 101 |
| 102 i::Code* CreateCode(LocalContext* env) { |
| 103 static int counter = 0; |
| 104 i::EmbeddedVector<char, 256> script; |
| 105 i::EmbeddedVector<char, 32> name; |
| 106 |
| 107 i::OS::SNPrintF(name, "function_%d", ++counter); |
| 108 const char* name_start = name.start(); |
| 109 i::OS::SNPrintF(script, |
| 110 "function %s() {\n" |
| 111 "var counter = 0;\n" |
| 112 "for (var i = 0; i < %d; ++i) counter += i;\n" |
| 113 "return '%s_' + counter;\n" |
| 114 "}\n" |
| 115 "%s();\n", name_start, counter, name_start, name_start); |
| 116 CompileRun(script.start()); |
| 117 i::Handle<i::JSFunction> fun = v8::Utils::OpenHandle( |
| 118 *v8::Local<v8::Function>::Cast( |
| 119 (*env)->Global()->Get(v8_str(name_start)))); |
| 120 return fun->code(); |
| 121 } |
| 122 |
| 123 |
100 TEST(CodeEvents) { | 124 TEST(CodeEvents) { |
101 CcTest::InitializeVM(); | 125 CcTest::InitializeVM(); |
| 126 LocalContext env; |
102 i::Isolate* isolate = i::Isolate::Current(); | 127 i::Isolate* isolate = i::Isolate::Current(); |
103 i::Heap* heap = isolate->heap(); | |
104 i::Factory* factory = isolate->factory(); | 128 i::Factory* factory = isolate->factory(); |
105 TestSetup test_setup; | 129 TestSetup test_setup; |
106 CpuProfilesCollection profiles; | 130 |
107 profiles.StartProfiling("", 1, false); | 131 i::HandleScope scope(isolate); |
108 ProfileGenerator generator(&profiles); | 132 |
109 ProfilerEventsProcessor processor(&generator, &profiles); | 133 i::Code* aaa_code = CreateCode(&env); |
| 134 i::Code* comment_code = CreateCode(&env); |
| 135 i::Code* args5_code = CreateCode(&env); |
| 136 i::Code* comment2_code = CreateCode(&env); |
| 137 i::Code* moved_code = CreateCode(&env); |
| 138 i::Code* args3_code = CreateCode(&env); |
| 139 i::Code* args4_code = CreateCode(&env); |
| 140 |
| 141 CpuProfilesCollection* profiles = new CpuProfilesCollection; |
| 142 profiles->StartProfiling("", 1, false); |
| 143 ProfileGenerator generator(profiles); |
| 144 ProfilerEventsProcessor processor(&generator); |
110 processor.Start(); | 145 processor.Start(); |
| 146 CpuProfiler profiler(isolate, profiles, &generator, &processor); |
111 | 147 |
112 // Enqueue code creation events. | 148 // Enqueue code creation events. |
113 i::HandleScope scope(isolate); | |
114 const char* aaa_str = "aaa"; | 149 const char* aaa_str = "aaa"; |
115 i::Handle<i::String> aaa_name = factory->NewStringFromAscii( | 150 i::Handle<i::String> aaa_name = factory->NewStringFromAscii( |
116 i::Vector<const char>(aaa_str, i::StrLength(aaa_str))); | 151 i::Vector<const char>(aaa_str, i::StrLength(aaa_str))); |
117 processor.CodeCreateEvent(i::Logger::FUNCTION_TAG, | 152 profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG, aaa_code, *aaa_name); |
118 *aaa_name, | 153 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment_code, "comment"); |
119 heap->empty_string(), | 154 profiler.CodeCreateEvent(i::Logger::STUB_TAG, args5_code, 5); |
120 0, | 155 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment2_code, "comment2"); |
121 ToAddress(0x1000), | 156 profiler.CodeMoveEvent(comment2_code->address(), moved_code->address()); |
122 0x100, | 157 profiler.CodeCreateEvent(i::Logger::STUB_TAG, args3_code, 3); |
123 ToAddress(0x10000), | 158 profiler.CodeCreateEvent(i::Logger::STUB_TAG, args4_code, 4); |
124 NULL); | 159 |
125 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | |
126 "bbb", | |
127 ToAddress(0x1200), | |
128 0x80); | |
129 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10); | |
130 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | |
131 "ddd", | |
132 ToAddress(0x1400), | |
133 0x80); | |
134 processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500)); | |
135 processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10); | |
136 processor.CodeCreateEvent(i::Logger::STUB_TAG, 4, ToAddress(0x1605), 0x10); | |
137 // Enqueue a tick event to enable code events processing. | 160 // Enqueue a tick event to enable code events processing. |
138 EnqueueTickSampleEvent(&processor, ToAddress(0x1000)); | 161 EnqueueTickSampleEvent(&processor, aaa_code->address()); |
139 | 162 |
140 processor.Stop(); | 163 processor.StopSynchronously(); |
141 processor.Join(); | 164 processor.Join(); |
142 | 165 |
143 // Check the state of profile generator. | 166 // Check the state of profile generator. |
144 CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000)); | 167 CodeEntry* aaa = generator.code_map()->FindEntry(aaa_code->address()); |
145 CHECK_NE(NULL, entry1); | 168 CHECK_NE(NULL, aaa); |
146 CHECK_EQ(aaa_str, entry1->name()); | 169 CHECK_EQ(aaa_str, aaa->name()); |
147 CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200)); | 170 |
148 CHECK_NE(NULL, entry2); | 171 CodeEntry* comment = generator.code_map()->FindEntry(comment_code->address()); |
149 CHECK_EQ("bbb", entry2->name()); | 172 CHECK_NE(NULL, comment); |
150 CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300)); | 173 CHECK_EQ("comment", comment->name()); |
151 CHECK_NE(NULL, entry3); | 174 |
152 CHECK_EQ("5", entry3->name()); | 175 CodeEntry* args5 = generator.code_map()->FindEntry(args5_code->address()); |
153 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400))); | 176 CHECK_NE(NULL, args5); |
154 CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500)); | 177 CHECK_EQ("5", args5->name()); |
155 CHECK_NE(NULL, entry4); | 178 |
156 CHECK_EQ("ddd", entry4->name()); | 179 CHECK_EQ(NULL, generator.code_map()->FindEntry(comment2_code->address())); |
157 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600))); | 180 |
| 181 CodeEntry* comment2 = generator.code_map()->FindEntry(moved_code->address()); |
| 182 CHECK_NE(NULL, comment2); |
| 183 CHECK_EQ("comment2", comment2->name()); |
158 } | 184 } |
159 | 185 |
160 | 186 |
161 template<typename T> | 187 template<typename T> |
162 static int CompareProfileNodes(const T* p1, const T* p2) { | 188 static int CompareProfileNodes(const T* p1, const T* p2) { |
163 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name()); | 189 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name()); |
164 } | 190 } |
165 | 191 |
| 192 |
166 TEST(TickEvents) { | 193 TEST(TickEvents) { |
167 TestSetup test_setup; | 194 TestSetup test_setup; |
168 CpuProfilesCollection profiles; | 195 LocalContext env; |
169 profiles.StartProfiling("", 1, false); | 196 i::Isolate* isolate = i::Isolate::Current(); |
170 ProfileGenerator generator(&profiles); | 197 i::HandleScope scope(isolate); |
171 ProfilerEventsProcessor processor(&generator, &profiles); | 198 |
| 199 i::Code* frame1_code = CreateCode(&env); |
| 200 i::Code* frame2_code = CreateCode(&env); |
| 201 i::Code* frame3_code = CreateCode(&env); |
| 202 |
| 203 CpuProfilesCollection* profiles = new CpuProfilesCollection; |
| 204 profiles->StartProfiling("", 1, false); |
| 205 ProfileGenerator generator(profiles); |
| 206 ProfilerEventsProcessor processor(&generator); |
172 processor.Start(); | 207 processor.Start(); |
| 208 CpuProfiler profiler(isolate, profiles, &generator, &processor); |
173 | 209 |
174 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | 210 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb"); |
175 "bbb", | 211 profiler.CodeCreateEvent(i::Logger::STUB_TAG, frame2_code, 5); |
176 ToAddress(0x1200), | 212 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame3_code, "ddd"); |
177 0x80); | |
178 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10); | |
179 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | |
180 "ddd", | |
181 ToAddress(0x1400), | |
182 0x80); | |
183 EnqueueTickSampleEvent(&processor, ToAddress(0x1210)); | |
184 EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220)); | |
185 EnqueueTickSampleEvent(&processor, | |
186 ToAddress(0x1404), | |
187 ToAddress(0x1305), | |
188 ToAddress(0x1230)); | |
189 | 213 |
190 processor.Stop(); | 214 EnqueueTickSampleEvent(&processor, frame1_code->instruction_start()); |
| 215 EnqueueTickSampleEvent( |
| 216 &processor, |
| 217 frame2_code->instruction_start() + frame2_code->ExecutableSize() / 2, |
| 218 frame1_code->instruction_start() + frame2_code->ExecutableSize() / 2); |
| 219 EnqueueTickSampleEvent( |
| 220 &processor, |
| 221 frame3_code->instruction_end() - 1, |
| 222 frame2_code->instruction_end() - 1, |
| 223 frame1_code->instruction_end() - 1); |
| 224 |
| 225 processor.StopSynchronously(); |
191 processor.Join(); | 226 processor.Join(); |
192 CpuProfile* profile = | 227 CpuProfile* profile = profiles->StopProfiling("", 1); |
193 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); | |
194 CHECK_NE(NULL, profile); | 228 CHECK_NE(NULL, profile); |
195 | 229 |
196 // Check call trees. | 230 // Check call trees. |
197 const i::List<ProfileNode*>* top_down_root_children = | 231 const i::List<ProfileNode*>* top_down_root_children = |
198 profile->top_down()->root()->children(); | 232 profile->top_down()->root()->children(); |
199 CHECK_EQ(1, top_down_root_children->length()); | 233 CHECK_EQ(1, top_down_root_children->length()); |
200 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name()); | 234 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name()); |
201 const i::List<ProfileNode*>* top_down_bbb_children = | 235 const i::List<ProfileNode*>* top_down_bbb_children = |
202 top_down_root_children->last()->children(); | 236 top_down_root_children->last()->children(); |
203 CHECK_EQ(1, top_down_bbb_children->length()); | 237 CHECK_EQ(1, top_down_bbb_children->length()); |
(...skipping 18 matching lines...) Expand all Loading... |
222 profiler->StopProfiling("2"); | 256 profiler->StopProfiling("2"); |
223 profiler->StartProfiling("1"); | 257 profiler->StartProfiling("1"); |
224 profiler->StopProfiling(""); | 258 profiler->StopProfiling(""); |
225 } | 259 } |
226 | 260 |
227 | 261 |
228 // http://code.google.com/p/v8/issues/detail?id=1398 | 262 // http://code.google.com/p/v8/issues/detail?id=1398 |
229 // Long stacks (exceeding max frames limit) must not be erased. | 263 // Long stacks (exceeding max frames limit) must not be erased. |
230 TEST(Issue1398) { | 264 TEST(Issue1398) { |
231 TestSetup test_setup; | 265 TestSetup test_setup; |
232 CpuProfilesCollection profiles; | 266 LocalContext env; |
233 profiles.StartProfiling("", 1, false); | 267 i::Isolate* isolate = i::Isolate::Current(); |
234 ProfileGenerator generator(&profiles); | 268 i::HandleScope scope(isolate); |
235 ProfilerEventsProcessor processor(&generator, &profiles); | 269 |
| 270 i::Code* code = CreateCode(&env); |
| 271 |
| 272 CpuProfilesCollection* profiles = new CpuProfilesCollection; |
| 273 profiles->StartProfiling("", 1, false); |
| 274 ProfileGenerator generator(profiles); |
| 275 ProfilerEventsProcessor processor(&generator); |
236 processor.Start(); | 276 processor.Start(); |
| 277 CpuProfiler profiler(isolate, profiles, &generator, &processor); |
237 | 278 |
238 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | 279 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb"); |
239 "bbb", | |
240 ToAddress(0x1200), | |
241 0x80); | |
242 | 280 |
243 i::TickSample* sample = processor.TickSampleEvent(); | 281 i::TickSample* sample = processor.TickSampleEvent(); |
244 sample->pc = ToAddress(0x1200); | 282 sample->pc = code->address(); |
245 sample->tos = 0; | 283 sample->tos = 0; |
246 sample->frames_count = i::TickSample::kMaxFramesCount; | 284 sample->frames_count = i::TickSample::kMaxFramesCount; |
247 for (int i = 0; i < sample->frames_count; ++i) { | 285 for (int i = 0; i < sample->frames_count; ++i) { |
248 sample->stack[i] = ToAddress(0x1200); | 286 sample->stack[i] = code->address(); |
249 } | 287 } |
250 | 288 |
251 processor.Stop(); | 289 processor.StopSynchronously(); |
252 processor.Join(); | 290 processor.Join(); |
253 CpuProfile* profile = | 291 CpuProfile* profile = profiles->StopProfiling("", 1); |
254 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); | |
255 CHECK_NE(NULL, profile); | 292 CHECK_NE(NULL, profile); |
256 | 293 |
257 int actual_depth = 0; | 294 int actual_depth = 0; |
258 const ProfileNode* node = profile->top_down()->root(); | 295 const ProfileNode* node = profile->top_down()->root(); |
259 while (node->children()->length() > 0) { | 296 while (node->children()->length() > 0) { |
260 node = node->children()->last(); | 297 node = node->children()->last(); |
261 ++actual_depth; | 298 ++actual_depth; |
262 } | 299 } |
263 | 300 |
264 CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC. | 301 CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 CHECK_EQ(NULL, FindCpuProfile(cpu_profiler, uid2)); | 385 CHECK_EQ(NULL, FindCpuProfile(cpu_profiler, uid2)); |
349 CHECK_EQ(p3, FindCpuProfile(cpu_profiler, uid3)); | 386 CHECK_EQ(p3, FindCpuProfile(cpu_profiler, uid3)); |
350 const_cast<v8::CpuProfile*>(p3)->Delete(); | 387 const_cast<v8::CpuProfile*>(p3)->Delete(); |
351 CHECK_EQ(0, cpu_profiler->GetProfileCount()); | 388 CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
352 CHECK_EQ(NULL, FindCpuProfile(cpu_profiler, uid3)); | 389 CHECK_EQ(NULL, FindCpuProfile(cpu_profiler, uid3)); |
353 CHECK_EQ(NULL, FindCpuProfile(cpu_profiler, uid2)); | 390 CHECK_EQ(NULL, FindCpuProfile(cpu_profiler, uid2)); |
354 CHECK_EQ(NULL, FindCpuProfile(cpu_profiler, uid1)); | 391 CHECK_EQ(NULL, FindCpuProfile(cpu_profiler, uid1)); |
355 } | 392 } |
356 | 393 |
357 | 394 |
358 TEST(DeleteCpuProfileDifferentTokens) { | 395 TEST(GetProfilerWhenIsolateIsNotInitialized) { |
359 LocalContext env; | 396 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
360 v8::HandleScope scope(env->GetIsolate()); | 397 CHECK(i::Isolate::Current()->IsDefaultIsolate()); |
361 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); | 398 CHECK(!i::Isolate::Current()->IsInitialized()); |
362 | 399 CHECK_EQ(NULL, isolate->GetCpuProfiler()); |
363 CHECK_EQ(0, cpu_profiler->GetProfileCount()); | 400 { |
364 v8::Local<v8::String> name1 = v8::String::New("1"); | 401 v8::Isolate::Scope isolateScope(isolate); |
365 cpu_profiler->StartCpuProfiling(name1); | 402 LocalContext env; |
366 const v8::CpuProfile* p1 = cpu_profiler->StopCpuProfiling(name1); | 403 v8::HandleScope scope(isolate); |
367 CHECK_NE(NULL, p1); | 404 CHECK_NE(NULL, isolate->GetCpuProfiler()); |
368 CHECK_EQ(1, cpu_profiler->GetProfileCount()); | 405 isolate->GetCpuProfiler()->StartCpuProfiling(v8::String::New("Test")); |
369 unsigned uid1 = p1->GetUid(); | 406 isolate->GetCpuProfiler()->StopCpuProfiling(v8::String::New("Test")); |
370 CHECK_EQ(p1, cpu_profiler->FindCpuProfile(uid1)); | 407 } |
371 v8::Local<v8::String> token1 = v8::String::New("token1"); | 408 CHECK(i::Isolate::Current()->IsInitialized()); |
372 const v8::CpuProfile* p1_t1 = cpu_profiler->FindCpuProfile(uid1, token1); | 409 CHECK_NE(NULL, isolate->GetCpuProfiler()); |
373 CHECK_NE(NULL, p1_t1); | 410 isolate->Dispose(); |
374 CHECK_NE(p1, p1_t1); | 411 CHECK_EQ(NULL, isolate->GetCpuProfiler()); |
375 CHECK_EQ(1, cpu_profiler->GetProfileCount()); | |
376 const_cast<v8::CpuProfile*>(p1)->Delete(); | |
377 CHECK_EQ(0, cpu_profiler->GetProfileCount()); | |
378 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1)); | |
379 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid1, token1)); | |
380 const_cast<v8::CpuProfile*>(p1_t1)->Delete(); | |
381 CHECK_EQ(0, cpu_profiler->GetProfileCount()); | |
382 | |
383 v8::Local<v8::String> name2 = v8::String::New("2"); | |
384 cpu_profiler->StartCpuProfiling(name2); | |
385 v8::Local<v8::String> token2 = v8::String::New("token2"); | |
386 const v8::CpuProfile* p2_t2 = cpu_profiler->StopCpuProfiling(name2, token2); | |
387 CHECK_NE(NULL, p2_t2); | |
388 CHECK_EQ(1, cpu_profiler->GetProfileCount()); | |
389 unsigned uid2 = p2_t2->GetUid(); | |
390 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2)); | |
391 const v8::CpuProfile* p2 = cpu_profiler->FindCpuProfile(uid2); | |
392 CHECK_NE(p2_t2, p2); | |
393 v8::Local<v8::String> name3 = v8::String::New("3"); | |
394 cpu_profiler->StartCpuProfiling(name3); | |
395 const v8::CpuProfile* p3 = cpu_profiler->StopCpuProfiling(name3); | |
396 CHECK_NE(NULL, p3); | |
397 CHECK_EQ(2, cpu_profiler->GetProfileCount()); | |
398 unsigned uid3 = p3->GetUid(); | |
399 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3)); | |
400 CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); | |
401 const_cast<v8::CpuProfile*>(p2_t2)->Delete(); | |
402 CHECK_EQ(1, cpu_profiler->GetProfileCount()); | |
403 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); | |
404 CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); | |
405 const_cast<v8::CpuProfile*>(p2)->Delete(); | |
406 CHECK_EQ(1, cpu_profiler->GetProfileCount()); | |
407 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); | |
408 CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); | |
409 const_cast<v8::CpuProfile*>(p3)->Delete(); | |
410 CHECK_EQ(0, cpu_profiler->GetProfileCount()); | |
411 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid3)); | |
412 } | 412 } |
413 | 413 |
414 | 414 |
415 static bool ContainsString(v8::Handle<v8::String> string, | 415 static bool ContainsString(v8::Handle<v8::String> string, |
416 const Vector<v8::Handle<v8::String> >& vector) { | 416 const Vector<v8::Handle<v8::String> >& vector) { |
417 for (int i = 0; i < vector.length(); i++) { | 417 for (int i = 0; i < vector.length(); i++) { |
418 if (string->Equals(vector[i])) | 418 if (string->Equals(vector[i])) |
419 return true; | 419 return true; |
420 } | 420 } |
421 return false; | 421 return false; |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); | 958 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); |
959 names[2] = v8::String::New("start"); | 959 names[2] = v8::String::New("start"); |
960 // Don't allow |foo| node to be at the top level. | 960 // Don't allow |foo| node to be at the top level. |
961 CheckChildrenNames(root, names); | 961 CheckChildrenNames(root, names); |
962 | 962 |
963 const v8::CpuProfileNode* startNode = GetChild(root, "start"); | 963 const v8::CpuProfileNode* startNode = GetChild(root, "start"); |
964 GetChild(startNode, "foo"); | 964 GetChild(startNode, "foo"); |
965 | 965 |
966 cpu_profiler->DeleteAllCpuProfiles(); | 966 cpu_profiler->DeleteAllCpuProfiles(); |
967 } | 967 } |
| 968 |
| 969 |
| 970 static const char* call_function_test_source = "function bar(iterations) {\n" |
| 971 "}\n" |
| 972 "function start(duration) {\n" |
| 973 " var start = Date.now();\n" |
| 974 " while (Date.now() - start < duration) {\n" |
| 975 " try {\n" |
| 976 " bar.call(this, 10 * 1000);\n" |
| 977 " } catch(e) {}\n" |
| 978 " }\n" |
| 979 "}"; |
| 980 |
| 981 |
| 982 // Test that if we sampled thread when it was inside FunctionCall buitin then |
| 983 // its caller frame will be '(unresolved function)' as we have no reliable way |
| 984 // to resolve it. |
| 985 // |
| 986 // [Top down]: |
| 987 // 96 0 (root) [-1] #1 |
| 988 // 1 1 (garbage collector) [-1] #4 |
| 989 // 5 0 (unresolved function) [-1] #5 |
| 990 // 5 5 call [-1] #6 |
| 991 // 71 70 start [-1] #3 |
| 992 // 1 1 bar [-1] #7 |
| 993 // 19 19 (program) [-1] #2 |
| 994 TEST(FunctionCallSample) { |
| 995 LocalContext env; |
| 996 v8::HandleScope scope(env->GetIsolate()); |
| 997 |
| 998 v8::Script::Compile(v8::String::New(call_function_test_source))->Run(); |
| 999 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( |
| 1000 env->Global()->Get(v8::String::New("start"))); |
| 1001 |
| 1002 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); |
| 1003 v8::Local<v8::String> profile_name = v8::String::New("my_profile"); |
| 1004 |
| 1005 cpu_profiler->StartCpuProfiling(profile_name); |
| 1006 int32_t duration_ms = 100; |
| 1007 #if defined(_WIN32) || defined(_WIN64) |
| 1008 // 100ms is not enough on Windows. See |
| 1009 // https://code.google.com/p/v8/issues/detail?id=2628 |
| 1010 duration_ms = 400; |
| 1011 #endif |
| 1012 v8::Handle<v8::Value> args[] = { v8::Integer::New(duration_ms) }; |
| 1013 function->Call(env->Global(), ARRAY_SIZE(args), args); |
| 1014 const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); |
| 1015 |
| 1016 CHECK_NE(NULL, profile); |
| 1017 // Dump collected profile to have a better diagnostic in case of failure. |
| 1018 reinterpret_cast<i::CpuProfile*>( |
| 1019 const_cast<v8::CpuProfile*>(profile))->Print(); |
| 1020 |
| 1021 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); |
| 1022 { |
| 1023 ScopedVector<v8::Handle<v8::String> > names(4); |
| 1024 names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName); |
| 1025 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); |
| 1026 names[2] = v8::String::New("start"); |
| 1027 names[3] = v8::String::New(i::ProfileGenerator::kUnresolvedFunctionName); |
| 1028 // Don't allow |bar| and |call| nodes to be at the top level. |
| 1029 CheckChildrenNames(root, names); |
| 1030 } |
| 1031 |
| 1032 // In case of GC stress tests all samples may be in GC phase and there |
| 1033 // won't be |start| node in the profiles. |
| 1034 bool is_gc_stress_testing = |
| 1035 (i::FLAG_gc_interval != -1) || i::FLAG_stress_compaction; |
| 1036 const v8::CpuProfileNode* startNode = FindChild(root, "start"); |
| 1037 CHECK(is_gc_stress_testing || startNode); |
| 1038 if (startNode) { |
| 1039 ScopedVector<v8::Handle<v8::String> > names(2); |
| 1040 names[0] = v8::String::New("bar"); |
| 1041 names[1] = v8::String::New("call"); |
| 1042 CheckChildrenNames(startNode, names); |
| 1043 } |
| 1044 |
| 1045 const v8::CpuProfileNode* unresolvedNode = |
| 1046 FindChild(root, i::ProfileGenerator::kUnresolvedFunctionName); |
| 1047 if (unresolvedNode) { |
| 1048 ScopedVector<v8::Handle<v8::String> > names(1); |
| 1049 names[0] = v8::String::New("call"); |
| 1050 CheckChildrenNames(unresolvedNode, names); |
| 1051 } |
| 1052 |
| 1053 cpu_profiler->DeleteAllCpuProfiles(); |
| 1054 } |
| 1055 |
| 1056 |
| 1057 static const char* function_apply_test_source = "function bar(iterations) {\n" |
| 1058 "}\n" |
| 1059 "function test() {\n" |
| 1060 " bar.apply(this, [10 * 1000]);\n" |
| 1061 "}\n" |
| 1062 "function start(duration) {\n" |
| 1063 " var start = Date.now();\n" |
| 1064 " while (Date.now() - start < duration) {\n" |
| 1065 " try {\n" |
| 1066 " test();\n" |
| 1067 " } catch(e) {}\n" |
| 1068 " }\n" |
| 1069 "}"; |
| 1070 |
| 1071 |
| 1072 // [Top down]: |
| 1073 // 94 0 (root) [-1] #0 1 |
| 1074 // 2 2 (garbage collector) [-1] #0 7 |
| 1075 // 82 49 start [-1] #16 3 |
| 1076 // 1 0 (unresolved function) [-1] #0 8 |
| 1077 // 1 1 apply [-1] #0 9 |
| 1078 // 32 21 test [-1] #16 4 |
| 1079 // 2 2 bar [-1] #16 6 |
| 1080 // 9 9 apply [-1] #0 5 |
| 1081 // 10 10 (program) [-1] #0 2 |
| 1082 TEST(FunctionApplySample) { |
| 1083 LocalContext env; |
| 1084 v8::HandleScope scope(env->GetIsolate()); |
| 1085 |
| 1086 v8::Script::Compile(v8::String::New(function_apply_test_source))->Run(); |
| 1087 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( |
| 1088 env->Global()->Get(v8::String::New("start"))); |
| 1089 |
| 1090 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); |
| 1091 v8::Local<v8::String> profile_name = v8::String::New("my_profile"); |
| 1092 |
| 1093 cpu_profiler->StartCpuProfiling(profile_name); |
| 1094 int32_t duration_ms = 100; |
| 1095 #if defined(_WIN32) || defined(_WIN64) |
| 1096 // 100ms is not enough on Windows. See |
| 1097 // https://code.google.com/p/v8/issues/detail?id=2628 |
| 1098 duration_ms = 400; |
| 1099 #endif |
| 1100 v8::Handle<v8::Value> args[] = { v8::Integer::New(duration_ms) }; |
| 1101 function->Call(env->Global(), ARRAY_SIZE(args), args); |
| 1102 const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); |
| 1103 |
| 1104 CHECK_NE(NULL, profile); |
| 1105 // Dump collected profile to have a better diagnostic in case of failure. |
| 1106 reinterpret_cast<i::CpuProfile*>( |
| 1107 const_cast<v8::CpuProfile*>(profile))->Print(); |
| 1108 |
| 1109 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); |
| 1110 { |
| 1111 ScopedVector<v8::Handle<v8::String> > names(3); |
| 1112 names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName); |
| 1113 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); |
| 1114 names[2] = v8::String::New("start"); |
| 1115 // Don't allow |test|, |bar| and |apply| nodes to be at the top level. |
| 1116 CheckChildrenNames(root, names); |
| 1117 } |
| 1118 |
| 1119 const v8::CpuProfileNode* startNode = FindChild(root, "start"); |
| 1120 if (startNode) { |
| 1121 { |
| 1122 ScopedVector<v8::Handle<v8::String> > names(2); |
| 1123 names[0] = v8::String::New("test"); |
| 1124 names[1] = v8::String::New(ProfileGenerator::kUnresolvedFunctionName); |
| 1125 CheckChildrenNames(startNode, names); |
| 1126 } |
| 1127 |
| 1128 const v8::CpuProfileNode* testNode = FindChild(startNode, "test"); |
| 1129 if (testNode) { |
| 1130 ScopedVector<v8::Handle<v8::String> > names(2); |
| 1131 names[0] = v8::String::New("bar"); |
| 1132 names[1] = v8::String::New("apply"); |
| 1133 CheckChildrenNames(testNode, names); |
| 1134 } |
| 1135 |
| 1136 if (const v8::CpuProfileNode* unresolvedNode = |
| 1137 FindChild(startNode, ProfileGenerator::kUnresolvedFunctionName)) { |
| 1138 ScopedVector<v8::Handle<v8::String> > names(1); |
| 1139 names[0] = v8::String::New("apply"); |
| 1140 CheckChildrenNames(unresolvedNode, names); |
| 1141 GetChild(unresolvedNode, "apply"); |
| 1142 } |
| 1143 } |
| 1144 |
| 1145 cpu_profiler->DeleteAllCpuProfiles(); |
| 1146 } |
OLD | NEW |