| 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" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 DisableNativeProfileScope() : FLAG_profile_vm_(FLAG_profile_vm) { | 27 DisableNativeProfileScope() : FLAG_profile_vm_(FLAG_profile_vm) { |
| 28 FLAG_profile_vm = false; | 28 FLAG_profile_vm = false; |
| 29 } | 29 } |
| 30 | 30 |
| 31 ~DisableNativeProfileScope() { FLAG_profile_vm = FLAG_profile_vm_; } | 31 ~DisableNativeProfileScope() { FLAG_profile_vm = FLAG_profile_vm_; } |
| 32 | 32 |
| 33 private: | 33 private: |
| 34 const bool FLAG_profile_vm_; | 34 const bool FLAG_profile_vm_; |
| 35 }; | 35 }; |
| 36 | 36 |
| 37 | |
| 38 class DisableBackgroundCompilationScope : public ValueObject { | 37 class DisableBackgroundCompilationScope : public ValueObject { |
| 39 public: | 38 public: |
| 40 DisableBackgroundCompilationScope() | 39 DisableBackgroundCompilationScope() |
| 41 : FLAG_background_compilation_(FLAG_background_compilation) { | 40 : FLAG_background_compilation_(FLAG_background_compilation) { |
| 42 FLAG_background_compilation = false; | 41 FLAG_background_compilation = false; |
| 43 } | 42 } |
| 44 | 43 |
| 45 ~DisableBackgroundCompilationScope() { | 44 ~DisableBackgroundCompilationScope() { |
| 46 FLAG_background_compilation = FLAG_background_compilation_; | 45 FLAG_background_compilation = FLAG_background_compilation_; |
| 47 } | 46 } |
| 48 | 47 |
| 49 private: | 48 private: |
| 50 const bool FLAG_background_compilation_; | 49 const bool FLAG_background_compilation_; |
| 51 }; | 50 }; |
| 52 | 51 |
| 53 | |
| 54 // Temporarily adjust the maximum profile depth. | 52 // Temporarily adjust the maximum profile depth. |
| 55 class MaxProfileDepthScope : public ValueObject { | 53 class MaxProfileDepthScope : public ValueObject { |
| 56 public: | 54 public: |
| 57 explicit MaxProfileDepthScope(intptr_t new_max_depth) | 55 explicit MaxProfileDepthScope(intptr_t new_max_depth) |
| 58 : FLAG_max_profile_depth_(FLAG_max_profile_depth) { | 56 : FLAG_max_profile_depth_(FLAG_max_profile_depth) { |
| 59 Profiler::SetSampleDepth(new_max_depth); | 57 Profiler::SetSampleDepth(new_max_depth); |
| 60 } | 58 } |
| 61 | 59 |
| 62 ~MaxProfileDepthScope() { Profiler::SetSampleDepth(FLAG_max_profile_depth_); } | 60 ~MaxProfileDepthScope() { Profiler::SetSampleDepth(FLAG_max_profile_depth_); } |
| 63 | 61 |
| 64 private: | 62 private: |
| 65 const intptr_t FLAG_max_profile_depth_; | 63 const intptr_t FLAG_max_profile_depth_; |
| 66 }; | 64 }; |
| 67 | 65 |
| 68 | |
| 69 class ProfileSampleBufferTestHelper { | 66 class ProfileSampleBufferTestHelper { |
| 70 public: | 67 public: |
| 71 static intptr_t IterateCount(const Dart_Port port, | 68 static intptr_t IterateCount(const Dart_Port port, |
| 72 const SampleBuffer& sample_buffer) { | 69 const SampleBuffer& sample_buffer) { |
| 73 intptr_t c = 0; | 70 intptr_t c = 0; |
| 74 for (intptr_t i = 0; i < sample_buffer.capacity(); i++) { | 71 for (intptr_t i = 0; i < sample_buffer.capacity(); i++) { |
| 75 Sample* sample = sample_buffer.At(i); | 72 Sample* sample = sample_buffer.At(i); |
| 76 if (sample->port() != port) { | 73 if (sample->port() != port) { |
| 77 continue; | 74 continue; |
| 78 } | 75 } |
| 79 c++; | 76 c++; |
| 80 } | 77 } |
| 81 return c; | 78 return c; |
| 82 } | 79 } |
| 83 | 80 |
| 84 | |
| 85 static intptr_t IterateSumPC(const Dart_Port port, | 81 static intptr_t IterateSumPC(const Dart_Port port, |
| 86 const SampleBuffer& sample_buffer) { | 82 const SampleBuffer& sample_buffer) { |
| 87 intptr_t c = 0; | 83 intptr_t c = 0; |
| 88 for (intptr_t i = 0; i < sample_buffer.capacity(); i++) { | 84 for (intptr_t i = 0; i < sample_buffer.capacity(); i++) { |
| 89 Sample* sample = sample_buffer.At(i); | 85 Sample* sample = sample_buffer.At(i); |
| 90 if (sample->port() != port) { | 86 if (sample->port() != port) { |
| 91 continue; | 87 continue; |
| 92 } | 88 } |
| 93 c += sample->At(0); | 89 c += sample->At(0); |
| 94 } | 90 } |
| 95 return c; | 91 return c; |
| 96 } | 92 } |
| 97 }; | 93 }; |
| 98 | 94 |
| 99 | |
| 100 TEST_CASE(Profiler_SampleBufferWrapTest) { | 95 TEST_CASE(Profiler_SampleBufferWrapTest) { |
| 101 SampleBuffer* sample_buffer = new SampleBuffer(3); | 96 SampleBuffer* sample_buffer = new SampleBuffer(3); |
| 102 Dart_Port i = 123; | 97 Dart_Port i = 123; |
| 103 EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); | 98 EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); |
| 104 Sample* s; | 99 Sample* s; |
| 105 s = sample_buffer->ReserveSample(); | 100 s = sample_buffer->ReserveSample(); |
| 106 s->Init(i, 0, 0); | 101 s->Init(i, 0, 0); |
| 107 s->SetAt(0, 2); | 102 s->SetAt(0, 2); |
| 108 EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); | 103 EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); |
| 109 s = sample_buffer->ReserveSample(); | 104 s = sample_buffer->ReserveSample(); |
| 110 s->Init(i, 0, 0); | 105 s->Init(i, 0, 0); |
| 111 s->SetAt(0, 4); | 106 s->SetAt(0, 4); |
| 112 EXPECT_EQ(6, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); | 107 EXPECT_EQ(6, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); |
| 113 s = sample_buffer->ReserveSample(); | 108 s = sample_buffer->ReserveSample(); |
| 114 s->Init(i, 0, 0); | 109 s->Init(i, 0, 0); |
| 115 s->SetAt(0, 6); | 110 s->SetAt(0, 6); |
| 116 EXPECT_EQ(12, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); | 111 EXPECT_EQ(12, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); |
| 117 s = sample_buffer->ReserveSample(); | 112 s = sample_buffer->ReserveSample(); |
| 118 s->Init(i, 0, 0); | 113 s->Init(i, 0, 0); |
| 119 s->SetAt(0, 8); | 114 s->SetAt(0, 8); |
| 120 EXPECT_EQ(18, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); | 115 EXPECT_EQ(18, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer)); |
| 121 delete sample_buffer; | 116 delete sample_buffer; |
| 122 } | 117 } |
| 123 | 118 |
| 124 | |
| 125 TEST_CASE(Profiler_SampleBufferIterateTest) { | 119 TEST_CASE(Profiler_SampleBufferIterateTest) { |
| 126 SampleBuffer* sample_buffer = new SampleBuffer(3); | 120 SampleBuffer* sample_buffer = new SampleBuffer(3); |
| 127 Dart_Port i = 123; | 121 Dart_Port i = 123; |
| 128 EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); | 122 EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); |
| 129 Sample* s; | 123 Sample* s; |
| 130 s = sample_buffer->ReserveSample(); | 124 s = sample_buffer->ReserveSample(); |
| 131 s->Init(i, 0, 0); | 125 s->Init(i, 0, 0); |
| 132 EXPECT_EQ(1, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); | 126 EXPECT_EQ(1, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); |
| 133 s = sample_buffer->ReserveSample(); | 127 s = sample_buffer->ReserveSample(); |
| 134 s->Init(i, 0, 0); | 128 s->Init(i, 0, 0); |
| 135 EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); | 129 EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); |
| 136 s = sample_buffer->ReserveSample(); | 130 s = sample_buffer->ReserveSample(); |
| 137 s->Init(i, 0, 0); | 131 s->Init(i, 0, 0); |
| 138 EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); | 132 EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); |
| 139 s = sample_buffer->ReserveSample(); | 133 s = sample_buffer->ReserveSample(); |
| 140 s->Init(i, 0, 0); | 134 s->Init(i, 0, 0); |
| 141 EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); | 135 EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer)); |
| 142 delete sample_buffer; | 136 delete sample_buffer; |
| 143 } | 137 } |
| 144 | 138 |
| 145 | |
| 146 TEST_CASE(Profiler_AllocationSampleTest) { | 139 TEST_CASE(Profiler_AllocationSampleTest) { |
| 147 Isolate* isolate = Isolate::Current(); | 140 Isolate* isolate = Isolate::Current(); |
| 148 SampleBuffer* sample_buffer = new SampleBuffer(3); | 141 SampleBuffer* sample_buffer = new SampleBuffer(3); |
| 149 Sample* sample = sample_buffer->ReserveSample(); | 142 Sample* sample = sample_buffer->ReserveSample(); |
| 150 sample->Init(isolate->main_port(), 0, 0); | 143 sample->Init(isolate->main_port(), 0, 0); |
| 151 sample->set_metadata(99); | 144 sample->set_metadata(99); |
| 152 sample->set_is_allocation_sample(true); | 145 sample->set_is_allocation_sample(true); |
| 153 EXPECT_EQ(99, sample->allocation_cid()); | 146 EXPECT_EQ(99, sample->allocation_cid()); |
| 154 delete sample_buffer; | 147 delete sample_buffer; |
| 155 } | 148 } |
| 156 | 149 |
| 157 | |
| 158 static RawClass* GetClass(const Library& lib, const char* name) { | 150 static RawClass* GetClass(const Library& lib, const char* name) { |
| 159 const Class& cls = Class::Handle(lib.LookupClassAllowPrivate( | 151 const Class& cls = Class::Handle(lib.LookupClassAllowPrivate( |
| 160 String::Handle(Symbols::New(Thread::Current(), name)))); | 152 String::Handle(Symbols::New(Thread::Current(), name)))); |
| 161 EXPECT(!cls.IsNull()); // No ambiguity error expected. | 153 EXPECT(!cls.IsNull()); // No ambiguity error expected. |
| 162 return cls.raw(); | 154 return cls.raw(); |
| 163 } | 155 } |
| 164 | 156 |
| 165 | |
| 166 static RawFunction* GetFunction(const Library& lib, const char* name) { | 157 static RawFunction* GetFunction(const Library& lib, const char* name) { |
| 167 const Function& func = Function::Handle(lib.LookupFunctionAllowPrivate( | 158 const Function& func = Function::Handle(lib.LookupFunctionAllowPrivate( |
| 168 String::Handle(Symbols::New(Thread::Current(), name)))); | 159 String::Handle(Symbols::New(Thread::Current(), name)))); |
| 169 EXPECT(!func.IsNull()); // No ambiguity error expected. | 160 EXPECT(!func.IsNull()); // No ambiguity error expected. |
| 170 return func.raw(); | 161 return func.raw(); |
| 171 } | 162 } |
| 172 | 163 |
| 173 | |
| 174 class AllocationFilter : public SampleFilter { | 164 class AllocationFilter : public SampleFilter { |
| 175 public: | 165 public: |
| 176 AllocationFilter(Dart_Port port, | 166 AllocationFilter(Dart_Port port, |
| 177 intptr_t cid, | 167 intptr_t cid, |
| 178 int64_t time_origin_micros = -1, | 168 int64_t time_origin_micros = -1, |
| 179 int64_t time_extent_micros = -1) | 169 int64_t time_extent_micros = -1) |
| 180 : SampleFilter(port, | 170 : SampleFilter(port, |
| 181 Thread::kMutatorTask, | 171 Thread::kMutatorTask, |
| 182 time_origin_micros, | 172 time_origin_micros, |
| 183 time_extent_micros), | 173 time_extent_micros), |
| 184 cid_(cid), | 174 cid_(cid), |
| 185 enable_vm_ticks_(false) {} | 175 enable_vm_ticks_(false) {} |
| 186 | 176 |
| 187 bool FilterSample(Sample* sample) { | 177 bool FilterSample(Sample* sample) { |
| 188 if (!enable_vm_ticks_ && (sample->vm_tag() == VMTag::kVMTagId)) { | 178 if (!enable_vm_ticks_ && (sample->vm_tag() == VMTag::kVMTagId)) { |
| 189 // We don't want to see embedder ticks in the test. | 179 // We don't want to see embedder ticks in the test. |
| 190 return false; | 180 return false; |
| 191 } | 181 } |
| 192 return sample->is_allocation_sample() && (sample->allocation_cid() == cid_); | 182 return sample->is_allocation_sample() && (sample->allocation_cid() == cid_); |
| 193 } | 183 } |
| 194 | 184 |
| 195 void set_enable_vm_ticks(bool enable) { enable_vm_ticks_ = enable; } | 185 void set_enable_vm_ticks(bool enable) { enable_vm_ticks_ = enable; } |
| 196 | 186 |
| 197 private: | 187 private: |
| 198 intptr_t cid_; | 188 intptr_t cid_; |
| 199 bool enable_vm_ticks_; | 189 bool enable_vm_ticks_; |
| 200 }; | 190 }; |
| 201 | 191 |
| 202 | |
| 203 TEST_CASE(Profiler_TrivialRecordAllocation) { | 192 TEST_CASE(Profiler_TrivialRecordAllocation) { |
| 204 DisableNativeProfileScope dnps; | 193 DisableNativeProfileScope dnps; |
| 205 const char* kScript = | 194 const char* kScript = |
| 206 "class A {\n" | 195 "class A {\n" |
| 207 " var a;\n" | 196 " var a;\n" |
| 208 " var b;\n" | 197 " var b;\n" |
| 209 "}\n" | 198 "}\n" |
| 210 "class B {\n" | 199 "class B {\n" |
| 211 " static boo() {\n" | 200 " static boo() {\n" |
| 212 " return new A();\n" | 201 " return new A();\n" |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 } | 306 } |
| 318 | 307 |
| 319 #if defined(DART_USE_TCMALLOC) && defined(HOST_OS_LINUX) && defined(DEBUG) && \ | 308 #if defined(DART_USE_TCMALLOC) && defined(HOST_OS_LINUX) && defined(DEBUG) && \ |
| 320 defined(HOST_ARCH_x64) | 309 defined(HOST_ARCH_x64) |
| 321 | 310 |
| 322 DART_NOINLINE static void NativeAllocationSampleHelper(char** result) { | 311 DART_NOINLINE static void NativeAllocationSampleHelper(char** result) { |
| 323 ASSERT(result != NULL); | 312 ASSERT(result != NULL); |
| 324 *result = static_cast<char*>(malloc(sizeof(char) * 1024)); | 313 *result = static_cast<char*>(malloc(sizeof(char) * 1024)); |
| 325 } | 314 } |
| 326 | 315 |
| 327 | |
| 328 ISOLATE_UNIT_TEST_CASE(Profiler_NativeAllocation) { | 316 ISOLATE_UNIT_TEST_CASE(Profiler_NativeAllocation) { |
| 329 bool enable_malloc_hooks_saved = FLAG_profiler_native_memory; | 317 bool enable_malloc_hooks_saved = FLAG_profiler_native_memory; |
| 330 FLAG_profiler_native_memory = true; | 318 FLAG_profiler_native_memory = true; |
| 331 | 319 |
| 332 MallocHooks::InitOnce(); | 320 MallocHooks::InitOnce(); |
| 333 MallocHooks::ResetStats(); | 321 MallocHooks::ResetStats(); |
| 334 bool stack_trace_collection_enabled = | 322 bool stack_trace_collection_enabled = |
| 335 MallocHooks::stack_trace_collection_enabled(); | 323 MallocHooks::stack_trace_collection_enabled(); |
| 336 MallocHooks::set_stack_trace_collection_enabled(true); | 324 MallocHooks::set_stack_trace_collection_enabled(true); |
| 337 | 325 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 } | 508 } |
| 521 | 509 |
| 522 MallocHooks::set_stack_trace_collection_enabled( | 510 MallocHooks::set_stack_trace_collection_enabled( |
| 523 stack_trace_collection_enabled); | 511 stack_trace_collection_enabled); |
| 524 MallocHooks::TearDown(); | 512 MallocHooks::TearDown(); |
| 525 FLAG_profiler_native_memory = enable_malloc_hooks_saved; | 513 FLAG_profiler_native_memory = enable_malloc_hooks_saved; |
| 526 } | 514 } |
| 527 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && | 515 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && |
| 528 // !defined(TARGET_ARCH_DBC) && !defined(HOST_OS_FUCHSIA) | 516 // !defined(TARGET_ARCH_DBC) && !defined(HOST_OS_FUCHSIA) |
| 529 | 517 |
| 530 | |
| 531 TEST_CASE(Profiler_ToggleRecordAllocation) { | 518 TEST_CASE(Profiler_ToggleRecordAllocation) { |
| 532 DisableNativeProfileScope dnps; | 519 DisableNativeProfileScope dnps; |
| 533 const char* kScript = | 520 const char* kScript = |
| 534 "class A {\n" | 521 "class A {\n" |
| 535 " var a;\n" | 522 " var a;\n" |
| 536 " var b;\n" | 523 " var b;\n" |
| 537 "}\n" | 524 "}\n" |
| 538 "class B {\n" | 525 "class B {\n" |
| 539 " static boo() {\n" | 526 " static boo() {\n" |
| 540 " return new A();\n" | 527 " return new A();\n" |
| 541 " }\n" | 528 " }\n" |
| 542 "}\n" | 529 "}\n" |
| 543 "main() {\n" | 530 "main() {\n" |
| 544 " return B.boo();\n" | 531 " return B.boo();\n" |
| 545 "}\n"; | 532 "}\n"; |
| 546 | 533 |
| 547 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 534 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 548 EXPECT_VALID(lib); | 535 EXPECT_VALID(lib); |
| 549 Library& root_library = Library::Handle(); | 536 Library& root_library = Library::Handle(); |
| 550 root_library ^= Api::UnwrapHandle(lib); | 537 root_library ^= Api::UnwrapHandle(lib); |
| 551 | 538 |
| 552 const Class& class_a = Class::Handle(GetClass(root_library, "A")); | 539 const Class& class_a = Class::Handle(GetClass(root_library, "A")); |
| 553 EXPECT(!class_a.IsNull()); | 540 EXPECT(!class_a.IsNull()); |
| 554 | 541 |
| 555 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 542 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
| 556 EXPECT_VALID(result); | 543 EXPECT_VALID(result); |
| 557 | 544 |
| 558 | |
| 559 { | 545 { |
| 560 Thread* thread = Thread::Current(); | 546 Thread* thread = Thread::Current(); |
| 561 Isolate* isolate = thread->isolate(); | 547 Isolate* isolate = thread->isolate(); |
| 562 StackZone zone(thread); | 548 StackZone zone(thread); |
| 563 HANDLESCOPE(thread); | 549 HANDLESCOPE(thread); |
| 564 Profile profile(isolate); | 550 Profile profile(isolate); |
| 565 AllocationFilter filter(isolate->main_port(), class_a.id()); | 551 AllocationFilter filter(isolate->main_port(), class_a.id()); |
| 566 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 552 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 567 // We should have no allocation samples. | 553 // We should have no allocation samples. |
| 568 EXPECT_EQ(0, profile.sample_count()); | 554 EXPECT_EQ(0, profile.sample_count()); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 StackZone zone(thread); | 637 StackZone zone(thread); |
| 652 HANDLESCOPE(thread); | 638 HANDLESCOPE(thread); |
| 653 Profile profile(isolate); | 639 Profile profile(isolate); |
| 654 AllocationFilter filter(isolate->main_port(), class_a.id()); | 640 AllocationFilter filter(isolate->main_port(), class_a.id()); |
| 655 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 641 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 656 // We should still only have one allocation sample. | 642 // We should still only have one allocation sample. |
| 657 EXPECT_EQ(1, profile.sample_count()); | 643 EXPECT_EQ(1, profile.sample_count()); |
| 658 } | 644 } |
| 659 } | 645 } |
| 660 | 646 |
| 661 | |
| 662 TEST_CASE(Profiler_CodeTicks) { | 647 TEST_CASE(Profiler_CodeTicks) { |
| 663 DisableNativeProfileScope dnps; | 648 DisableNativeProfileScope dnps; |
| 664 const char* kScript = | 649 const char* kScript = |
| 665 "class A {\n" | 650 "class A {\n" |
| 666 " var a;\n" | 651 " var a;\n" |
| 667 " var b;\n" | 652 " var b;\n" |
| 668 "}\n" | 653 "}\n" |
| 669 "class B {\n" | 654 "class B {\n" |
| 670 " static boo() {\n" | 655 " static boo() {\n" |
| 671 " return new A();\n" | 656 " return new A();\n" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 EXPECT_EQ(3, walker.CurrentInclusiveTicks()); | 739 EXPECT_EQ(3, walker.CurrentInclusiveTicks()); |
| 755 EXPECT(walker.Down()); | 740 EXPECT(walker.Down()); |
| 756 EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName()); | 741 EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName()); |
| 757 EXPECT_EQ(3, walker.CurrentExclusiveTicks()); | 742 EXPECT_EQ(3, walker.CurrentExclusiveTicks()); |
| 758 EXPECT(walker.Down()); | 743 EXPECT(walker.Down()); |
| 759 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); | 744 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); |
| 760 EXPECT(!walker.Down()); | 745 EXPECT(!walker.Down()); |
| 761 } | 746 } |
| 762 } | 747 } |
| 763 | 748 |
| 764 | |
| 765 TEST_CASE(Profiler_FunctionTicks) { | 749 TEST_CASE(Profiler_FunctionTicks) { |
| 766 DisableNativeProfileScope dnps; | 750 DisableNativeProfileScope dnps; |
| 767 const char* kScript = | 751 const char* kScript = |
| 768 "class A {\n" | 752 "class A {\n" |
| 769 " var a;\n" | 753 " var a;\n" |
| 770 " var b;\n" | 754 " var b;\n" |
| 771 "}\n" | 755 "}\n" |
| 772 "class B {\n" | 756 "class B {\n" |
| 773 " static boo() {\n" | 757 " static boo() {\n" |
| 774 " return new A();\n" | 758 " return new A();\n" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 EXPECT_EQ(3, walker.CurrentInclusiveTicks()); | 841 EXPECT_EQ(3, walker.CurrentInclusiveTicks()); |
| 858 EXPECT(walker.Down()); | 842 EXPECT(walker.Down()); |
| 859 EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName()); | 843 EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName()); |
| 860 EXPECT_EQ(3, walker.CurrentExclusiveTicks()); | 844 EXPECT_EQ(3, walker.CurrentExclusiveTicks()); |
| 861 EXPECT(walker.Down()); | 845 EXPECT(walker.Down()); |
| 862 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); | 846 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); |
| 863 EXPECT(!walker.Down()); | 847 EXPECT(!walker.Down()); |
| 864 } | 848 } |
| 865 } | 849 } |
| 866 | 850 |
| 867 | |
| 868 TEST_CASE(Profiler_IntrinsicAllocation) { | 851 TEST_CASE(Profiler_IntrinsicAllocation) { |
| 869 DisableNativeProfileScope dnps; | 852 DisableNativeProfileScope dnps; |
| 870 const char* kScript = "double foo(double a, double b) => a + b;"; | 853 const char* kScript = "double foo(double a, double b) => a + b;"; |
| 871 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 854 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 872 EXPECT_VALID(lib); | 855 EXPECT_VALID(lib); |
| 873 Library& root_library = Library::Handle(); | 856 Library& root_library = Library::Handle(); |
| 874 root_library ^= Api::UnwrapHandle(lib); | 857 root_library ^= Api::UnwrapHandle(lib); |
| 875 Isolate* isolate = thread->isolate(); | 858 Isolate* isolate = thread->isolate(); |
| 876 | 859 |
| 877 const Class& double_class = | 860 const Class& double_class = |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 StackZone zone(thread); | 912 StackZone zone(thread); |
| 930 HANDLESCOPE(thread); | 913 HANDLESCOPE(thread); |
| 931 Profile profile(isolate); | 914 Profile profile(isolate); |
| 932 AllocationFilter filter(isolate->main_port(), double_class.id()); | 915 AllocationFilter filter(isolate->main_port(), double_class.id()); |
| 933 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 916 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 934 // We should still only have one allocation sample. | 917 // We should still only have one allocation sample. |
| 935 EXPECT_EQ(1, profile.sample_count()); | 918 EXPECT_EQ(1, profile.sample_count()); |
| 936 } | 919 } |
| 937 } | 920 } |
| 938 | 921 |
| 939 | |
| 940 TEST_CASE(Profiler_ArrayAllocation) { | 922 TEST_CASE(Profiler_ArrayAllocation) { |
| 941 DisableNativeProfileScope dnps; | 923 DisableNativeProfileScope dnps; |
| 942 const char* kScript = | 924 const char* kScript = |
| 943 "List foo() => new List(4);\n" | 925 "List foo() => new List(4);\n" |
| 944 "List bar() => new List();\n"; | 926 "List bar() => new List();\n"; |
| 945 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 927 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 946 EXPECT_VALID(lib); | 928 EXPECT_VALID(lib); |
| 947 Library& root_library = Library::Handle(); | 929 Library& root_library = Library::Handle(); |
| 948 root_library ^= Api::UnwrapHandle(lib); | 930 root_library ^= Api::UnwrapHandle(lib); |
| 949 Isolate* isolate = thread->isolate(); | 931 Isolate* isolate = thread->isolate(); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 HANDLESCOPE(thread); | 1008 HANDLESCOPE(thread); |
| 1027 Profile profile(isolate); | 1009 Profile profile(isolate); |
| 1028 AllocationFilter filter(isolate->main_port(), array_class.id()); | 1010 AllocationFilter filter(isolate->main_port(), array_class.id()); |
| 1029 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 1011 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 1030 // We should have no allocation samples, since empty | 1012 // We should have no allocation samples, since empty |
| 1031 // growable lists use a shared backing. | 1013 // growable lists use a shared backing. |
| 1032 EXPECT_EQ(0, profile.sample_count()); | 1014 EXPECT_EQ(0, profile.sample_count()); |
| 1033 } | 1015 } |
| 1034 } | 1016 } |
| 1035 | 1017 |
| 1036 | |
| 1037 TEST_CASE(Profiler_ContextAllocation) { | 1018 TEST_CASE(Profiler_ContextAllocation) { |
| 1038 DisableNativeProfileScope dnps; | 1019 DisableNativeProfileScope dnps; |
| 1039 const char* kScript = | 1020 const char* kScript = |
| 1040 "var msg1 = 'a';\n" | 1021 "var msg1 = 'a';\n" |
| 1041 "foo() {\n" | 1022 "foo() {\n" |
| 1042 " var msg = msg1 + msg1;\n" | 1023 " var msg = msg1 + msg1;\n" |
| 1043 " return (x) { return '$msg + $msg'; }(msg);\n" | 1024 " return (x) { return '$msg + $msg'; }(msg);\n" |
| 1044 "}\n"; | 1025 "}\n"; |
| 1045 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 1026 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 1046 EXPECT_VALID(lib); | 1027 EXPECT_VALID(lib); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1096 StackZone zone(thread); | 1077 StackZone zone(thread); |
| 1097 HANDLESCOPE(thread); | 1078 HANDLESCOPE(thread); |
| 1098 Profile profile(isolate); | 1079 Profile profile(isolate); |
| 1099 AllocationFilter filter(isolate->main_port(), context_class.id()); | 1080 AllocationFilter filter(isolate->main_port(), context_class.id()); |
| 1100 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 1081 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 1101 // We should still only have one allocation sample. | 1082 // We should still only have one allocation sample. |
| 1102 EXPECT_EQ(1, profile.sample_count()); | 1083 EXPECT_EQ(1, profile.sample_count()); |
| 1103 } | 1084 } |
| 1104 } | 1085 } |
| 1105 | 1086 |
| 1106 | |
| 1107 TEST_CASE(Profiler_ClosureAllocation) { | 1087 TEST_CASE(Profiler_ClosureAllocation) { |
| 1108 DisableNativeProfileScope dnps; | 1088 DisableNativeProfileScope dnps; |
| 1109 const char* kScript = | 1089 const char* kScript = |
| 1110 "var msg1 = 'a';\n" | 1090 "var msg1 = 'a';\n" |
| 1111 "\n" | 1091 "\n" |
| 1112 "foo() {\n" | 1092 "foo() {\n" |
| 1113 " var msg = msg1 + msg1;\n" | 1093 " var msg = msg1 + msg1;\n" |
| 1114 " var msg2 = msg + msg;\n" | 1094 " var msg2 = msg + msg;\n" |
| 1115 " return (x, y, z, w) { return '$x + $y + $z'; }(msg, msg2, msg, msg);\n" | 1095 " return (x, y, z, w) { return '$x + $y + $z'; }(msg, msg2, msg, msg);\n" |
| 1116 "}\n" | 1096 "}\n" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 HANDLESCOPE(thread); | 1148 HANDLESCOPE(thread); |
| 1169 Profile profile(isolate); | 1149 Profile profile(isolate); |
| 1170 AllocationFilter filter(isolate->main_port(), closure_class.id()); | 1150 AllocationFilter filter(isolate->main_port(), closure_class.id()); |
| 1171 filter.set_enable_vm_ticks(true); | 1151 filter.set_enable_vm_ticks(true); |
| 1172 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 1152 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 1173 // We should still only have one allocation sample. | 1153 // We should still only have one allocation sample. |
| 1174 EXPECT_EQ(1, profile.sample_count()); | 1154 EXPECT_EQ(1, profile.sample_count()); |
| 1175 } | 1155 } |
| 1176 } | 1156 } |
| 1177 | 1157 |
| 1178 | |
| 1179 TEST_CASE(Profiler_TypedArrayAllocation) { | 1158 TEST_CASE(Profiler_TypedArrayAllocation) { |
| 1180 DisableNativeProfileScope dnps; | 1159 DisableNativeProfileScope dnps; |
| 1181 const char* kScript = | 1160 const char* kScript = |
| 1182 "import 'dart:typed_data';\n" | 1161 "import 'dart:typed_data';\n" |
| 1183 "List foo() => new Float32List(4);\n"; | 1162 "List foo() => new Float32List(4);\n"; |
| 1184 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 1163 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 1185 EXPECT_VALID(lib); | 1164 EXPECT_VALID(lib); |
| 1186 Library& root_library = Library::Handle(); | 1165 Library& root_library = Library::Handle(); |
| 1187 root_library ^= Api::UnwrapHandle(lib); | 1166 root_library ^= Api::UnwrapHandle(lib); |
| 1188 Isolate* isolate = thread->isolate(); | 1167 Isolate* isolate = thread->isolate(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1253 StackZone zone(thread); | 1232 StackZone zone(thread); |
| 1254 HANDLESCOPE(thread); | 1233 HANDLESCOPE(thread); |
| 1255 Profile profile(isolate); | 1234 Profile profile(isolate); |
| 1256 AllocationFilter filter(isolate->main_port(), float32_list_class.id()); | 1235 AllocationFilter filter(isolate->main_port(), float32_list_class.id()); |
| 1257 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 1236 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 1258 // We should now have two allocation samples. | 1237 // We should now have two allocation samples. |
| 1259 EXPECT_EQ(2, profile.sample_count()); | 1238 EXPECT_EQ(2, profile.sample_count()); |
| 1260 } | 1239 } |
| 1261 } | 1240 } |
| 1262 | 1241 |
| 1263 | |
| 1264 TEST_CASE(Profiler_StringAllocation) { | 1242 TEST_CASE(Profiler_StringAllocation) { |
| 1265 DisableNativeProfileScope dnps; | 1243 DisableNativeProfileScope dnps; |
| 1266 const char* kScript = "String foo(String a, String b) => a + b;"; | 1244 const char* kScript = "String foo(String a, String b) => a + b;"; |
| 1267 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 1245 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 1268 EXPECT_VALID(lib); | 1246 EXPECT_VALID(lib); |
| 1269 Library& root_library = Library::Handle(); | 1247 Library& root_library = Library::Handle(); |
| 1270 root_library ^= Api::UnwrapHandle(lib); | 1248 root_library ^= Api::UnwrapHandle(lib); |
| 1271 Isolate* isolate = thread->isolate(); | 1249 Isolate* isolate = thread->isolate(); |
| 1272 | 1250 |
| 1273 const Class& one_byte_string_class = | 1251 const Class& one_byte_string_class = |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 StackZone zone(thread); | 1317 StackZone zone(thread); |
| 1340 HANDLESCOPE(thread); | 1318 HANDLESCOPE(thread); |
| 1341 Profile profile(isolate); | 1319 Profile profile(isolate); |
| 1342 AllocationFilter filter(isolate->main_port(), one_byte_string_class.id()); | 1320 AllocationFilter filter(isolate->main_port(), one_byte_string_class.id()); |
| 1343 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 1321 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 1344 // We should now have two allocation samples. | 1322 // We should now have two allocation samples. |
| 1345 EXPECT_EQ(2, profile.sample_count()); | 1323 EXPECT_EQ(2, profile.sample_count()); |
| 1346 } | 1324 } |
| 1347 } | 1325 } |
| 1348 | 1326 |
| 1349 | |
| 1350 TEST_CASE(Profiler_StringInterpolation) { | 1327 TEST_CASE(Profiler_StringInterpolation) { |
| 1351 DisableNativeProfileScope dnps; | 1328 DisableNativeProfileScope dnps; |
| 1352 DisableBackgroundCompilationScope dbcs; | 1329 DisableBackgroundCompilationScope dbcs; |
| 1353 const char* kScript = "String foo(String a, String b) => '$a | $b';"; | 1330 const char* kScript = "String foo(String a, String b) => '$a | $b';"; |
| 1354 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 1331 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
| 1355 EXPECT_VALID(lib); | 1332 EXPECT_VALID(lib); |
| 1356 Library& root_library = Library::Handle(); | 1333 Library& root_library = Library::Handle(); |
| 1357 root_library ^= Api::UnwrapHandle(lib); | 1334 root_library ^= Api::UnwrapHandle(lib); |
| 1358 Isolate* isolate = thread->isolate(); | 1335 Isolate* isolate = thread->isolate(); |
| 1359 | 1336 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1428 StackZone zone(thread); | 1405 StackZone zone(thread); |
| 1429 HANDLESCOPE(thread); | 1406 HANDLESCOPE(thread); |
| 1430 Profile profile(isolate); | 1407 Profile profile(isolate); |
| 1431 AllocationFilter filter(isolate->main_port(), one_byte_string_class.id()); | 1408 AllocationFilter filter(isolate->main_port(), one_byte_string_class.id()); |
| 1432 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 1409 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 1433 // We should now have two allocation samples. | 1410 // We should now have two allocation samples. |
| 1434 EXPECT_EQ(2, profile.sample_count()); | 1411 EXPECT_EQ(2, profile.sample_count()); |
| 1435 } | 1412 } |
| 1436 } | 1413 } |
| 1437 | 1414 |
| 1438 | |
| 1439 TEST_CASE(Profiler_FunctionInline) { | 1415 TEST_CASE(Profiler_FunctionInline) { |
| 1440 DisableNativeProfileScope dnps; | 1416 DisableNativeProfileScope dnps; |
| 1441 DisableBackgroundCompilationScope dbcs; | 1417 DisableBackgroundCompilationScope dbcs; |
| 1442 | 1418 |
| 1443 const char* kScript = | 1419 const char* kScript = |
| 1444 "class A {\n" | 1420 "class A {\n" |
| 1445 " var a;\n" | 1421 " var a;\n" |
| 1446 " var b;\n" | 1422 " var b;\n" |
| 1447 "}\n" | 1423 "}\n" |
| 1448 "class B {\n" | 1424 "class B {\n" |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1713 EXPECT(walker.Down()); | 1689 EXPECT(walker.Down()); |
| 1714 EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName()); | 1690 EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName()); |
| 1715 EXPECT(walker.Down()); | 1691 EXPECT(walker.Down()); |
| 1716 EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName()); | 1692 EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName()); |
| 1717 EXPECT(walker.Down()); | 1693 EXPECT(walker.Down()); |
| 1718 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); | 1694 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); |
| 1719 EXPECT(!walker.Down()); | 1695 EXPECT(!walker.Down()); |
| 1720 } | 1696 } |
| 1721 } | 1697 } |
| 1722 | 1698 |
| 1723 | |
| 1724 TEST_CASE(Profiler_InliningIntervalBoundry) { | 1699 TEST_CASE(Profiler_InliningIntervalBoundry) { |
| 1725 // The PC of frames below the top frame is a call's return address, | 1700 // The PC of frames below the top frame is a call's return address, |
| 1726 // which can belong to a different inlining interval than the call. | 1701 // which can belong to a different inlining interval than the call. |
| 1727 // This test checks the profiler service takes this into account; see | 1702 // This test checks the profiler service takes this into account; see |
| 1728 // ProfileBuilder::ProcessFrame. | 1703 // ProfileBuilder::ProcessFrame. |
| 1729 | 1704 |
| 1730 DisableNativeProfileScope dnps; | 1705 DisableNativeProfileScope dnps; |
| 1731 DisableBackgroundCompilationScope dbcs; | 1706 DisableBackgroundCompilationScope dbcs; |
| 1732 const char* kScript = | 1707 const char* kScript = |
| 1733 "class A {\n" | 1708 "class A {\n" |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1850 EXPECT(walker.Down()); | 1825 EXPECT(walker.Down()); |
| 1851 EXPECT_STREQ("maybeAlloc", walker.CurrentName()); | 1826 EXPECT_STREQ("maybeAlloc", walker.CurrentName()); |
| 1852 EXPECT(walker.Down()); | 1827 EXPECT(walker.Down()); |
| 1853 EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName()); | 1828 EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName()); |
| 1854 EXPECT(walker.Down()); | 1829 EXPECT(walker.Down()); |
| 1855 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); | 1830 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); |
| 1856 EXPECT(!walker.Down()); | 1831 EXPECT(!walker.Down()); |
| 1857 } | 1832 } |
| 1858 } | 1833 } |
| 1859 | 1834 |
| 1860 | |
| 1861 TEST_CASE(Profiler_ChainedSamples) { | 1835 TEST_CASE(Profiler_ChainedSamples) { |
| 1862 MaxProfileDepthScope mpds(32); | 1836 MaxProfileDepthScope mpds(32); |
| 1863 DisableNativeProfileScope dnps; | 1837 DisableNativeProfileScope dnps; |
| 1864 | 1838 |
| 1865 // Each sample holds 8 stack frames. | 1839 // Each sample holds 8 stack frames. |
| 1866 // This chain is 20 stack frames deep. | 1840 // This chain is 20 stack frames deep. |
| 1867 const char* kScript = | 1841 const char* kScript = |
| 1868 "class A {\n" | 1842 "class A {\n" |
| 1869 " var a;\n" | 1843 " var a;\n" |
| 1870 " var b;\n" | 1844 " var b;\n" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1901 Library& root_library = Library::Handle(); | 1875 Library& root_library = Library::Handle(); |
| 1902 root_library ^= Api::UnwrapHandle(lib); | 1876 root_library ^= Api::UnwrapHandle(lib); |
| 1903 | 1877 |
| 1904 const Class& class_a = Class::Handle(GetClass(root_library, "A")); | 1878 const Class& class_a = Class::Handle(GetClass(root_library, "A")); |
| 1905 EXPECT(!class_a.IsNull()); | 1879 EXPECT(!class_a.IsNull()); |
| 1906 class_a.SetTraceAllocation(true); | 1880 class_a.SetTraceAllocation(true); |
| 1907 | 1881 |
| 1908 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); | 1882 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
| 1909 EXPECT_VALID(result); | 1883 EXPECT_VALID(result); |
| 1910 | 1884 |
| 1911 | |
| 1912 { | 1885 { |
| 1913 Thread* thread = Thread::Current(); | 1886 Thread* thread = Thread::Current(); |
| 1914 Isolate* isolate = thread->isolate(); | 1887 Isolate* isolate = thread->isolate(); |
| 1915 StackZone zone(thread); | 1888 StackZone zone(thread); |
| 1916 HANDLESCOPE(thread); | 1889 HANDLESCOPE(thread); |
| 1917 Profile profile(isolate); | 1890 Profile profile(isolate); |
| 1918 AllocationFilter filter(isolate->main_port(), class_a.id()); | 1891 AllocationFilter filter(isolate->main_port(), class_a.id()); |
| 1919 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); | 1892 profile.Build(thread, &filter, Profiler::sample_buffer(), Profile::kNoTags); |
| 1920 // We should have 1 allocation sample. | 1893 // We should have 1 allocation sample. |
| 1921 EXPECT_EQ(1, profile.sample_count()); | 1894 EXPECT_EQ(1, profile.sample_count()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1964 EXPECT(walker.Down()); | 1937 EXPECT(walker.Down()); |
| 1965 EXPECT_STREQ("init", walker.CurrentName()); | 1938 EXPECT_STREQ("init", walker.CurrentName()); |
| 1966 EXPECT(walker.Down()); | 1939 EXPECT(walker.Down()); |
| 1967 EXPECT_STREQ("go", walker.CurrentName()); | 1940 EXPECT_STREQ("go", walker.CurrentName()); |
| 1968 EXPECT(walker.Down()); | 1941 EXPECT(walker.Down()); |
| 1969 EXPECT_STREQ("main", walker.CurrentName()); | 1942 EXPECT_STREQ("main", walker.CurrentName()); |
| 1970 EXPECT(!walker.Down()); | 1943 EXPECT(!walker.Down()); |
| 1971 } | 1944 } |
| 1972 } | 1945 } |
| 1973 | 1946 |
| 1974 | |
| 1975 TEST_CASE(Profiler_BasicSourcePosition) { | 1947 TEST_CASE(Profiler_BasicSourcePosition) { |
| 1976 DisableNativeProfileScope dnps; | 1948 DisableNativeProfileScope dnps; |
| 1977 DisableBackgroundCompilationScope dbcs; | 1949 DisableBackgroundCompilationScope dbcs; |
| 1978 const char* kScript = | 1950 const char* kScript = |
| 1979 "const AlwaysInline = 'AlwaysInline';\n" | 1951 "const AlwaysInline = 'AlwaysInline';\n" |
| 1980 "const NeverInline = 'NeverInline';\n" | 1952 "const NeverInline = 'NeverInline';\n" |
| 1981 "class A {\n" | 1953 "class A {\n" |
| 1982 " var a;\n" | 1954 " var a;\n" |
| 1983 " var b;\n" | 1955 " var b;\n" |
| 1984 " @NeverInline A() { }\n" | 1956 " @NeverInline A() { }\n" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2039 EXPECT(walker.Down()); | 2011 EXPECT(walker.Down()); |
| 2040 EXPECT_STREQ("main", walker.CurrentName()); | 2012 EXPECT_STREQ("main", walker.CurrentName()); |
| 2041 EXPECT_EQ(1, walker.CurrentNodeTickCount()); | 2013 EXPECT_EQ(1, walker.CurrentNodeTickCount()); |
| 2042 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); | 2014 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); |
| 2043 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); | 2015 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); |
| 2044 EXPECT_STREQ("boo", walker.CurrentToken()); | 2016 EXPECT_STREQ("boo", walker.CurrentToken()); |
| 2045 EXPECT(!walker.Down()); | 2017 EXPECT(!walker.Down()); |
| 2046 } | 2018 } |
| 2047 } | 2019 } |
| 2048 | 2020 |
| 2049 | |
| 2050 TEST_CASE(Profiler_BasicSourcePositionOptimized) { | 2021 TEST_CASE(Profiler_BasicSourcePositionOptimized) { |
| 2051 DisableNativeProfileScope dnps; | 2022 DisableNativeProfileScope dnps; |
| 2052 DisableBackgroundCompilationScope dbcs; | 2023 DisableBackgroundCompilationScope dbcs; |
| 2053 // We use the AlwaysInline and NeverInline annotations in this test. | 2024 // We use the AlwaysInline and NeverInline annotations in this test. |
| 2054 SetFlagScope<bool> sfs(&FLAG_enable_inlining_annotations, true); | 2025 SetFlagScope<bool> sfs(&FLAG_enable_inlining_annotations, true); |
| 2055 // Optimize quickly. | 2026 // Optimize quickly. |
| 2056 SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5); | 2027 SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5); |
| 2057 const char* kScript = | 2028 const char* kScript = |
| 2058 "const AlwaysInline = 'AlwaysInline';\n" | 2029 "const AlwaysInline = 'AlwaysInline';\n" |
| 2059 "const NeverInline = 'NeverInline';\n" | 2030 "const NeverInline = 'NeverInline';\n" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2133 EXPECT(walker.Down()); | 2104 EXPECT(walker.Down()); |
| 2134 EXPECT_STREQ("main", walker.CurrentName()); | 2105 EXPECT_STREQ("main", walker.CurrentName()); |
| 2135 EXPECT_EQ(1, walker.CurrentNodeTickCount()); | 2106 EXPECT_EQ(1, walker.CurrentNodeTickCount()); |
| 2136 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); | 2107 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); |
| 2137 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); | 2108 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); |
| 2138 EXPECT_STREQ("boo", walker.CurrentToken()); | 2109 EXPECT_STREQ("boo", walker.CurrentToken()); |
| 2139 EXPECT(!walker.Down()); | 2110 EXPECT(!walker.Down()); |
| 2140 } | 2111 } |
| 2141 } | 2112 } |
| 2142 | 2113 |
| 2143 | |
| 2144 TEST_CASE(Profiler_SourcePosition) { | 2114 TEST_CASE(Profiler_SourcePosition) { |
| 2145 DisableNativeProfileScope dnps; | 2115 DisableNativeProfileScope dnps; |
| 2146 DisableBackgroundCompilationScope dbcs; | 2116 DisableBackgroundCompilationScope dbcs; |
| 2147 const char* kScript = | 2117 const char* kScript = |
| 2148 "const AlwaysInline = 'AlwaysInline';\n" | 2118 "const AlwaysInline = 'AlwaysInline';\n" |
| 2149 "const NeverInline = 'NeverInline';\n" | 2119 "const NeverInline = 'NeverInline';\n" |
| 2150 "class A {\n" | 2120 "class A {\n" |
| 2151 " var a;\n" | 2121 " var a;\n" |
| 2152 " var b;\n" | 2122 " var b;\n" |
| 2153 " @NeverInline A() { }\n" | 2123 " @NeverInline A() { }\n" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2238 EXPECT(walker.Down()); | 2208 EXPECT(walker.Down()); |
| 2239 EXPECT_STREQ("main", walker.CurrentName()); | 2209 EXPECT_STREQ("main", walker.CurrentName()); |
| 2240 EXPECT_EQ(1, walker.CurrentNodeTickCount()); | 2210 EXPECT_EQ(1, walker.CurrentNodeTickCount()); |
| 2241 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); | 2211 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); |
| 2242 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); | 2212 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); |
| 2243 EXPECT_STREQ("bacon", walker.CurrentToken()); | 2213 EXPECT_STREQ("bacon", walker.CurrentToken()); |
| 2244 EXPECT(!walker.Down()); | 2214 EXPECT(!walker.Down()); |
| 2245 } | 2215 } |
| 2246 } | 2216 } |
| 2247 | 2217 |
| 2248 | |
| 2249 TEST_CASE(Profiler_SourcePositionOptimized) { | 2218 TEST_CASE(Profiler_SourcePositionOptimized) { |
| 2250 DisableNativeProfileScope dnps; | 2219 DisableNativeProfileScope dnps; |
| 2251 DisableBackgroundCompilationScope dbcs; | 2220 DisableBackgroundCompilationScope dbcs; |
| 2252 // We use the AlwaysInline and NeverInline annotations in this test. | 2221 // We use the AlwaysInline and NeverInline annotations in this test. |
| 2253 SetFlagScope<bool> sfs(&FLAG_enable_inlining_annotations, true); | 2222 SetFlagScope<bool> sfs(&FLAG_enable_inlining_annotations, true); |
| 2254 // Optimize quickly. | 2223 // Optimize quickly. |
| 2255 SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5); | 2224 SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5); |
| 2256 | 2225 |
| 2257 const char* kScript = | 2226 const char* kScript = |
| 2258 "const AlwaysInline = 'AlwaysInline';\n" | 2227 "const AlwaysInline = 'AlwaysInline';\n" |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2363 EXPECT(walker.Down()); | 2332 EXPECT(walker.Down()); |
| 2364 EXPECT_STREQ("main", walker.CurrentName()); | 2333 EXPECT_STREQ("main", walker.CurrentName()); |
| 2365 EXPECT_EQ(1, walker.CurrentNodeTickCount()); | 2334 EXPECT_EQ(1, walker.CurrentNodeTickCount()); |
| 2366 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); | 2335 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); |
| 2367 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); | 2336 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); |
| 2368 EXPECT_STREQ("bacon", walker.CurrentToken()); | 2337 EXPECT_STREQ("bacon", walker.CurrentToken()); |
| 2369 EXPECT(!walker.Down()); | 2338 EXPECT(!walker.Down()); |
| 2370 } | 2339 } |
| 2371 } | 2340 } |
| 2372 | 2341 |
| 2373 | |
| 2374 TEST_CASE(Profiler_BinaryOperatorSourcePosition) { | 2342 TEST_CASE(Profiler_BinaryOperatorSourcePosition) { |
| 2375 DisableNativeProfileScope dnps; | 2343 DisableNativeProfileScope dnps; |
| 2376 DisableBackgroundCompilationScope dbcs; | 2344 DisableBackgroundCompilationScope dbcs; |
| 2377 const char* kScript = | 2345 const char* kScript = |
| 2378 "const AlwaysInline = 'AlwaysInline';\n" | 2346 "const AlwaysInline = 'AlwaysInline';\n" |
| 2379 "const NeverInline = 'NeverInline';\n" | 2347 "const NeverInline = 'NeverInline';\n" |
| 2380 "class A {\n" | 2348 "class A {\n" |
| 2381 " var a;\n" | 2349 " var a;\n" |
| 2382 " var b;\n" | 2350 " var b;\n" |
| 2383 " @NeverInline A() { }\n" | 2351 " @NeverInline A() { }\n" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2477 EXPECT(walker.Down()); | 2445 EXPECT(walker.Down()); |
| 2478 EXPECT_STREQ("main", walker.CurrentName()); | 2446 EXPECT_STREQ("main", walker.CurrentName()); |
| 2479 EXPECT_EQ(1, walker.CurrentNodeTickCount()); | 2447 EXPECT_EQ(1, walker.CurrentNodeTickCount()); |
| 2480 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); | 2448 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); |
| 2481 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); | 2449 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); |
| 2482 EXPECT_STREQ("bacon", walker.CurrentToken()); | 2450 EXPECT_STREQ("bacon", walker.CurrentToken()); |
| 2483 EXPECT(!walker.Down()); | 2451 EXPECT(!walker.Down()); |
| 2484 } | 2452 } |
| 2485 } | 2453 } |
| 2486 | 2454 |
| 2487 | |
| 2488 TEST_CASE(Profiler_BinaryOperatorSourcePositionOptimized) { | 2455 TEST_CASE(Profiler_BinaryOperatorSourcePositionOptimized) { |
| 2489 DisableNativeProfileScope dnps; | 2456 DisableNativeProfileScope dnps; |
| 2490 DisableBackgroundCompilationScope dbcs; | 2457 DisableBackgroundCompilationScope dbcs; |
| 2491 // We use the AlwaysInline and NeverInline annotations in this test. | 2458 // We use the AlwaysInline and NeverInline annotations in this test. |
| 2492 SetFlagScope<bool> sfs(&FLAG_enable_inlining_annotations, true); | 2459 SetFlagScope<bool> sfs(&FLAG_enable_inlining_annotations, true); |
| 2493 // Optimize quickly. | 2460 // Optimize quickly. |
| 2494 SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5); | 2461 SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5); |
| 2495 | 2462 |
| 2496 const char* kScript = | 2463 const char* kScript = |
| 2497 "const AlwaysInline = 'AlwaysInline';\n" | 2464 "const AlwaysInline = 'AlwaysInline';\n" |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2611 EXPECT(walker.Down()); | 2578 EXPECT(walker.Down()); |
| 2612 EXPECT_STREQ("main", walker.CurrentName()); | 2579 EXPECT_STREQ("main", walker.CurrentName()); |
| 2613 EXPECT_EQ(1, walker.CurrentNodeTickCount()); | 2580 EXPECT_EQ(1, walker.CurrentNodeTickCount()); |
| 2614 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); | 2581 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); |
| 2615 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); | 2582 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); |
| 2616 EXPECT_STREQ("bacon", walker.CurrentToken()); | 2583 EXPECT_STREQ("bacon", walker.CurrentToken()); |
| 2617 EXPECT(!walker.Down()); | 2584 EXPECT(!walker.Down()); |
| 2618 } | 2585 } |
| 2619 } | 2586 } |
| 2620 | 2587 |
| 2621 | |
| 2622 static void InsertFakeSample(SampleBuffer* sample_buffer, uword* pc_offsets) { | 2588 static void InsertFakeSample(SampleBuffer* sample_buffer, uword* pc_offsets) { |
| 2623 ASSERT(sample_buffer != NULL); | 2589 ASSERT(sample_buffer != NULL); |
| 2624 Isolate* isolate = Isolate::Current(); | 2590 Isolate* isolate = Isolate::Current(); |
| 2625 Sample* sample = sample_buffer->ReserveSample(); | 2591 Sample* sample = sample_buffer->ReserveSample(); |
| 2626 ASSERT(sample != NULL); | 2592 ASSERT(sample != NULL); |
| 2627 sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), | 2593 sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), |
| 2628 OSThread::Current()->trace_id()); | 2594 OSThread::Current()->trace_id()); |
| 2629 sample->set_thread_task(Thread::kMutatorTask); | 2595 sample->set_thread_task(Thread::kMutatorTask); |
| 2630 | 2596 |
| 2631 intptr_t i = 0; | 2597 intptr_t i = 0; |
| 2632 while (pc_offsets[i] != 0) { | 2598 while (pc_offsets[i] != 0) { |
| 2633 // When we collect a real stack trace, all PCs collected aside from the | 2599 // When we collect a real stack trace, all PCs collected aside from the |
| 2634 // executing one (i == 0) are actually return addresses. Return addresses | 2600 // executing one (i == 0) are actually return addresses. Return addresses |
| 2635 // are one byte beyond the call instruction that is executing. The profiler | 2601 // are one byte beyond the call instruction that is executing. The profiler |
| 2636 // accounts for this and subtracts one from these addresses when querying | 2602 // accounts for this and subtracts one from these addresses when querying |
| 2637 // inline and token position ranges. To be consistent with real stack | 2603 // inline and token position ranges. To be consistent with real stack |
| 2638 // traces, we add one byte to all PCs except the executing one. | 2604 // traces, we add one byte to all PCs except the executing one. |
| 2639 // See OffsetForPC in profiler_service.cc for more context. | 2605 // See OffsetForPC in profiler_service.cc for more context. |
| 2640 const intptr_t return_address_offset = i > 0 ? 1 : 0; | 2606 const intptr_t return_address_offset = i > 0 ? 1 : 0; |
| 2641 sample->SetAt(i, pc_offsets[i] + return_address_offset); | 2607 sample->SetAt(i, pc_offsets[i] + return_address_offset); |
| 2642 i++; | 2608 i++; |
| 2643 } | 2609 } |
| 2644 sample->SetAt(i, 0); | 2610 sample->SetAt(i, 0); |
| 2645 } | 2611 } |
| 2646 | 2612 |
| 2647 | 2613 static uword FindPCForTokenPosition(const Code& code, TokenPosition tp) { |
| 2648 static uword FindPCForTokenPosition(const Code& code, | |
| 2649 TokenPosition tp) { | |
| 2650 GrowableArray<const Function*> functions; | 2614 GrowableArray<const Function*> functions; |
| 2651 GrowableArray<TokenPosition> token_positions; | 2615 GrowableArray<TokenPosition> token_positions; |
| 2652 for (intptr_t pc_offset = 0; pc_offset < code.Size(); pc_offset++) { | 2616 for (intptr_t pc_offset = 0; pc_offset < code.Size(); pc_offset++) { |
| 2653 code.GetInlinedFunctionsAtInstruction(pc_offset, &functions, | 2617 code.GetInlinedFunctionsAtInstruction(pc_offset, &functions, |
| 2654 &token_positions); | 2618 &token_positions); |
| 2655 if (token_positions[0] == tp) { | 2619 if (token_positions[0] == tp) { |
| 2656 return code.PayloadStart() + pc_offset; | 2620 return code.PayloadStart() + pc_offset; |
| 2657 } | 2621 } |
| 2658 } | 2622 } |
| 2659 | 2623 |
| 2660 return 0; | 2624 return 0; |
| 2661 } | 2625 } |
| 2662 | 2626 |
| 2663 | |
| 2664 TEST_CASE(Profiler_GetSourceReport) { | 2627 TEST_CASE(Profiler_GetSourceReport) { |
| 2665 const char* kScript = | 2628 const char* kScript = |
| 2666 "doWork(i) => i * i;\n" | 2629 "doWork(i) => i * i;\n" |
| 2667 "main() {\n" | 2630 "main() {\n" |
| 2668 " var sum = 0;\n" | 2631 " var sum = 0;\n" |
| 2669 " for (var i = 0; i < 100; i++) {\n" | 2632 " for (var i = 0; i < 100; i++) {\n" |
| 2670 " sum += doWork(i);\n" | 2633 " sum += doWork(i);\n" |
| 2671 " }\n" | 2634 " }\n" |
| 2672 " return sum;\n" | 2635 " return sum;\n" |
| 2673 "}\n"; | 2636 "}\n"; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2787 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); | 2750 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); |
| 2788 | 2751 |
| 2789 // Verify positions in main. | 2752 // Verify positions in main. |
| 2790 EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString()); | 2753 EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString()); |
| 2791 // Verify exclusive ticks in main. | 2754 // Verify exclusive ticks in main. |
| 2792 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString()); | 2755 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString()); |
| 2793 // Verify inclusive ticks in main. | 2756 // Verify inclusive ticks in main. |
| 2794 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); | 2757 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); |
| 2795 } | 2758 } |
| 2796 | 2759 |
| 2797 | |
| 2798 TEST_CASE(Profiler_ProfileCodeTableTest) { | 2760 TEST_CASE(Profiler_ProfileCodeTableTest) { |
| 2799 Zone* Z = Thread::Current()->zone(); | 2761 Zone* Z = Thread::Current()->zone(); |
| 2800 | 2762 |
| 2801 ProfileCodeTable* table = new (Z) ProfileCodeTable(); | 2763 ProfileCodeTable* table = new (Z) ProfileCodeTable(); |
| 2802 EXPECT_EQ(table->length(), 0); | 2764 EXPECT_EQ(table->length(), 0); |
| 2803 EXPECT_EQ(table->FindCodeForPC(42), static_cast<ProfileCode*>(NULL)); | 2765 EXPECT_EQ(table->FindCodeForPC(42), static_cast<ProfileCode*>(NULL)); |
| 2804 | 2766 |
| 2805 int64_t timestamp = 0; | 2767 int64_t timestamp = 0; |
| 2806 Code& null_code = Code::Handle(Z); | 2768 Code& null_code = Code::Handle(Z); |
| 2807 | 2769 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2896 EXPECT_EQ(table->FindCodeForPC(45), code1); // Merged right. | 2858 EXPECT_EQ(table->FindCodeForPC(45), code1); // Merged right. |
| 2897 EXPECT_EQ(table->FindCodeForPC(54), code1); // Merged right. | 2859 EXPECT_EQ(table->FindCodeForPC(54), code1); // Merged right. |
| 2898 EXPECT_EQ(table->FindCodeForPC(20), code2); // Merged left. | 2860 EXPECT_EQ(table->FindCodeForPC(20), code2); // Merged left. |
| 2899 EXPECT_EQ(table->FindCodeForPC(49), code1); // Truncated. | 2861 EXPECT_EQ(table->FindCodeForPC(49), code1); // Truncated. |
| 2900 EXPECT_EQ(table->FindCodeForPC(50), code1); | 2862 EXPECT_EQ(table->FindCodeForPC(50), code1); |
| 2901 } | 2863 } |
| 2902 | 2864 |
| 2903 #endif // !PRODUCT | 2865 #endif // !PRODUCT |
| 2904 | 2866 |
| 2905 } // namespace dart | 2867 } // namespace dart |
| OLD | NEW |