OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/assert.h" | 5 #include "platform/assert.h" |
6 | 6 |
7 #include "vm/dart_api_impl.h" | 7 #include "vm/dart_api_impl.h" |
8 #include "vm/dart_api_state.h" | 8 #include "vm/dart_api_state.h" |
9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
10 #include "vm/profiler.h" | 10 #include "vm/profiler.h" |
11 #include "vm/profiler_service.h" | 11 #include "vm/profiler_service.h" |
12 #include "vm/source_report.h" | 12 #include "vm/source_report.h" |
13 #include "vm/unit_test.h" | 13 #include "vm/unit_test.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
17 #ifndef PRODUCT | 17 #ifndef PRODUCT |
18 | 18 |
19 DECLARE_FLAG(bool, profile_vm); | 19 DECLARE_FLAG(bool, profile_vm); |
20 DECLARE_FLAG(int, max_profile_depth); | 20 DECLARE_FLAG(int, max_profile_depth); |
21 DECLARE_FLAG(bool, enable_inlining_annotations); | 21 DECLARE_FLAG(bool, enable_inlining_annotations); |
22 DECLARE_FLAG(int, optimization_counter_threshold); | 22 DECLARE_FLAG(int, optimization_counter_threshold); |
23 | 23 |
24 // Some tests are written assuming native stack trace profiling is disabled. | 24 // Some tests are written assuming native stack trace profiling is disabled. |
25 class DisableNativeProfileScope : public ValueObject { | 25 class DisableNativeProfileScope : public ValueObject { |
26 public: | 26 public: |
27 DisableNativeProfileScope() | 27 DisableNativeProfileScope() : FLAG_profile_vm_(FLAG_profile_vm) { |
28 : FLAG_profile_vm_(FLAG_profile_vm) { | |
29 FLAG_profile_vm = false; | 28 FLAG_profile_vm = false; |
30 } | 29 } |
31 | 30 |
32 ~DisableNativeProfileScope() { | 31 ~DisableNativeProfileScope() { FLAG_profile_vm = FLAG_profile_vm_; } |
33 FLAG_profile_vm = FLAG_profile_vm_; | |
34 } | |
35 | 32 |
36 private: | 33 private: |
37 const bool FLAG_profile_vm_; | 34 const bool FLAG_profile_vm_; |
38 }; | 35 }; |
39 | 36 |
40 | 37 |
41 class DisableBackgroundCompilationScope : public ValueObject { | 38 class DisableBackgroundCompilationScope : public ValueObject { |
42 public: | 39 public: |
43 DisableBackgroundCompilationScope() | 40 DisableBackgroundCompilationScope() |
44 : FLAG_background_compilation_(FLAG_background_compilation) { | 41 : FLAG_background_compilation_(FLAG_background_compilation) { |
(...skipping 10 matching lines...) Expand all Loading... |
55 | 52 |
56 | 53 |
57 // Temporarily adjust the maximum profile depth. | 54 // Temporarily adjust the maximum profile depth. |
58 class MaxProfileDepthScope : public ValueObject { | 55 class MaxProfileDepthScope : public ValueObject { |
59 public: | 56 public: |
60 explicit MaxProfileDepthScope(intptr_t new_max_depth) | 57 explicit MaxProfileDepthScope(intptr_t new_max_depth) |
61 : FLAG_max_profile_depth_(FLAG_max_profile_depth) { | 58 : FLAG_max_profile_depth_(FLAG_max_profile_depth) { |
62 Profiler::SetSampleDepth(new_max_depth); | 59 Profiler::SetSampleDepth(new_max_depth); |
63 } | 60 } |
64 | 61 |
65 ~MaxProfileDepthScope() { | 62 ~MaxProfileDepthScope() { Profiler::SetSampleDepth(FLAG_max_profile_depth_); } |
66 Profiler::SetSampleDepth(FLAG_max_profile_depth_); | |
67 } | |
68 | 63 |
69 private: | 64 private: |
70 const intptr_t FLAG_max_profile_depth_; | 65 const intptr_t FLAG_max_profile_depth_; |
71 }; | 66 }; |
72 | 67 |
73 | 68 |
74 class ProfileSampleBufferTestHelper { | 69 class ProfileSampleBufferTestHelper { |
75 public: | 70 public: |
76 static intptr_t IterateCount(const Isolate* isolate, | 71 static intptr_t IterateCount(const Isolate* isolate, |
77 const SampleBuffer& sample_buffer) { | 72 const SampleBuffer& sample_buffer) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 Sample* sample = sample_buffer->ReserveSample(); | 149 Sample* sample = sample_buffer->ReserveSample(); |
155 sample->Init(isolate, 0, 0); | 150 sample->Init(isolate, 0, 0); |
156 sample->set_metadata(99); | 151 sample->set_metadata(99); |
157 sample->set_is_allocation_sample(true); | 152 sample->set_is_allocation_sample(true); |
158 EXPECT_EQ(99, sample->allocation_cid()); | 153 EXPECT_EQ(99, sample->allocation_cid()); |
159 delete sample_buffer; | 154 delete sample_buffer; |
160 } | 155 } |
161 | 156 |
162 | 157 |
163 static RawClass* GetClass(const Library& lib, const char* name) { | 158 static RawClass* GetClass(const Library& lib, const char* name) { |
164 const Class& cls = Class::Handle( | 159 const Class& cls = Class::Handle(lib.LookupClassAllowPrivate( |
165 lib.LookupClassAllowPrivate(String::Handle(Symbols::New(Thread::Current(), | 160 String::Handle(Symbols::New(Thread::Current(), name)))); |
166 name)))); | |
167 EXPECT(!cls.IsNull()); // No ambiguity error expected. | 161 EXPECT(!cls.IsNull()); // No ambiguity error expected. |
168 return cls.raw(); | 162 return cls.raw(); |
169 } | 163 } |
170 | 164 |
171 | 165 |
172 static RawFunction* GetFunction(const Library& lib, const char* name) { | 166 static RawFunction* GetFunction(const Library& lib, const char* name) { |
173 const Function& func = Function::Handle(lib.LookupFunctionAllowPrivate( | 167 const Function& func = Function::Handle(lib.LookupFunctionAllowPrivate( |
174 String::Handle(Symbols::New(Thread::Current(), name)))); | 168 String::Handle(Symbols::New(Thread::Current(), name)))); |
175 EXPECT(!func.IsNull()); // No ambiguity error expected. | 169 EXPECT(!func.IsNull()); // No ambiguity error expected. |
176 return func.raw(); | 170 return func.raw(); |
177 } | 171 } |
178 | 172 |
179 | 173 |
180 class AllocationFilter : public SampleFilter { | 174 class AllocationFilter : public SampleFilter { |
181 public: | 175 public: |
182 AllocationFilter(Isolate* isolate, | 176 AllocationFilter(Isolate* isolate, |
183 intptr_t cid, | 177 intptr_t cid, |
184 int64_t time_origin_micros = -1, | 178 int64_t time_origin_micros = -1, |
185 int64_t time_extent_micros = -1) | 179 int64_t time_extent_micros = -1) |
186 : SampleFilter(isolate, | 180 : SampleFilter(isolate, |
187 Thread::kMutatorTask, | 181 Thread::kMutatorTask, |
188 time_origin_micros, | 182 time_origin_micros, |
189 time_extent_micros), | 183 time_extent_micros), |
190 cid_(cid), | 184 cid_(cid), |
191 enable_vm_ticks_(false) { | 185 enable_vm_ticks_(false) {} |
192 } | |
193 | 186 |
194 bool FilterSample(Sample* sample) { | 187 bool FilterSample(Sample* sample) { |
195 if (!enable_vm_ticks_ && | 188 if (!enable_vm_ticks_ && (sample->vm_tag() == VMTag::kVMTagId)) { |
196 (sample->vm_tag() == VMTag::kVMTagId)) { | |
197 // We don't want to see embedder ticks in the test. | 189 // We don't want to see embedder ticks in the test. |
198 return false; | 190 return false; |
199 } | 191 } |
200 return sample->is_allocation_sample() && | 192 return sample->is_allocation_sample() && (sample->allocation_cid() == cid_); |
201 (sample->allocation_cid() == cid_); | |
202 } | 193 } |
203 | 194 |
204 void set_enable_vm_ticks(bool enable) { | 195 void set_enable_vm_ticks(bool enable) { enable_vm_ticks_ = enable; } |
205 enable_vm_ticks_ = enable; | |
206 } | |
207 | 196 |
208 private: | 197 private: |
209 intptr_t cid_; | 198 intptr_t cid_; |
210 bool enable_vm_ticks_; | 199 bool enable_vm_ticks_; |
211 }; | 200 }; |
212 | 201 |
213 | 202 |
214 TEST_CASE(Profiler_TrivialRecordAllocation) { | 203 TEST_CASE(Profiler_TrivialRecordAllocation) { |
215 DisableNativeProfileScope dnps; | 204 DisableNativeProfileScope dnps; |
216 const char* kScript = | 205 const char* kScript = |
(...skipping 26 matching lines...) Expand all Loading... |
243 const int64_t after_allocations_micros = Dart_TimelineGetMicros(); | 232 const int64_t after_allocations_micros = Dart_TimelineGetMicros(); |
244 const int64_t allocation_extent_micros = | 233 const int64_t allocation_extent_micros = |
245 after_allocations_micros - before_allocations_micros; | 234 after_allocations_micros - before_allocations_micros; |
246 { | 235 { |
247 Thread* thread = Thread::Current(); | 236 Thread* thread = Thread::Current(); |
248 Isolate* isolate = thread->isolate(); | 237 Isolate* isolate = thread->isolate(); |
249 StackZone zone(thread); | 238 StackZone zone(thread); |
250 HANDLESCOPE(thread); | 239 HANDLESCOPE(thread); |
251 Profile profile(isolate); | 240 Profile profile(isolate); |
252 // Filter for the class in the time range. | 241 // Filter for the class in the time range. |
253 AllocationFilter filter(isolate, | 242 AllocationFilter filter(isolate, class_a.id(), before_allocations_micros, |
254 class_a.id(), | |
255 before_allocations_micros, | |
256 allocation_extent_micros); | 243 allocation_extent_micros); |
257 profile.Build(thread, &filter, Profile::kNoTags); | 244 profile.Build(thread, &filter, Profile::kNoTags); |
258 // We should have 1 allocation sample. | 245 // We should have 1 allocation sample. |
259 EXPECT_EQ(1, profile.sample_count()); | 246 EXPECT_EQ(1, profile.sample_count()); |
260 ProfileTrieWalker walker(&profile); | 247 ProfileTrieWalker walker(&profile); |
261 | 248 |
262 // Exclusive code: B.boo -> main. | 249 // Exclusive code: B.boo -> main. |
263 walker.Reset(Profile::kExclusiveCode); | 250 walker.Reset(Profile::kExclusiveCode); |
264 // Move down from the root. | 251 // Move down from the root. |
265 EXPECT(walker.Down()); | 252 EXPECT(walker.Down()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 EXPECT(!walker.Down()); | 291 EXPECT(!walker.Down()); |
305 } | 292 } |
306 | 293 |
307 // Query with a time filter where no allocations occurred. | 294 // Query with a time filter where no allocations occurred. |
308 { | 295 { |
309 Thread* thread = Thread::Current(); | 296 Thread* thread = Thread::Current(); |
310 Isolate* isolate = thread->isolate(); | 297 Isolate* isolate = thread->isolate(); |
311 StackZone zone(thread); | 298 StackZone zone(thread); |
312 HANDLESCOPE(thread); | 299 HANDLESCOPE(thread); |
313 Profile profile(isolate); | 300 Profile profile(isolate); |
314 AllocationFilter filter(isolate, | 301 AllocationFilter filter(isolate, class_a.id(), Dart_TimelineGetMicros(), |
315 class_a.id(), | |
316 Dart_TimelineGetMicros(), | |
317 16000); | 302 16000); |
318 profile.Build(thread, &filter, Profile::kNoTags); | 303 profile.Build(thread, &filter, Profile::kNoTags); |
319 // We should have no allocation samples because none occured within | 304 // We should have no allocation samples because none occured within |
320 // the specified time range. | 305 // the specified time range. |
321 EXPECT_EQ(0, profile.sample_count()); | 306 EXPECT_EQ(0, profile.sample_count()); |
322 } | 307 } |
323 } | 308 } |
324 | 309 |
325 | 310 |
326 TEST_CASE(Profiler_ToggleRecordAllocation) { | 311 TEST_CASE(Profiler_ToggleRecordAllocation) { |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 635 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
651 EXPECT_VALID(lib); | 636 EXPECT_VALID(lib); |
652 Library& root_library = Library::Handle(); | 637 Library& root_library = Library::Handle(); |
653 root_library ^= Api::UnwrapHandle(lib); | 638 root_library ^= Api::UnwrapHandle(lib); |
654 Isolate* isolate = thread->isolate(); | 639 Isolate* isolate = thread->isolate(); |
655 | 640 |
656 const Class& double_class = | 641 const Class& double_class = |
657 Class::Handle(isolate->object_store()->double_class()); | 642 Class::Handle(isolate->object_store()->double_class()); |
658 EXPECT(!double_class.IsNull()); | 643 EXPECT(!double_class.IsNull()); |
659 | 644 |
660 Dart_Handle args[2] = { Dart_NewDouble(1.0), Dart_NewDouble(2.0), }; | 645 Dart_Handle args[2] = { |
| 646 Dart_NewDouble(1.0), Dart_NewDouble(2.0), |
| 647 }; |
661 | 648 |
662 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]); | 649 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]); |
663 EXPECT_VALID(result); | 650 EXPECT_VALID(result); |
664 | 651 |
665 { | 652 { |
666 StackZone zone(thread); | 653 StackZone zone(thread); |
667 HANDLESCOPE(thread); | 654 HANDLESCOPE(thread); |
668 Profile profile(isolate); | 655 Profile profile(isolate); |
669 AllocationFilter filter(isolate, double_class.id()); | 656 AllocationFilter filter(isolate, double_class.id()); |
670 profile.Build(thread, &filter, Profile::kNoTags); | 657 profile.Build(thread, &filter, Profile::kNoTags); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 "foo() {\n" | 816 "foo() {\n" |
830 " var msg = msg1 + msg1;\n" | 817 " var msg = msg1 + msg1;\n" |
831 " return (x) { return '$msg + $msg'; }(msg);\n" | 818 " return (x) { return '$msg + $msg'; }(msg);\n" |
832 "}\n"; | 819 "}\n"; |
833 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 820 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
834 EXPECT_VALID(lib); | 821 EXPECT_VALID(lib); |
835 Library& root_library = Library::Handle(); | 822 Library& root_library = Library::Handle(); |
836 root_library ^= Api::UnwrapHandle(lib); | 823 root_library ^= Api::UnwrapHandle(lib); |
837 Isolate* isolate = thread->isolate(); | 824 Isolate* isolate = thread->isolate(); |
838 | 825 |
839 const Class& context_class = | 826 const Class& context_class = Class::Handle(Object::context_class()); |
840 Class::Handle(Object::context_class()); | |
841 EXPECT(!context_class.IsNull()); | 827 EXPECT(!context_class.IsNull()); |
842 | 828 |
843 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL); | 829 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL); |
844 EXPECT_VALID(result); | 830 EXPECT_VALID(result); |
845 | 831 |
846 { | 832 { |
847 StackZone zone(thread); | 833 StackZone zone(thread); |
848 HANDLESCOPE(thread); | 834 HANDLESCOPE(thread); |
849 Profile profile(isolate); | 835 Profile profile(isolate); |
850 AllocationFilter filter(isolate, context_class.id()); | 836 AllocationFilter filter(isolate, context_class.id()); |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 1038 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
1053 EXPECT_VALID(lib); | 1039 EXPECT_VALID(lib); |
1054 Library& root_library = Library::Handle(); | 1040 Library& root_library = Library::Handle(); |
1055 root_library ^= Api::UnwrapHandle(lib); | 1041 root_library ^= Api::UnwrapHandle(lib); |
1056 Isolate* isolate = thread->isolate(); | 1042 Isolate* isolate = thread->isolate(); |
1057 | 1043 |
1058 const Class& one_byte_string_class = | 1044 const Class& one_byte_string_class = |
1059 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1045 Class::Handle(isolate->object_store()->one_byte_string_class()); |
1060 EXPECT(!one_byte_string_class.IsNull()); | 1046 EXPECT(!one_byte_string_class.IsNull()); |
1061 | 1047 |
1062 Dart_Handle args[2] = { NewString("a"), NewString("b"), }; | 1048 Dart_Handle args[2] = { |
| 1049 NewString("a"), NewString("b"), |
| 1050 }; |
1063 | 1051 |
1064 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]); | 1052 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]); |
1065 EXPECT_VALID(result); | 1053 EXPECT_VALID(result); |
1066 | 1054 |
1067 { | 1055 { |
1068 StackZone zone(thread); | 1056 StackZone zone(thread); |
1069 HANDLESCOPE(thread); | 1057 HANDLESCOPE(thread); |
1070 Profile profile(isolate); | 1058 Profile profile(isolate); |
1071 AllocationFilter filter(isolate, one_byte_string_class.id()); | 1059 AllocationFilter filter(isolate, one_byte_string_class.id()); |
1072 profile.Build(thread, &filter, Profile::kNoTags); | 1060 profile.Build(thread, &filter, Profile::kNoTags); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); | 1123 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); |
1136 EXPECT_VALID(lib); | 1124 EXPECT_VALID(lib); |
1137 Library& root_library = Library::Handle(); | 1125 Library& root_library = Library::Handle(); |
1138 root_library ^= Api::UnwrapHandle(lib); | 1126 root_library ^= Api::UnwrapHandle(lib); |
1139 Isolate* isolate = thread->isolate(); | 1127 Isolate* isolate = thread->isolate(); |
1140 | 1128 |
1141 const Class& one_byte_string_class = | 1129 const Class& one_byte_string_class = |
1142 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1130 Class::Handle(isolate->object_store()->one_byte_string_class()); |
1143 EXPECT(!one_byte_string_class.IsNull()); | 1131 EXPECT(!one_byte_string_class.IsNull()); |
1144 | 1132 |
1145 Dart_Handle args[2] = { NewString("a"), NewString("b"), }; | 1133 Dart_Handle args[2] = { |
| 1134 NewString("a"), NewString("b"), |
| 1135 }; |
1146 | 1136 |
1147 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]); | 1137 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]); |
1148 EXPECT_VALID(result); | 1138 EXPECT_VALID(result); |
1149 | 1139 |
1150 { | 1140 { |
1151 StackZone zone(thread); | 1141 StackZone zone(thread); |
1152 HANDLESCOPE(thread); | 1142 HANDLESCOPE(thread); |
1153 Profile profile(isolate); | 1143 Profile profile(isolate); |
1154 AllocationFilter filter(isolate, one_byte_string_class.id()); | 1144 AllocationFilter filter(isolate, one_byte_string_class.id()); |
1155 profile.Build(thread, &filter, Profile::kNoTags); | 1145 profile.Build(thread, &filter, Profile::kNoTags); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1390 } | 1380 } |
1391 | 1381 |
1392 // Test code transition tags. | 1382 // Test code transition tags. |
1393 { | 1383 { |
1394 Thread* thread = Thread::Current(); | 1384 Thread* thread = Thread::Current(); |
1395 Isolate* isolate = thread->isolate(); | 1385 Isolate* isolate = thread->isolate(); |
1396 StackZone zone(thread); | 1386 StackZone zone(thread); |
1397 HANDLESCOPE(thread); | 1387 HANDLESCOPE(thread); |
1398 Profile profile(isolate); | 1388 Profile profile(isolate); |
1399 AllocationFilter filter(isolate, class_a.id()); | 1389 AllocationFilter filter(isolate, class_a.id()); |
1400 profile.Build(thread, | 1390 profile.Build(thread, &filter, Profile::kNoTags, |
1401 &filter, | |
1402 Profile::kNoTags, | |
1403 ProfilerService::kCodeTransitionTagsBit); | 1391 ProfilerService::kCodeTransitionTagsBit); |
1404 // We should have 50,000 allocation samples. | 1392 // We should have 50,000 allocation samples. |
1405 EXPECT_EQ(50000, profile.sample_count()); | 1393 EXPECT_EQ(50000, profile.sample_count()); |
1406 ProfileTrieWalker walker(&profile); | 1394 ProfileTrieWalker walker(&profile); |
1407 // We have two code objects: mainA and B.boo. | 1395 // We have two code objects: mainA and B.boo. |
1408 walker.Reset(Profile::kExclusiveCode); | 1396 walker.Reset(Profile::kExclusiveCode); |
1409 EXPECT(walker.Down()); | 1397 EXPECT(walker.Down()); |
1410 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); | 1398 EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName()); |
1411 EXPECT(walker.Down()); | 1399 EXPECT(walker.Down()); |
1412 EXPECT_STREQ("B.boo", walker.CurrentName()); | 1400 EXPECT_STREQ("B.boo", walker.CurrentName()); |
(...skipping 938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2351 EXPECT_STREQ("main", walker.CurrentName()); | 2339 EXPECT_STREQ("main", walker.CurrentName()); |
2352 EXPECT_EQ(1, walker.CurrentNodeTickCount()); | 2340 EXPECT_EQ(1, walker.CurrentNodeTickCount()); |
2353 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); | 2341 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); |
2354 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); | 2342 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); |
2355 EXPECT_STREQ("bacon", walker.CurrentToken()); | 2343 EXPECT_STREQ("bacon", walker.CurrentToken()); |
2356 EXPECT(!walker.Down()); | 2344 EXPECT(!walker.Down()); |
2357 } | 2345 } |
2358 } | 2346 } |
2359 | 2347 |
2360 | 2348 |
2361 static void InsertFakeSample(SampleBuffer* sample_buffer, | 2349 static void InsertFakeSample(SampleBuffer* sample_buffer, uword* pc_offsets) { |
2362 uword* pc_offsets) { | |
2363 ASSERT(sample_buffer != NULL); | 2350 ASSERT(sample_buffer != NULL); |
2364 Isolate* isolate = Isolate::Current(); | 2351 Isolate* isolate = Isolate::Current(); |
2365 Sample* sample = sample_buffer->ReserveSample(); | 2352 Sample* sample = sample_buffer->ReserveSample(); |
2366 ASSERT(sample != NULL); | 2353 ASSERT(sample != NULL); |
2367 sample->Init(isolate, | 2354 sample->Init(isolate, OS::GetCurrentMonotonicMicros(), |
2368 OS::GetCurrentMonotonicMicros(), | |
2369 OSThread::Current()->trace_id()); | 2355 OSThread::Current()->trace_id()); |
2370 sample->set_thread_task(Thread::kMutatorTask); | 2356 sample->set_thread_task(Thread::kMutatorTask); |
2371 | 2357 |
2372 intptr_t i = 0; | 2358 intptr_t i = 0; |
2373 while (pc_offsets[i] != 0) { | 2359 while (pc_offsets[i] != 0) { |
2374 // When we collect a real stack trace, all PCs collected aside from the | 2360 // When we collect a real stack trace, all PCs collected aside from the |
2375 // executing one (i == 0) are actually return addresses. Return addresses | 2361 // executing one (i == 0) are actually return addresses. Return addresses |
2376 // are one byte beyond the call instruction that is executing. The profiler | 2362 // are one byte beyond the call instruction that is executing. The profiler |
2377 // accounts for this and subtracts one from these addresses when querying | 2363 // accounts for this and subtracts one from these addresses when querying |
2378 // inline and token position ranges. To be consistent with real stack | 2364 // inline and token position ranges. To be consistent with real stack |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2466 | 2452 |
2467 const CodeSourceMap& do_work_code_source_map = | 2453 const CodeSourceMap& do_work_code_source_map = |
2468 CodeSourceMap::Handle(do_work_code.code_source_map()); | 2454 CodeSourceMap::Handle(do_work_code.code_source_map()); |
2469 EXPECT(!do_work_code_source_map.IsNull()); | 2455 EXPECT(!do_work_code_source_map.IsNull()); |
2470 | 2456 |
2471 // Dump code source map. | 2457 // Dump code source map. |
2472 CodeSourceMap::Dump(do_work_code_source_map, do_work_code, main); | 2458 CodeSourceMap::Dump(do_work_code_source_map, do_work_code, main); |
2473 CodeSourceMap::Dump(main_code_source_map, main_code, main); | 2459 CodeSourceMap::Dump(main_code_source_map, main_code, main); |
2474 | 2460 |
2475 // Look up some source token position's pc. | 2461 // Look up some source token position's pc. |
2476 uword squarePositionPc = | 2462 uword squarePositionPc = FindPCForTokenPosition( |
2477 FindPCForTokenPosition(do_work_code, | 2463 do_work_code, do_work_code_source_map, squarePosition); |
2478 do_work_code_source_map, | |
2479 squarePosition); | |
2480 EXPECT(squarePositionPc != 0); | 2464 EXPECT(squarePositionPc != 0); |
2481 | 2465 |
2482 uword callPositionPc = | 2466 uword callPositionPc = |
2483 FindPCForTokenPosition(main_code, main_code_source_map, callPosition); | 2467 FindPCForTokenPosition(main_code, main_code_source_map, callPosition); |
2484 EXPECT(callPositionPc != 0); | 2468 EXPECT(callPositionPc != 0); |
2485 | 2469 |
2486 // Look up some classifying token position's pc. | 2470 // Look up some classifying token position's pc. |
2487 uword controlFlowPc = | 2471 uword controlFlowPc = FindPCForTokenPosition( |
2488 FindPCForTokenPosition(do_work_code, | 2472 do_work_code, do_work_code_source_map, TokenPosition::kControlFlow); |
2489 do_work_code_source_map, | |
2490 TokenPosition::kControlFlow); | |
2491 EXPECT(controlFlowPc != 0); | 2473 EXPECT(controlFlowPc != 0); |
2492 | 2474 |
2493 uword tempMovePc = | 2475 uword tempMovePc = FindPCForTokenPosition(main_code, main_code_source_map, |
2494 FindPCForTokenPosition(main_code, | 2476 TokenPosition::kTempMove); |
2495 main_code_source_map, | |
2496 TokenPosition::kTempMove); | |
2497 EXPECT(tempMovePc != 0); | 2477 EXPECT(tempMovePc != 0); |
2498 | 2478 |
2499 // Insert fake samples. | 2479 // Insert fake samples. |
2500 | 2480 |
2501 // Sample 1: | 2481 // Sample 1: |
2502 // squarePositionPc exclusive. | 2482 // squarePositionPc exclusive. |
2503 // callPositionPc inclusive. | 2483 // callPositionPc inclusive. |
2504 uword sample1[] = { | 2484 uword sample1[] = {squarePositionPc, // doWork. |
2505 squarePositionPc, // doWork. | 2485 callPositionPc, // main. |
2506 callPositionPc, // main. | 2486 0}; |
2507 0 | |
2508 }; | |
2509 | 2487 |
2510 // Sample 2: | 2488 // Sample 2: |
2511 // squarePositionPc exclusive. | 2489 // squarePositionPc exclusive. |
2512 uword sample2[] = { | 2490 uword sample2[] = { |
2513 squarePositionPc, // doWork. | 2491 squarePositionPc, // doWork. |
2514 0, | 2492 0, |
2515 }; | 2493 }; |
2516 | 2494 |
2517 // Sample 3: | 2495 // Sample 3: |
2518 // controlFlowPc exclusive. | 2496 // controlFlowPc exclusive. |
2519 // callPositionPc inclusive. | 2497 // callPositionPc inclusive. |
2520 uword sample3[] = { | 2498 uword sample3[] = {controlFlowPc, // doWork. |
2521 controlFlowPc, // doWork. | 2499 callPositionPc, // main. |
2522 callPositionPc, // main. | 2500 0}; |
2523 0 | |
2524 }; | |
2525 | 2501 |
2526 // Sample 4: | 2502 // Sample 4: |
2527 // tempMovePc exclusive. | 2503 // tempMovePc exclusive. |
2528 uword sample4[] = { | 2504 uword sample4[] = {tempMovePc, // main. |
2529 tempMovePc, // main. | 2505 0}; |
2530 0 | |
2531 }; | |
2532 | 2506 |
2533 InsertFakeSample(sample_buffer, &sample1[0]); | 2507 InsertFakeSample(sample_buffer, &sample1[0]); |
2534 InsertFakeSample(sample_buffer, &sample2[0]); | 2508 InsertFakeSample(sample_buffer, &sample2[0]); |
2535 InsertFakeSample(sample_buffer, &sample3[0]); | 2509 InsertFakeSample(sample_buffer, &sample3[0]); |
2536 InsertFakeSample(sample_buffer, &sample4[0]); | 2510 InsertFakeSample(sample_buffer, &sample4[0]); |
2537 | 2511 |
2538 // Generate source report for main. | 2512 // Generate source report for main. |
2539 SourceReport sourceReport(SourceReport::kProfile); | 2513 SourceReport sourceReport(SourceReport::kProfile); |
2540 JSONStream js; | 2514 JSONStream js; |
2541 sourceReport.PrintJSON(&js, | 2515 sourceReport.PrintJSON(&js, script, do_work.token_pos(), |
2542 script, | |
2543 do_work.token_pos(), | |
2544 main.end_token_pos()); | 2516 main.end_token_pos()); |
2545 | 2517 |
2546 // Verify positions in do_work. | 2518 // Verify positions in do_work. |
2547 EXPECT_SUBSTRING("\"positions\":[\"ControlFlow\",6]", js.ToCString()); | 2519 EXPECT_SUBSTRING("\"positions\":[\"ControlFlow\",6]", js.ToCString()); |
2548 // Verify exclusive ticks in do_work. | 2520 // Verify exclusive ticks in do_work. |
2549 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,2]", js.ToCString()); | 2521 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,2]", js.ToCString()); |
2550 // Verify inclusive ticks in do_work. | 2522 // Verify inclusive ticks in do_work. |
2551 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); | 2523 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); |
2552 | 2524 |
2553 // Verify positions in main. | 2525 // Verify positions in main. |
2554 EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString()); | 2526 EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString()); |
2555 // Verify exclusive ticks in main. | 2527 // Verify exclusive ticks in main. |
2556 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString()); | 2528 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString()); |
2557 // Verify inclusive ticks in main. | 2529 // Verify inclusive ticks in main. |
2558 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); | 2530 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); |
2559 } | 2531 } |
2560 | 2532 |
2561 #endif // !PRODUCT | 2533 #endif // !PRODUCT |
2562 | 2534 |
2563 } // namespace dart | 2535 } // namespace dart |
OLD | NEW |