| 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); |
| 17 |
| 18 // Some tests are written assuming native stack trace profiling is disabled. |
| 19 class DisableNativeProfileScope { |
| 20 DisableNativeProfileScope() |
| 21 : FLAG_profile_vm_(FLAG_profile_vm) { |
| 22 FLAG_profile_vm = false; |
| 23 } |
| 24 |
| 25 ~DisableNativeProfileScope() { |
| 26 FLAG_profile_vm = FLAG_profile_vm_; |
| 27 } |
| 28 |
| 29 private: |
| 30 bool FLAG_profile_vm_; |
| 31 }; |
| 32 |
| 33 |
| 16 class ProfileSampleBufferTestHelper { | 34 class ProfileSampleBufferTestHelper { |
| 17 public: | 35 public: |
| 18 static intptr_t IterateCount(const Isolate* isolate, | 36 static intptr_t IterateCount(const Isolate* isolate, |
| 19 const SampleBuffer& sample_buffer) { | 37 const SampleBuffer& sample_buffer) { |
| 20 intptr_t c = 0; | 38 intptr_t c = 0; |
| 21 for (intptr_t i = 0; i < sample_buffer.capacity(); i++) { | 39 for (intptr_t i = 0; i < sample_buffer.capacity(); i++) { |
| 22 Sample* sample = sample_buffer.At(i); | 40 Sample* sample = sample_buffer.At(i); |
| 23 if (sample->isolate() != isolate) { | 41 if (sample->isolate() != isolate) { |
| 24 continue; | 42 continue; |
| 25 } | 43 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 bool FilterSample(Sample* sample) { | 137 bool FilterSample(Sample* sample) { |
| 120 return sample->is_allocation_sample() && (sample->allocation_cid() == cid_); | 138 return sample->is_allocation_sample() && (sample->allocation_cid() == cid_); |
| 121 } | 139 } |
| 122 | 140 |
| 123 private: | 141 private: |
| 124 intptr_t cid_; | 142 intptr_t cid_; |
| 125 }; | 143 }; |
| 126 | 144 |
| 127 | 145 |
| 128 TEST_CASE(Profiler_TrivialRecordAllocation) { | 146 TEST_CASE(Profiler_TrivialRecordAllocation) { |
| 147 DisableNativeProfileScope dnps; |
| 129 const char* kScript = | 148 const char* kScript = |
| 130 "class A {\n" | 149 "class A {\n" |
| 131 " var a;\n" | 150 " var a;\n" |
| 132 " var b;\n" | 151 " var b;\n" |
| 133 "}\n" | 152 "}\n" |
| 134 "class B {\n" | 153 "class B {\n" |
| 135 " static boo() {\n" | 154 " static boo() {\n" |
| 136 " return new A();\n" | 155 " return new A();\n" |
| 137 " }\n" | 156 " }\n" |
| 138 "}\n" | 157 "}\n" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 EXPECT(walker.Down()); | 216 EXPECT(walker.Down()); |
| 198 EXPECT_STREQ("main", walker.CurrentName()); | 217 EXPECT_STREQ("main", walker.CurrentName()); |
| 199 EXPECT(walker.Down()); | 218 EXPECT(walker.Down()); |
| 200 EXPECT_STREQ("B.boo", walker.CurrentName()); | 219 EXPECT_STREQ("B.boo", walker.CurrentName()); |
| 201 EXPECT(!walker.Down()); | 220 EXPECT(!walker.Down()); |
| 202 } | 221 } |
| 203 } | 222 } |
| 204 | 223 |
| 205 | 224 |
| 206 TEST_CASE(Profiler_ToggleRecordAllocation) { | 225 TEST_CASE(Profiler_ToggleRecordAllocation) { |
| 226 DisableNativeProfileScope dnps; |
| 207 const char* kScript = | 227 const char* kScript = |
| 208 "class A {\n" | 228 "class A {\n" |
| 209 " var a;\n" | 229 " var a;\n" |
| 210 " var b;\n" | 230 " var b;\n" |
| 211 "}\n" | 231 "}\n" |
| 212 "class B {\n" | 232 "class B {\n" |
| 213 " static boo() {\n" | 233 " static boo() {\n" |
| 214 " return new A();\n" | 234 " return new A();\n" |
| 215 " }\n" | 235 " }\n" |
| 216 "}\n" | 236 "}\n" |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 Profile profile(isolate); | 328 Profile profile(isolate); |
| 309 AllocationFilter filter(isolate, class_a.id()); | 329 AllocationFilter filter(isolate, class_a.id()); |
| 310 profile.Build(&filter, Profile::kNoTags); | 330 profile.Build(&filter, Profile::kNoTags); |
| 311 // We should still only have one allocation sample. | 331 // We should still only have one allocation sample. |
| 312 EXPECT_EQ(1, profile.sample_count()); | 332 EXPECT_EQ(1, profile.sample_count()); |
| 313 } | 333 } |
| 314 } | 334 } |
| 315 | 335 |
| 316 | 336 |
| 317 TEST_CASE(Profiler_CodeTicks) { | 337 TEST_CASE(Profiler_CodeTicks) { |
| 338 DisableNativeProfileScope dnps; |
| 318 const char* kScript = | 339 const char* kScript = |
| 319 "class A {\n" | 340 "class A {\n" |
| 320 " var a;\n" | 341 " var a;\n" |
| 321 " var b;\n" | 342 " var b;\n" |
| 322 "}\n" | 343 "}\n" |
| 323 "class B {\n" | 344 "class B {\n" |
| 324 " static boo() {\n" | 345 " static boo() {\n" |
| 325 " return new A();\n" | 346 " return new A();\n" |
| 326 " }\n" | 347 " }\n" |
| 327 "}\n" | 348 "}\n" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 EXPECT_STREQ("B.boo", walker.CurrentName()); | 421 EXPECT_STREQ("B.boo", walker.CurrentName()); |
| 401 EXPECT_EQ(3, walker.CurrentNodeTickCount()); | 422 EXPECT_EQ(3, walker.CurrentNodeTickCount()); |
| 402 EXPECT_EQ(3, walker.CurrentInclusiveTicks()); | 423 EXPECT_EQ(3, walker.CurrentInclusiveTicks()); |
| 403 EXPECT_EQ(3, walker.CurrentExclusiveTicks()); | 424 EXPECT_EQ(3, walker.CurrentExclusiveTicks()); |
| 404 EXPECT(!walker.Down()); | 425 EXPECT(!walker.Down()); |
| 405 } | 426 } |
| 406 } | 427 } |
| 407 | 428 |
| 408 | 429 |
| 409 TEST_CASE(Profiler_FunctionTicks) { | 430 TEST_CASE(Profiler_FunctionTicks) { |
| 431 DisableNativeProfileScope dnps; |
| 410 const char* kScript = | 432 const char* kScript = |
| 411 "class A {\n" | 433 "class A {\n" |
| 412 " var a;\n" | 434 " var a;\n" |
| 413 " var b;\n" | 435 " var b;\n" |
| 414 "}\n" | 436 "}\n" |
| 415 "class B {\n" | 437 "class B {\n" |
| 416 " static boo() {\n" | 438 " static boo() {\n" |
| 417 " return new A();\n" | 439 " return new A();\n" |
| 418 " }\n" | 440 " }\n" |
| 419 "}\n" | 441 "}\n" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 EXPECT_STREQ("B.boo", walker.CurrentName()); | 514 EXPECT_STREQ("B.boo", walker.CurrentName()); |
| 493 EXPECT_EQ(3, walker.CurrentNodeTickCount()); | 515 EXPECT_EQ(3, walker.CurrentNodeTickCount()); |
| 494 EXPECT_EQ(3, walker.CurrentInclusiveTicks()); | 516 EXPECT_EQ(3, walker.CurrentInclusiveTicks()); |
| 495 EXPECT_EQ(3, walker.CurrentExclusiveTicks()); | 517 EXPECT_EQ(3, walker.CurrentExclusiveTicks()); |
| 496 EXPECT(!walker.Down()); | 518 EXPECT(!walker.Down()); |
| 497 } | 519 } |
| 498 } | 520 } |
| 499 | 521 |
| 500 | 522 |
| 501 TEST_CASE(Profiler_IntrinsicAllocation) { | 523 TEST_CASE(Profiler_IntrinsicAllocation) { |
| 524 DisableNativeProfileScope dnps; |
| 502 const char* kScript = "double foo(double a, double b) => a + b;"; | 525 const char* kScript = "double foo(double a, double b) => a + b;"; |
| 503 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 526 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 504 EXPECT_VALID(lib); | 527 EXPECT_VALID(lib); |
| 505 Library& root_library = Library::Handle(); | 528 Library& root_library = Library::Handle(); |
| 506 root_library ^= Api::UnwrapHandle(lib); | 529 root_library ^= Api::UnwrapHandle(lib); |
| 507 Isolate* isolate = Isolate::Current(); | 530 Isolate* isolate = Isolate::Current(); |
| 508 | 531 |
| 509 const Class& double_class = | 532 const Class& double_class = |
| 510 Class::Handle(isolate->object_store()->double_class()); | 533 Class::Handle(isolate->object_store()->double_class()); |
| 511 EXPECT(!double_class.IsNull()); | 534 EXPECT(!double_class.IsNull()); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 Profile profile(isolate); | 582 Profile profile(isolate); |
| 560 AllocationFilter filter(isolate, double_class.id()); | 583 AllocationFilter filter(isolate, double_class.id()); |
| 561 profile.Build(&filter, Profile::kNoTags); | 584 profile.Build(&filter, Profile::kNoTags); |
| 562 // We should still only have one allocation sample. | 585 // We should still only have one allocation sample. |
| 563 EXPECT_EQ(1, profile.sample_count()); | 586 EXPECT_EQ(1, profile.sample_count()); |
| 564 } | 587 } |
| 565 } | 588 } |
| 566 | 589 |
| 567 | 590 |
| 568 TEST_CASE(Profiler_ArrayAllocation) { | 591 TEST_CASE(Profiler_ArrayAllocation) { |
| 592 DisableNativeProfileScope dnps; |
| 569 const char* kScript = | 593 const char* kScript = |
| 570 "List foo() => new List(4);\n" | 594 "List foo() => new List(4);\n" |
| 571 "List bar() => new List();\n"; | 595 "List bar() => new List();\n"; |
| 572 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 596 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 573 EXPECT_VALID(lib); | 597 EXPECT_VALID(lib); |
| 574 Library& root_library = Library::Handle(); | 598 Library& root_library = Library::Handle(); |
| 575 root_library ^= Api::UnwrapHandle(lib); | 599 root_library ^= Api::UnwrapHandle(lib); |
| 576 Isolate* isolate = Isolate::Current(); | 600 Isolate* isolate = Isolate::Current(); |
| 577 | 601 |
| 578 const Class& array_class = | 602 const Class& array_class = |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 EXPECT(walker.Down()); | 686 EXPECT(walker.Down()); |
| 663 EXPECT_STREQ("List.List", walker.CurrentName()); | 687 EXPECT_STREQ("List.List", walker.CurrentName()); |
| 664 EXPECT(walker.Down()); | 688 EXPECT(walker.Down()); |
| 665 EXPECT_STREQ("bar", walker.CurrentName()); | 689 EXPECT_STREQ("bar", walker.CurrentName()); |
| 666 EXPECT(!walker.Down()); | 690 EXPECT(!walker.Down()); |
| 667 } | 691 } |
| 668 } | 692 } |
| 669 | 693 |
| 670 | 694 |
| 671 TEST_CASE(Profiler_TypedArrayAllocation) { | 695 TEST_CASE(Profiler_TypedArrayAllocation) { |
| 696 DisableNativeProfileScope dnps; |
| 672 const char* kScript = | 697 const char* kScript = |
| 673 "import 'dart:typed_data';\n" | 698 "import 'dart:typed_data';\n" |
| 674 "List foo() => new Float32List(4);\n"; | 699 "List foo() => new Float32List(4);\n"; |
| 675 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 700 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 676 EXPECT_VALID(lib); | 701 EXPECT_VALID(lib); |
| 677 Library& root_library = Library::Handle(); | 702 Library& root_library = Library::Handle(); |
| 678 root_library ^= Api::UnwrapHandle(lib); | 703 root_library ^= Api::UnwrapHandle(lib); |
| 679 Isolate* isolate = Isolate::Current(); | 704 Isolate* isolate = Isolate::Current(); |
| 680 | 705 |
| 681 const Library& typed_data_library = | 706 const Library& typed_data_library = |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 Profile profile(isolate); | 773 Profile profile(isolate); |
| 749 AllocationFilter filter(isolate, float32_list_class.id()); | 774 AllocationFilter filter(isolate, float32_list_class.id()); |
| 750 profile.Build(&filter, Profile::kNoTags); | 775 profile.Build(&filter, Profile::kNoTags); |
| 751 // We should now have two allocation samples. | 776 // We should now have two allocation samples. |
| 752 EXPECT_EQ(2, profile.sample_count()); | 777 EXPECT_EQ(2, profile.sample_count()); |
| 753 } | 778 } |
| 754 } | 779 } |
| 755 | 780 |
| 756 | 781 |
| 757 TEST_CASE(Profiler_StringAllocation) { | 782 TEST_CASE(Profiler_StringAllocation) { |
| 783 DisableNativeProfileScope dnps; |
| 758 const char* kScript = "String foo(String a, String b) => a + b;"; | 784 const char* kScript = "String foo(String a, String b) => a + b;"; |
| 759 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 785 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 760 EXPECT_VALID(lib); | 786 EXPECT_VALID(lib); |
| 761 Library& root_library = Library::Handle(); | 787 Library& root_library = Library::Handle(); |
| 762 root_library ^= Api::UnwrapHandle(lib); | 788 root_library ^= Api::UnwrapHandle(lib); |
| 763 Isolate* isolate = Isolate::Current(); | 789 Isolate* isolate = Isolate::Current(); |
| 764 | 790 |
| 765 const Class& one_byte_string_class = | 791 const Class& one_byte_string_class = |
| 766 Class::Handle(isolate->object_store()->one_byte_string_class()); | 792 Class::Handle(isolate->object_store()->one_byte_string_class()); |
| 767 EXPECT(!one_byte_string_class.IsNull()); | 793 EXPECT(!one_byte_string_class.IsNull()); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 Profile profile(isolate); | 853 Profile profile(isolate); |
| 828 AllocationFilter filter(isolate, one_byte_string_class.id()); | 854 AllocationFilter filter(isolate, one_byte_string_class.id()); |
| 829 profile.Build(&filter, Profile::kNoTags); | 855 profile.Build(&filter, Profile::kNoTags); |
| 830 // We should now have two allocation samples. | 856 // We should now have two allocation samples. |
| 831 EXPECT_EQ(2, profile.sample_count()); | 857 EXPECT_EQ(2, profile.sample_count()); |
| 832 } | 858 } |
| 833 } | 859 } |
| 834 | 860 |
| 835 | 861 |
| 836 TEST_CASE(Profiler_StringInterpolation) { | 862 TEST_CASE(Profiler_StringInterpolation) { |
| 863 DisableNativeProfileScope dnps; |
| 837 const char* kScript = "String foo(String a, String b) => '$a | $b';"; | 864 const char* kScript = "String foo(String a, String b) => '$a | $b';"; |
| 838 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 865 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 839 EXPECT_VALID(lib); | 866 EXPECT_VALID(lib); |
| 840 Library& root_library = Library::Handle(); | 867 Library& root_library = Library::Handle(); |
| 841 root_library ^= Api::UnwrapHandle(lib); | 868 root_library ^= Api::UnwrapHandle(lib); |
| 842 Isolate* isolate = Isolate::Current(); | 869 Isolate* isolate = Isolate::Current(); |
| 843 | 870 |
| 844 const Class& one_byte_string_class = | 871 const Class& one_byte_string_class = |
| 845 Class::Handle(isolate->object_store()->one_byte_string_class()); | 872 Class::Handle(isolate->object_store()->one_byte_string_class()); |
| 846 EXPECT(!one_byte_string_class.IsNull()); | 873 EXPECT(!one_byte_string_class.IsNull()); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 Profile profile(isolate); | 937 Profile profile(isolate); |
| 911 AllocationFilter filter(isolate, one_byte_string_class.id()); | 938 AllocationFilter filter(isolate, one_byte_string_class.id()); |
| 912 profile.Build(&filter, Profile::kNoTags); | 939 profile.Build(&filter, Profile::kNoTags); |
| 913 // We should now have two allocation samples. | 940 // We should now have two allocation samples. |
| 914 EXPECT_EQ(2, profile.sample_count()); | 941 EXPECT_EQ(2, profile.sample_count()); |
| 915 } | 942 } |
| 916 } | 943 } |
| 917 | 944 |
| 918 | 945 |
| 919 TEST_CASE(Profiler_FunctionInline) { | 946 TEST_CASE(Profiler_FunctionInline) { |
| 947 DisableNativeProfileScope dnps; |
| 920 const char* kScript = | 948 const char* kScript = |
| 921 "class A {\n" | 949 "class A {\n" |
| 922 " var a;\n" | 950 " var a;\n" |
| 923 " var b;\n" | 951 " var b;\n" |
| 924 "}\n" | 952 "}\n" |
| 925 "class B {\n" | 953 "class B {\n" |
| 926 " static choo(bool alloc) {\n" | 954 " static choo(bool alloc) {\n" |
| 927 " if (alloc) return new A();\n" | 955 " if (alloc) return new A();\n" |
| 928 " return alloc && alloc && !alloc;\n" | 956 " return alloc && alloc && !alloc;\n" |
| 929 " }\n" | 957 " }\n" |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1152 EXPECT(walker.Down()); | 1180 EXPECT(walker.Down()); |
| 1153 EXPECT_STREQ("B.choo", walker.CurrentName()); | 1181 EXPECT_STREQ("B.choo", walker.CurrentName()); |
| 1154 EXPECT(walker.Down()); | 1182 EXPECT(walker.Down()); |
| 1155 EXPECT_STREQ("[Inline End]", walker.CurrentName()); | 1183 EXPECT_STREQ("[Inline End]", walker.CurrentName()); |
| 1156 EXPECT(!walker.Down()); | 1184 EXPECT(!walker.Down()); |
| 1157 } | 1185 } |
| 1158 } | 1186 } |
| 1159 | 1187 |
| 1160 } // namespace dart | 1188 } // namespace dart |
| 1161 | 1189 |
| OLD | NEW |