Chromium Code Reviews| 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/address_sanitizer.h" | 5 #include "platform/address_sanitizer.h" |
| 6 #include "platform/memory_sanitizer.h" | 6 #include "platform/memory_sanitizer.h" |
| 7 #include "platform/utils.h" | 7 #include "platform/utils.h" |
| 8 | 8 |
| 9 #include "vm/allocation.h" | 9 #include "vm/allocation.h" |
| 10 #include "vm/atomic.h" | 10 #include "vm/atomic.h" |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) | 321 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) |
| 322 : SampleVisitor(isolate) { | 322 : SampleVisitor(isolate) { |
| 323 } | 323 } |
| 324 | 324 |
| 325 | 325 |
| 326 void ClearProfileVisitor::VisitSample(Sample* sample) { | 326 void ClearProfileVisitor::VisitSample(Sample* sample) { |
| 327 sample->Clear(); | 327 sample->Clear(); |
| 328 } | 328 } |
| 329 | 329 |
| 330 | 330 |
| 331 static void DumpStackFrame(intptr_t frame, uword pc) { | |
|
srdjan
2016/04/25 20:05:55
maybe s/frame/frame_index/ ... also below
Cutch
2016/04/25 20:14:54
Done.
| |
| 332 uintptr_t start = 0; | |
| 333 char* native_symbol_name = | |
| 334 NativeSymbolResolver::LookupSymbolName(pc, &start); | |
| 335 if (native_symbol_name == NULL) { | |
| 336 OS::Print("Frame[%" Pd "] = `unknown symbol` [0x%" Px "]\n", frame, pc); | |
| 337 } else { | |
| 338 OS::Print("Frame[%" Pd "] = `%s` [0x%" Px "]\n", | |
| 339 frame, native_symbol_name, pc); | |
| 340 free(native_symbol_name); | |
| 341 } | |
| 342 } | |
| 343 | |
| 344 | |
| 345 static void DumpStackFrame(intptr_t frame, | |
| 346 uword pc, | |
| 347 const Code& code) { | |
| 348 if (code.IsNull()) { | |
| 349 DumpStackFrame(frame, pc); | |
| 350 } else { | |
| 351 OS::Print("Frame[%" Pd "] = Dart:`%s` [0x%" Px "]\n", | |
| 352 frame, code.ToCString(), pc); | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 | |
| 331 class ProfilerStackWalker : public ValueObject { | 357 class ProfilerStackWalker : public ValueObject { |
| 332 public: | 358 public: |
| 333 ProfilerStackWalker(Isolate* isolate, | 359 ProfilerStackWalker(Isolate* isolate, |
| 334 Sample* head_sample, | 360 Sample* head_sample, |
| 335 SampleBuffer* sample_buffer) | 361 SampleBuffer* sample_buffer) |
| 336 : isolate_(isolate), | 362 : isolate_(isolate), |
| 337 sample_(head_sample), | 363 sample_(head_sample), |
| 338 sample_buffer_(sample_buffer), | 364 sample_buffer_(sample_buffer), |
| 339 frame_index_(0), | 365 frame_index_(0), |
| 340 total_frames_(0) { | 366 total_frames_(0) { |
| 341 ASSERT(isolate_ != NULL); | 367 ASSERT(isolate_ != NULL); |
| 342 ASSERT(sample_ != NULL); | 368 if (sample_ != NULL) { |
|
srdjan
2016/04/25 20:05:55
I find using positive test (in most cases) to be m
Cutch
2016/04/25 20:14:54
Done.
| |
| 343 ASSERT(sample_buffer_ != NULL); | 369 ASSERT(sample_buffer_ != NULL); |
| 344 ASSERT(sample_->head_sample()); | 370 ASSERT(sample_->head_sample()); |
| 371 } else { | |
| 372 ASSERT(sample_buffer_ == NULL); | |
| 373 } | |
| 374 } | |
| 375 | |
| 376 bool Append(uword pc, const Code& code) { | |
| 377 if (sample_ == NULL) { | |
| 378 DumpStackFrame(frame_index_, pc, code); | |
| 379 frame_index_++; | |
| 380 total_frames_++; | |
| 381 return true; | |
| 382 } | |
| 383 return Append(pc); | |
| 345 } | 384 } |
| 346 | 385 |
| 347 bool Append(uword pc) { | 386 bool Append(uword pc) { |
| 387 if (sample_ == NULL) { | |
| 388 DumpStackFrame(frame_index_, pc); | |
| 389 frame_index_++; | |
| 390 total_frames_++; | |
| 391 return true; | |
| 392 } | |
| 348 if (total_frames_ >= FLAG_max_profile_depth) { | 393 if (total_frames_ >= FLAG_max_profile_depth) { |
| 349 sample_->set_truncated_trace(true); | 394 sample_->set_truncated_trace(true); |
| 350 return false; | 395 return false; |
| 351 } | 396 } |
| 352 ASSERT(sample_ != NULL); | 397 ASSERT(sample_ != NULL); |
| 353 if (frame_index_ == kSampleSize) { | 398 if (frame_index_ == kSampleSize) { |
| 354 Sample* new_sample = sample_buffer_->ReserveSampleAndLink(sample_); | 399 Sample* new_sample = sample_buffer_->ReserveSampleAndLink(sample_); |
| 355 if (new_sample == NULL) { | 400 if (new_sample == NULL) { |
| 356 // Could not reserve new sample- mark this as truncated. | 401 // Could not reserve new sample- mark this as truncated. |
| 357 sample_->set_truncated_trace(true); | 402 sample_->set_truncated_trace(true); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 385 SampleBuffer* sample_buffer) | 430 SampleBuffer* sample_buffer) |
| 386 : ProfilerStackWalker(isolate, sample, sample_buffer), | 431 : ProfilerStackWalker(isolate, sample, sample_buffer), |
| 387 frame_iterator_(thread) { | 432 frame_iterator_(thread) { |
| 388 } | 433 } |
| 389 | 434 |
| 390 void walk() { | 435 void walk() { |
| 391 // Mark that this sample was collected from an exit frame. | 436 // Mark that this sample was collected from an exit frame. |
| 392 sample_->set_exit_frame_sample(true); | 437 sample_->set_exit_frame_sample(true); |
| 393 | 438 |
| 394 StackFrame* frame = frame_iterator_.NextFrame(); | 439 StackFrame* frame = frame_iterator_.NextFrame(); |
| 440 Code& code = Code::Handle(); | |
|
srdjan
2016/04/25 20:05:55
Can you use zone here (from frame_iterator_ or Pro
Cutch
2016/04/25 20:14:54
I've actually re-worked this code here. It was uns
| |
| 395 while (frame != NULL) { | 441 while (frame != NULL) { |
| 396 if (!Append(frame->pc())) { | 442 code ^= frame->LookupDartCode(); |
| 443 if (!Append(frame->pc(), code)) { | |
| 397 return; | 444 return; |
| 398 } | 445 } |
| 399 frame = frame_iterator_.NextFrame(); | 446 frame = frame_iterator_.NextFrame(); |
| 400 } | 447 } |
| 401 } | 448 } |
| 402 | 449 |
| 403 private: | 450 private: |
| 404 DartFrameIterator frame_iterator_; | 451 DartFrameIterator frame_iterator_; |
| 405 }; | 452 }; |
| 406 | 453 |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 : ProfilerStackWalker(isolate, sample, sample_buffer), | 621 : ProfilerStackWalker(isolate, sample, sample_buffer), |
| 575 stack_upper_(stack_upper), | 622 stack_upper_(stack_upper), |
| 576 original_pc_(pc), | 623 original_pc_(pc), |
| 577 original_fp_(fp), | 624 original_fp_(fp), |
| 578 original_sp_(sp), | 625 original_sp_(sp), |
| 579 lower_bound_(stack_lower) { | 626 lower_bound_(stack_lower) { |
| 580 } | 627 } |
| 581 | 628 |
| 582 void walk() { | 629 void walk() { |
| 583 const uword kMaxStep = VirtualMemory::PageSize(); | 630 const uword kMaxStep = VirtualMemory::PageSize(); |
| 584 | |
| 585 Append(original_pc_); | 631 Append(original_pc_); |
| 586 | 632 |
| 587 uword* pc = reinterpret_cast<uword*>(original_pc_); | 633 uword* pc = reinterpret_cast<uword*>(original_pc_); |
| 588 uword* fp = reinterpret_cast<uword*>(original_fp_); | 634 uword* fp = reinterpret_cast<uword*>(original_fp_); |
| 589 uword* previous_fp = fp; | 635 uword* previous_fp = fp; |
| 590 | 636 |
| 591 uword gap = original_fp_ - original_sp_; | 637 uword gap = original_fp_ - original_sp_; |
| 592 if (gap >= kMaxStep) { | 638 if (gap >= kMaxStep) { |
| 593 // Gap between frame pointer and stack pointer is | 639 // Gap between frame pointer and stack pointer is |
| 594 // too large. | 640 // too large. |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 874 static uintptr_t GetProgramCounter() { | 920 static uintptr_t GetProgramCounter() { |
| 875 return reinterpret_cast<uintptr_t>(_ReturnAddress()); | 921 return reinterpret_cast<uintptr_t>(_ReturnAddress()); |
| 876 } | 922 } |
| 877 #else | 923 #else |
| 878 static uintptr_t __attribute__((noinline)) GetProgramCounter() { | 924 static uintptr_t __attribute__((noinline)) GetProgramCounter() { |
| 879 return reinterpret_cast<uintptr_t>( | 925 return reinterpret_cast<uintptr_t>( |
| 880 __builtin_extract_return_addr(__builtin_return_address(0))); | 926 __builtin_extract_return_addr(__builtin_return_address(0))); |
| 881 } | 927 } |
| 882 #endif | 928 #endif |
| 883 | 929 |
| 930 | |
| 931 void Profiler::DumpStackTrace(bool native_stack_trace) { | |
| 932 Thread* thread = Thread::Current(); | |
| 933 ASSERT(thread != NULL); | |
| 934 OSThread* os_thread = thread->os_thread(); | |
| 935 ASSERT(os_thread != NULL); | |
| 936 Isolate* isolate = thread->isolate(); | |
| 937 if (!CheckIsolate(isolate)) { | |
| 938 return; | |
| 939 } | |
| 940 | |
| 941 const bool exited_dart_code = thread->HasExitedDartCode(); | |
| 942 | |
| 943 OS::Print("Dumping %s stack trace for thread %" Px "\n", | |
| 944 native_stack_trace ? "native" : "dart-only", | |
| 945 static_cast<uintptr_t>(os_thread->trace_id())); | |
| 946 | |
| 947 uintptr_t sp = Thread::GetCurrentStackPointer(); | |
| 948 uintptr_t fp = 0; | |
| 949 uintptr_t pc = GetProgramCounter(); | |
| 950 | |
| 951 COPY_FP_REGISTER(fp); | |
| 952 | |
| 953 uword stack_lower = 0; | |
| 954 uword stack_upper = 0; | |
| 955 | |
| 956 if (!InitialRegisterCheck(pc, fp, sp)) { | |
| 957 OS::Print( | |
| 958 "Stack dump aborted because InitialRegisterCheck.\n"); | |
| 959 return; | |
| 960 } | |
| 961 | |
| 962 if (!GetAndValidateIsolateStackBounds(thread, | |
| 963 fp, | |
| 964 sp, | |
| 965 &stack_lower, | |
| 966 &stack_upper)) { | |
| 967 OS::Print( | |
| 968 "Stack dump aborted because GetAndValidateIsolateStackBounds.\n"); | |
| 969 return; | |
| 970 } | |
| 971 | |
| 972 if (native_stack_trace) { | |
| 973 ProfilerNativeStackWalker native_stack_walker(isolate, | |
| 974 NULL, | |
| 975 NULL, | |
| 976 stack_lower, | |
| 977 stack_upper, | |
| 978 pc, | |
| 979 fp, | |
| 980 sp); | |
| 981 native_stack_walker.walk(); | |
| 982 } else if (exited_dart_code) { | |
| 983 ProfilerDartExitStackWalker dart_exit_stack_walker(thread, | |
| 984 isolate, | |
| 985 NULL, | |
| 986 NULL); | |
| 987 dart_exit_stack_walker.walk(); | |
| 988 } else { | |
| 989 ProfilerDartStackWalker dart_stack_walker(isolate, | |
| 990 NULL, | |
| 991 NULL, | |
| 992 stack_lower, | |
| 993 stack_upper, | |
| 994 pc, | |
| 995 fp, | |
| 996 sp); | |
| 997 } | |
| 998 } | |
| 999 | |
| 1000 | |
| 884 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { | 1001 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { |
| 885 ASSERT(thread != NULL); | 1002 ASSERT(thread != NULL); |
| 886 OSThread* os_thread = thread->os_thread(); | 1003 OSThread* os_thread = thread->os_thread(); |
| 887 ASSERT(os_thread != NULL); | 1004 ASSERT(os_thread != NULL); |
| 888 Isolate* isolate = thread->isolate(); | 1005 Isolate* isolate = thread->isolate(); |
| 889 if (!CheckIsolate(isolate)) { | 1006 if (!CheckIsolate(isolate)) { |
| 890 return; | 1007 return; |
| 891 } | 1008 } |
| 892 | 1009 |
| 893 const bool exited_dart_code = thread->HasExitedDartCode(); | 1010 const bool exited_dart_code = thread->HasExitedDartCode(); |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1435 | 1552 |
| 1436 | 1553 |
| 1437 ProcessedSampleBuffer::ProcessedSampleBuffer() | 1554 ProcessedSampleBuffer::ProcessedSampleBuffer() |
| 1438 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { | 1555 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { |
| 1439 ASSERT(code_lookup_table_ != NULL); | 1556 ASSERT(code_lookup_table_ != NULL); |
| 1440 } | 1557 } |
| 1441 | 1558 |
| 1442 #endif // !PRODUCT | 1559 #endif // !PRODUCT |
| 1443 | 1560 |
| 1444 } // namespace dart | 1561 } // namespace dart |
| OLD | NEW |