OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/assert.h" | 5 #include "platform/assert.h" |
6 | 6 |
7 #include "vm/dart_api_impl.h" | 7 #include "vm/dart_api_impl.h" |
8 #include "vm/dart_api_state.h" | 8 #include "vm/dart_api_state.h" |
9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
10 #include "vm/profiler.h" | 10 #include "vm/profiler.h" |
11 #include "vm/profiler_service.h" | 11 #include "vm/profiler_service.h" |
12 #include "vm/unit_test.h" | 12 #include "vm/unit_test.h" |
13 | 13 |
14 namespace dart { | 14 namespace dart { |
15 | 15 |
16 DECLARE_FLAG(bool, profile_vm); | 16 DECLARE_FLAG(bool, profile_vm); |
| 17 DECLARE_FLAG(int, max_profile_depth); |
17 | 18 |
18 // Some tests are written assuming native stack trace profiling is disabled. | 19 // Some tests are written assuming native stack trace profiling is disabled. |
19 class DisableNativeProfileScope { | 20 class DisableNativeProfileScope : public ValueObject { |
20 public: | 21 public: |
21 DisableNativeProfileScope() | 22 DisableNativeProfileScope() |
22 : FLAG_profile_vm_(FLAG_profile_vm) { | 23 : FLAG_profile_vm_(FLAG_profile_vm) { |
23 FLAG_profile_vm = false; | 24 FLAG_profile_vm = false; |
24 } | 25 } |
25 | 26 |
26 ~DisableNativeProfileScope() { | 27 ~DisableNativeProfileScope() { |
27 FLAG_profile_vm = FLAG_profile_vm_; | 28 FLAG_profile_vm = FLAG_profile_vm_; |
28 } | 29 } |
29 | 30 |
30 private: | 31 private: |
31 const bool FLAG_profile_vm_; | 32 const bool FLAG_profile_vm_; |
32 }; | 33 }; |
33 | 34 |
34 | 35 |
| 36 // Temporarily adjust the maximum profile depth. |
| 37 class MaxProfileDepthScope : public ValueObject { |
| 38 public: |
| 39 explicit MaxProfileDepthScope(intptr_t new_max_depth) |
| 40 : FLAG_max_profile_depth_(FLAG_max_profile_depth) { |
| 41 Profiler::SetSampleDepth(new_max_depth); |
| 42 } |
| 43 |
| 44 ~MaxProfileDepthScope() { |
| 45 Profiler::SetSampleDepth(FLAG_max_profile_depth_); |
| 46 } |
| 47 |
| 48 private: |
| 49 const intptr_t FLAG_max_profile_depth_; |
| 50 }; |
| 51 |
| 52 |
35 class ProfileSampleBufferTestHelper { | 53 class ProfileSampleBufferTestHelper { |
36 public: | 54 public: |
37 static intptr_t IterateCount(const Isolate* isolate, | 55 static intptr_t IterateCount(const Isolate* isolate, |
38 const SampleBuffer& sample_buffer) { | 56 const SampleBuffer& sample_buffer) { |
39 intptr_t c = 0; | 57 intptr_t c = 0; |
40 for (intptr_t i = 0; i < sample_buffer.capacity(); i++) { | 58 for (intptr_t i = 0; i < sample_buffer.capacity(); i++) { |
41 Sample* sample = sample_buffer.At(i); | 59 Sample* sample = sample_buffer.At(i); |
42 if (sample->isolate() != isolate) { | 60 if (sample->isolate() != isolate) { |
43 continue; | 61 continue; |
44 } | 62 } |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 | 197 |
180 const Class& class_a = Class::Handle(GetClass(root_library, "A")); | 198 const Class& class_a = Class::Handle(GetClass(root_library, "A")); |
181 EXPECT(!class_a.IsNull()); | 199 EXPECT(!class_a.IsNull()); |
182 class_a.SetTraceAllocation(true); | 200 class_a.SetTraceAllocation(true); |
183 | 201 |
184 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 202 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
185 EXPECT_VALID(result); | 203 EXPECT_VALID(result); |
186 | 204 |
187 | 205 |
188 { | 206 { |
189 Isolate* isolate = Isolate::Current(); | 207 Thread* thread = Thread::Current(); |
190 StackZone zone(isolate); | 208 Isolate* isolate = thread->isolate(); |
191 HANDLESCOPE(isolate); | 209 StackZone zone(thread); |
| 210 HANDLESCOPE(thread); |
192 Profile profile(isolate); | 211 Profile profile(isolate); |
193 AllocationFilter filter(isolate, class_a.id()); | 212 AllocationFilter filter(isolate, class_a.id()); |
194 profile.Build(&filter, Profile::kNoTags); | 213 profile.Build(&filter, Profile::kNoTags); |
195 // We should have 1 allocation sample. | 214 // We should have 1 allocation sample. |
196 EXPECT_EQ(1, profile.sample_count()); | 215 EXPECT_EQ(1, profile.sample_count()); |
197 ProfileTrieWalker walker(&profile); | 216 ProfileTrieWalker walker(&profile); |
198 | 217 |
199 // Exclusive code: B.boo -> main. | 218 // Exclusive code: B.boo -> main. |
200 walker.Reset(Profile::kExclusiveCode); | 219 walker.Reset(Profile::kExclusiveCode); |
201 // Move down from the root. | 220 // Move down from the root. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 root_library ^= Api::UnwrapHandle(lib); | 276 root_library ^= Api::UnwrapHandle(lib); |
258 | 277 |
259 const Class& class_a = Class::Handle(GetClass(root_library, "A")); | 278 const Class& class_a = Class::Handle(GetClass(root_library, "A")); |
260 EXPECT(!class_a.IsNull()); | 279 EXPECT(!class_a.IsNull()); |
261 | 280 |
262 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 281 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
263 EXPECT_VALID(result); | 282 EXPECT_VALID(result); |
264 | 283 |
265 | 284 |
266 { | 285 { |
267 Isolate* isolate = Isolate::Current(); | 286 Thread* thread = Thread::Current(); |
268 StackZone zone(isolate); | 287 Isolate* isolate = thread->isolate(); |
269 HANDLESCOPE(isolate); | 288 StackZone zone(thread); |
| 289 HANDLESCOPE(thread); |
270 Profile profile(isolate); | 290 Profile profile(isolate); |
271 AllocationFilter filter(isolate, class_a.id()); | 291 AllocationFilter filter(isolate, class_a.id()); |
272 profile.Build(&filter, Profile::kNoTags); | 292 profile.Build(&filter, Profile::kNoTags); |
273 // We should have no allocation samples. | 293 // We should have no allocation samples. |
274 EXPECT_EQ(0, profile.sample_count()); | 294 EXPECT_EQ(0, profile.sample_count()); |
275 } | 295 } |
276 | 296 |
277 // Turn on allocation tracing for A. | 297 // Turn on allocation tracing for A. |
278 class_a.SetTraceAllocation(true); | 298 class_a.SetTraceAllocation(true); |
279 | 299 |
280 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 300 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
281 EXPECT_VALID(result); | 301 EXPECT_VALID(result); |
282 | 302 |
283 { | 303 { |
284 Isolate* isolate = Isolate::Current(); | 304 Thread* thread = Thread::Current(); |
285 StackZone zone(isolate); | 305 Isolate* isolate = thread->isolate(); |
286 HANDLESCOPE(isolate); | 306 StackZone zone(thread); |
| 307 HANDLESCOPE(thread); |
287 Profile profile(isolate); | 308 Profile profile(isolate); |
288 AllocationFilter filter(isolate, class_a.id()); | 309 AllocationFilter filter(isolate, class_a.id()); |
289 profile.Build(&filter, Profile::kNoTags); | 310 profile.Build(&filter, Profile::kNoTags); |
290 // We should have one allocation sample. | 311 // We should have one allocation sample. |
291 EXPECT_EQ(1, profile.sample_count()); | 312 EXPECT_EQ(1, profile.sample_count()); |
292 ProfileTrieWalker walker(&profile); | 313 ProfileTrieWalker walker(&profile); |
293 | 314 |
294 // Exclusive code: B.boo -> main. | 315 // Exclusive code: B.boo -> main. |
295 walker.Reset(Profile::kExclusiveCode); | 316 walker.Reset(Profile::kExclusiveCode); |
296 // Move down from the root. | 317 // Move down from the root. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 EXPECT(!walker.Down()); | 349 EXPECT(!walker.Down()); |
329 } | 350 } |
330 | 351 |
331 // Turn off allocation tracing for A. | 352 // Turn off allocation tracing for A. |
332 class_a.SetTraceAllocation(false); | 353 class_a.SetTraceAllocation(false); |
333 | 354 |
334 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 355 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
335 EXPECT_VALID(result); | 356 EXPECT_VALID(result); |
336 | 357 |
337 { | 358 { |
338 Isolate* isolate = Isolate::Current(); | 359 Thread* thread = Thread::Current(); |
339 StackZone zone(isolate); | 360 Isolate* isolate = thread->isolate(); |
340 HANDLESCOPE(isolate); | 361 StackZone zone(thread); |
| 362 HANDLESCOPE(thread); |
341 Profile profile(isolate); | 363 Profile profile(isolate); |
342 AllocationFilter filter(isolate, class_a.id()); | 364 AllocationFilter filter(isolate, class_a.id()); |
343 profile.Build(&filter, Profile::kNoTags); | 365 profile.Build(&filter, Profile::kNoTags); |
344 // We should still only have one allocation sample. | 366 // We should still only have one allocation sample. |
345 EXPECT_EQ(1, profile.sample_count()); | 367 EXPECT_EQ(1, profile.sample_count()); |
346 } | 368 } |
347 } | 369 } |
348 | 370 |
349 | 371 |
350 TEST_CASE(Profiler_CodeTicks) { | 372 TEST_CASE(Profiler_CodeTicks) { |
(...skipping 17 matching lines...) Expand all Loading... |
368 Library& root_library = Library::Handle(); | 390 Library& root_library = Library::Handle(); |
369 root_library ^= Api::UnwrapHandle(lib); | 391 root_library ^= Api::UnwrapHandle(lib); |
370 | 392 |
371 const Class& class_a = Class::Handle(GetClass(root_library, "A")); | 393 const Class& class_a = Class::Handle(GetClass(root_library, "A")); |
372 EXPECT(!class_a.IsNull()); | 394 EXPECT(!class_a.IsNull()); |
373 | 395 |
374 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 396 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
375 EXPECT_VALID(result); | 397 EXPECT_VALID(result); |
376 | 398 |
377 { | 399 { |
378 Isolate* isolate = Isolate::Current(); | 400 Thread* thread = Thread::Current(); |
379 StackZone zone(isolate); | 401 Isolate* isolate = thread->isolate(); |
380 HANDLESCOPE(isolate); | 402 StackZone zone(thread); |
| 403 HANDLESCOPE(thread); |
381 Profile profile(isolate); | 404 Profile profile(isolate); |
382 AllocationFilter filter(isolate, class_a.id()); | 405 AllocationFilter filter(isolate, class_a.id()); |
383 profile.Build(&filter, Profile::kNoTags); | 406 profile.Build(&filter, Profile::kNoTags); |
384 // We should have no allocation samples. | 407 // We should have no allocation samples. |
385 EXPECT_EQ(0, profile.sample_count()); | 408 EXPECT_EQ(0, profile.sample_count()); |
386 } | 409 } |
387 | 410 |
388 // Turn on allocation tracing for A. | 411 // Turn on allocation tracing for A. |
389 class_a.SetTraceAllocation(true); | 412 class_a.SetTraceAllocation(true); |
390 | 413 |
391 // Allocate three times. | 414 // Allocate three times. |
392 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 415 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
393 EXPECT_VALID(result); | 416 EXPECT_VALID(result); |
394 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 417 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
395 EXPECT_VALID(result); | 418 EXPECT_VALID(result); |
396 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 419 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
397 EXPECT_VALID(result); | 420 EXPECT_VALID(result); |
398 | 421 |
399 { | 422 { |
400 Isolate* isolate = Isolate::Current(); | 423 Thread* thread = Thread::Current(); |
401 StackZone zone(isolate); | 424 Isolate* isolate = thread->isolate(); |
402 HANDLESCOPE(isolate); | 425 StackZone zone(thread); |
| 426 HANDLESCOPE(thread); |
403 Profile profile(isolate); | 427 Profile profile(isolate); |
404 AllocationFilter filter(isolate, class_a.id()); | 428 AllocationFilter filter(isolate, class_a.id()); |
405 profile.Build(&filter, Profile::kNoTags); | 429 profile.Build(&filter, Profile::kNoTags); |
406 // We should have three allocation samples. | 430 // We should have three allocation samples. |
407 EXPECT_EQ(3, profile.sample_count()); | 431 EXPECT_EQ(3, profile.sample_count()); |
408 ProfileTrieWalker walker(&profile); | 432 ProfileTrieWalker walker(&profile); |
409 | 433 |
410 // Exclusive code: B.boo -> main. | 434 // Exclusive code: B.boo -> main. |
411 walker.Reset(Profile::kExclusiveCode); | 435 walker.Reset(Profile::kExclusiveCode); |
412 // Move down from the root. | 436 // Move down from the root. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 Library& root_library = Library::Handle(); | 485 Library& root_library = Library::Handle(); |
462 root_library ^= Api::UnwrapHandle(lib); | 486 root_library ^= Api::UnwrapHandle(lib); |
463 | 487 |
464 const Class& class_a = Class::Handle(GetClass(root_library, "A")); | 488 const Class& class_a = Class::Handle(GetClass(root_library, "A")); |
465 EXPECT(!class_a.IsNull()); | 489 EXPECT(!class_a.IsNull()); |
466 | 490 |
467 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 491 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
468 EXPECT_VALID(result); | 492 EXPECT_VALID(result); |
469 | 493 |
470 { | 494 { |
471 Isolate* isolate = Isolate::Current(); | 495 Thread* thread = Thread::Current(); |
472 StackZone zone(isolate); | 496 Isolate* isolate = thread->isolate(); |
473 HANDLESCOPE(isolate); | 497 StackZone zone(thread); |
| 498 HANDLESCOPE(thread); |
474 Profile profile(isolate); | 499 Profile profile(isolate); |
475 AllocationFilter filter(isolate, class_a.id()); | 500 AllocationFilter filter(isolate, class_a.id()); |
476 profile.Build(&filter, Profile::kNoTags); | 501 profile.Build(&filter, Profile::kNoTags); |
477 // We should have no allocation samples. | 502 // We should have no allocation samples. |
478 EXPECT_EQ(0, profile.sample_count()); | 503 EXPECT_EQ(0, profile.sample_count()); |
479 } | 504 } |
480 | 505 |
481 // Turn on allocation tracing for A. | 506 // Turn on allocation tracing for A. |
482 class_a.SetTraceAllocation(true); | 507 class_a.SetTraceAllocation(true); |
483 | 508 |
484 // Allocate three times. | 509 // Allocate three times. |
485 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 510 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
486 EXPECT_VALID(result); | 511 EXPECT_VALID(result); |
487 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 512 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
488 EXPECT_VALID(result); | 513 EXPECT_VALID(result); |
489 result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 514 result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
490 EXPECT_VALID(result); | 515 EXPECT_VALID(result); |
491 | 516 |
492 { | 517 { |
493 Isolate* isolate = Isolate::Current(); | 518 Thread* thread = Thread::Current(); |
494 StackZone zone(isolate); | 519 Isolate* isolate = thread->isolate(); |
495 HANDLESCOPE(isolate); | 520 StackZone zone(thread); |
| 521 HANDLESCOPE(thread); |
496 Profile profile(isolate); | 522 Profile profile(isolate); |
497 AllocationFilter filter(isolate, class_a.id()); | 523 AllocationFilter filter(isolate, class_a.id()); |
498 profile.Build(&filter, Profile::kNoTags); | 524 profile.Build(&filter, Profile::kNoTags); |
499 // We should have three allocation samples. | 525 // We should have three allocation samples. |
500 EXPECT_EQ(3, profile.sample_count()); | 526 EXPECT_EQ(3, profile.sample_count()); |
501 ProfileTrieWalker walker(&profile); | 527 ProfileTrieWalker walker(&profile); |
502 | 528 |
503 // Exclusive function: B.boo -> main. | 529 // Exclusive function: B.boo -> main. |
504 walker.Reset(Profile::kExclusiveFunction); | 530 walker.Reset(Profile::kExclusiveFunction); |
505 // Move down from the root. | 531 // Move down from the root. |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1134 | 1160 |
1135 // Compile "main". | 1161 // Compile "main". |
1136 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 1162 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
1137 EXPECT_VALID(result); | 1163 EXPECT_VALID(result); |
1138 // Compile "mainA". | 1164 // Compile "mainA". |
1139 result = Dart_Invoke(lib, NewString("mainA"), 0, NULL); | 1165 result = Dart_Invoke(lib, NewString("mainA"), 0, NULL); |
1140 EXPECT_VALID(result); | 1166 EXPECT_VALID(result); |
1141 // At this point B.boo should be optimized and inlined B.foo and B.choo. | 1167 // At this point B.boo should be optimized and inlined B.foo and B.choo. |
1142 | 1168 |
1143 { | 1169 { |
1144 Isolate* isolate = Isolate::Current(); | 1170 Thread* thread = Thread::Current(); |
1145 StackZone zone(isolate); | 1171 Isolate* isolate = thread->isolate(); |
1146 HANDLESCOPE(isolate); | 1172 StackZone zone(thread); |
| 1173 HANDLESCOPE(thread); |
1147 Profile profile(isolate); | 1174 Profile profile(isolate); |
1148 AllocationFilter filter(isolate, class_a.id()); | 1175 AllocationFilter filter(isolate, class_a.id()); |
1149 profile.Build(&filter, Profile::kNoTags); | 1176 profile.Build(&filter, Profile::kNoTags); |
1150 // We should have no allocation samples. | 1177 // We should have no allocation samples. |
1151 EXPECT_EQ(0, profile.sample_count()); | 1178 EXPECT_EQ(0, profile.sample_count()); |
1152 } | 1179 } |
1153 | 1180 |
1154 // Turn on allocation tracing for A. | 1181 // Turn on allocation tracing for A. |
1155 class_a.SetTraceAllocation(true); | 1182 class_a.SetTraceAllocation(true); |
1156 | 1183 |
1157 // Allocate 50,000 instances of A. | 1184 // Allocate 50,000 instances of A. |
1158 result = Dart_Invoke(lib, NewString("mainA"), 0, NULL); | 1185 result = Dart_Invoke(lib, NewString("mainA"), 0, NULL); |
1159 EXPECT_VALID(result); | 1186 EXPECT_VALID(result); |
1160 | 1187 |
1161 { | 1188 { |
1162 Isolate* isolate = Isolate::Current(); | 1189 Thread* thread = Thread::Current(); |
1163 StackZone zone(isolate); | 1190 Isolate* isolate = thread->isolate(); |
1164 HANDLESCOPE(isolate); | 1191 StackZone zone(thread); |
| 1192 HANDLESCOPE(thread); |
1165 Profile profile(isolate); | 1193 Profile profile(isolate); |
1166 AllocationFilter filter(isolate, class_a.id()); | 1194 AllocationFilter filter(isolate, class_a.id()); |
1167 profile.Build(&filter, Profile::kNoTags); | 1195 profile.Build(&filter, Profile::kNoTags); |
1168 // We should have 50,000 allocation samples. | 1196 // We should have 50,000 allocation samples. |
1169 EXPECT_EQ(50000, profile.sample_count()); | 1197 EXPECT_EQ(50000, profile.sample_count()); |
1170 ProfileTrieWalker walker(&profile); | 1198 ProfileTrieWalker walker(&profile); |
1171 // We have two code objects: mainA and B.boo. | 1199 // We have two code objects: mainA and B.boo. |
1172 walker.Reset(Profile::kExclusiveCode); | 1200 walker.Reset(Profile::kExclusiveCode); |
1173 EXPECT(walker.Down()); | 1201 EXPECT(walker.Down()); |
1174 EXPECT_STREQ("B.boo", walker.CurrentName()); | 1202 EXPECT_STREQ("B.boo", walker.CurrentName()); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 EXPECT_STREQ("B.choo", walker.CurrentName()); | 1281 EXPECT_STREQ("B.choo", walker.CurrentName()); |
1254 EXPECT_EQ(1, walker.SiblingCount()); | 1282 EXPECT_EQ(1, walker.SiblingCount()); |
1255 EXPECT_EQ(50000, walker.CurrentNodeTickCount()); | 1283 EXPECT_EQ(50000, walker.CurrentNodeTickCount()); |
1256 EXPECT_EQ(50000, walker.CurrentInclusiveTicks()); | 1284 EXPECT_EQ(50000, walker.CurrentInclusiveTicks()); |
1257 EXPECT_EQ(50000, walker.CurrentExclusiveTicks()); | 1285 EXPECT_EQ(50000, walker.CurrentExclusiveTicks()); |
1258 EXPECT(!walker.Down()); | 1286 EXPECT(!walker.Down()); |
1259 } | 1287 } |
1260 | 1288 |
1261 // Test code transition tags. | 1289 // Test code transition tags. |
1262 { | 1290 { |
1263 Isolate* isolate = Isolate::Current(); | 1291 Thread* thread = Thread::Current(); |
1264 StackZone zone(isolate); | 1292 Isolate* isolate = thread->isolate(); |
1265 HANDLESCOPE(isolate); | 1293 StackZone zone(thread); |
| 1294 HANDLESCOPE(thread); |
1266 Profile profile(isolate); | 1295 Profile profile(isolate); |
1267 AllocationFilter filter(isolate, class_a.id()); | 1296 AllocationFilter filter(isolate, class_a.id()); |
1268 profile.Build(&filter, | 1297 profile.Build(&filter, |
1269 Profile::kNoTags, | 1298 Profile::kNoTags, |
1270 ProfilerService::kCodeTransitionTagsBit); | 1299 ProfilerService::kCodeTransitionTagsBit); |
1271 // We should have 50,000 allocation samples. | 1300 // We should have 50,000 allocation samples. |
1272 EXPECT_EQ(50000, profile.sample_count()); | 1301 EXPECT_EQ(50000, profile.sample_count()); |
1273 ProfileTrieWalker walker(&profile); | 1302 ProfileTrieWalker walker(&profile); |
1274 // We have two code objects: mainA and B.boo. | 1303 // We have two code objects: mainA and B.boo. |
1275 walker.Reset(Profile::kExclusiveCode); | 1304 walker.Reset(Profile::kExclusiveCode); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 EXPECT(walker.Down()); | 1360 EXPECT(walker.Down()); |
1332 EXPECT_STREQ("B.foo", walker.CurrentName()); | 1361 EXPECT_STREQ("B.foo", walker.CurrentName()); |
1333 EXPECT(walker.Down()); | 1362 EXPECT(walker.Down()); |
1334 EXPECT_STREQ("B.choo", walker.CurrentName()); | 1363 EXPECT_STREQ("B.choo", walker.CurrentName()); |
1335 EXPECT(walker.Down()); | 1364 EXPECT(walker.Down()); |
1336 EXPECT_STREQ("[Inline End]", walker.CurrentName()); | 1365 EXPECT_STREQ("[Inline End]", walker.CurrentName()); |
1337 EXPECT(!walker.Down()); | 1366 EXPECT(!walker.Down()); |
1338 } | 1367 } |
1339 } | 1368 } |
1340 | 1369 |
| 1370 |
| 1371 TEST_CASE(Profiler_ChainedSamples) { |
| 1372 MaxProfileDepthScope mpds(32); |
| 1373 // Each sample holds 8 stack frames. |
| 1374 // This chain is 20 stack frames deep. |
| 1375 const char* kScript = |
| 1376 "class A {\n" |
| 1377 " var a;\n" |
| 1378 " var b;\n" |
| 1379 "}\n" |
| 1380 "class B {\n" |
| 1381 " static boo() {\n" |
| 1382 " return new A();\n" |
| 1383 " }\n" |
| 1384 "}\n" |
| 1385 "go() => init();\n" |
| 1386 "init() => secondInit();\n" |
| 1387 "secondInit() => apple();\n" |
| 1388 "apple() => banana();\n" |
| 1389 "banana() => cantaloupe();\n" |
| 1390 "cantaloupe() => dog();\n" |
| 1391 "dog() => elephant();\n" |
| 1392 "elephant() => fred();\n" |
| 1393 "fred() => granola();\n" |
| 1394 "granola() => haystack();\n" |
| 1395 "haystack() => ice();\n" |
| 1396 "ice() => jeep();\n" |
| 1397 "jeep() => kindle();\n" |
| 1398 "kindle() => lemon();\n" |
| 1399 "lemon() => mayo();\n" |
| 1400 "mayo() => napkin();\n" |
| 1401 "napkin() => orange();\n" |
| 1402 "orange() => B.boo();\n" |
| 1403 "main() {\n" |
| 1404 " return go();\n" |
| 1405 "}\n"; |
| 1406 |
| 1407 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 1408 EXPECT_VALID(lib); |
| 1409 Library& root_library = Library::Handle(); |
| 1410 root_library ^= Api::UnwrapHandle(lib); |
| 1411 |
| 1412 const Class& class_a = Class::Handle(GetClass(root_library, "A")); |
| 1413 EXPECT(!class_a.IsNull()); |
| 1414 class_a.SetTraceAllocation(true); |
| 1415 |
| 1416 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
| 1417 EXPECT_VALID(result); |
| 1418 |
| 1419 |
| 1420 { |
| 1421 Thread* thread = Thread::Current(); |
| 1422 Isolate* isolate = thread->isolate(); |
| 1423 StackZone zone(thread); |
| 1424 HANDLESCOPE(thread); |
| 1425 Profile profile(isolate); |
| 1426 AllocationFilter filter(isolate, class_a.id()); |
| 1427 profile.Build(&filter, Profile::kNoTags); |
| 1428 // We should have 1 allocation sample. |
| 1429 EXPECT_EQ(1, profile.sample_count()); |
| 1430 ProfileTrieWalker walker(&profile); |
| 1431 |
| 1432 walker.Reset(Profile::kExclusiveCode); |
| 1433 // Move down from the root. |
| 1434 EXPECT(walker.Down()); |
| 1435 EXPECT_STREQ("B.boo", walker.CurrentName()); |
| 1436 EXPECT(walker.Down()); |
| 1437 EXPECT_STREQ("orange", walker.CurrentName()); |
| 1438 EXPECT(walker.Down()); |
| 1439 EXPECT_STREQ("napkin", walker.CurrentName()); |
| 1440 EXPECT(walker.Down()); |
| 1441 EXPECT_STREQ("mayo", walker.CurrentName()); |
| 1442 EXPECT(walker.Down()); |
| 1443 EXPECT_STREQ("lemon", walker.CurrentName()); |
| 1444 EXPECT(walker.Down()); |
| 1445 EXPECT_STREQ("kindle", walker.CurrentName()); |
| 1446 EXPECT(walker.Down()); |
| 1447 EXPECT_STREQ("jeep", walker.CurrentName()); |
| 1448 EXPECT(walker.Down()); |
| 1449 EXPECT_STREQ("ice", walker.CurrentName()); |
| 1450 EXPECT(walker.Down()); |
| 1451 EXPECT_STREQ("haystack", walker.CurrentName()); |
| 1452 EXPECT(walker.Down()); |
| 1453 EXPECT_STREQ("granola", walker.CurrentName()); |
| 1454 EXPECT(walker.Down()); |
| 1455 EXPECT_STREQ("fred", walker.CurrentName()); |
| 1456 EXPECT(walker.Down()); |
| 1457 EXPECT_STREQ("elephant", walker.CurrentName()); |
| 1458 EXPECT(walker.Down()); |
| 1459 EXPECT_STREQ("dog", walker.CurrentName()); |
| 1460 EXPECT(walker.Down()); |
| 1461 EXPECT_STREQ("cantaloupe", walker.CurrentName()); |
| 1462 EXPECT(walker.Down()); |
| 1463 EXPECT_STREQ("banana", walker.CurrentName()); |
| 1464 EXPECT(walker.Down()); |
| 1465 EXPECT_STREQ("apple", walker.CurrentName()); |
| 1466 EXPECT(walker.Down()); |
| 1467 EXPECT_STREQ("secondInit", walker.CurrentName()); |
| 1468 EXPECT(walker.Down()); |
| 1469 EXPECT_STREQ("init", walker.CurrentName()); |
| 1470 EXPECT(walker.Down()); |
| 1471 EXPECT_STREQ("go", walker.CurrentName()); |
| 1472 EXPECT(walker.Down()); |
| 1473 EXPECT_STREQ("main", walker.CurrentName()); |
| 1474 EXPECT(!walker.Down()); |
| 1475 } |
| 1476 } |
| 1477 |
1341 } // namespace dart | 1478 } // namespace dart |
1342 | 1479 |
OLD | NEW |