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