| 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 |