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 |