| 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_index, uword pc) { |
| 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", |
| 337 frame_index, pc); |
| 338 } else { |
| 339 OS::Print("Frame[%" Pd "] = `%s` [0x%" Px "]\n", |
| 340 frame_index, native_symbol_name, pc); |
| 341 free(native_symbol_name); |
| 342 } |
| 343 } |
| 344 |
| 345 |
| 346 static void DumpStackFrame(intptr_t frame_index, |
| 347 uword pc, |
| 348 const Code& code) { |
| 349 if (code.IsNull()) { |
| 350 DumpStackFrame(frame_index, pc); |
| 351 } else { |
| 352 OS::Print("Frame[%" Pd "] = Dart:`%s` [0x%" Px "]\n", |
| 353 frame_index, code.ToCString(), pc); |
| 354 } |
| 355 } |
| 356 |
| 357 |
| 331 class ProfilerStackWalker : public ValueObject { | 358 class ProfilerStackWalker : public ValueObject { |
| 332 public: | 359 public: |
| 333 ProfilerStackWalker(Isolate* isolate, | 360 ProfilerStackWalker(Isolate* isolate, |
| 334 Sample* head_sample, | 361 Sample* head_sample, |
| 335 SampleBuffer* sample_buffer) | 362 SampleBuffer* sample_buffer) |
| 336 : isolate_(isolate), | 363 : isolate_(isolate), |
| 337 sample_(head_sample), | 364 sample_(head_sample), |
| 338 sample_buffer_(sample_buffer), | 365 sample_buffer_(sample_buffer), |
| 339 frame_index_(0), | 366 frame_index_(0), |
| 340 total_frames_(0) { | 367 total_frames_(0) { |
| 341 ASSERT(isolate_ != NULL); | 368 ASSERT(isolate_ != NULL); |
| 342 ASSERT(sample_ != NULL); | 369 if (sample_ == NULL) { |
| 343 ASSERT(sample_buffer_ != NULL); | 370 ASSERT(sample_buffer_ == NULL); |
| 344 ASSERT(sample_->head_sample()); | 371 } else { |
| 372 ASSERT(sample_buffer_ != NULL); |
| 373 ASSERT(sample_->head_sample()); |
| 374 } |
| 375 } |
| 376 |
| 377 bool Append(uword pc, const Code& code) { |
| 378 if (sample_ == NULL) { |
| 379 DumpStackFrame(frame_index_, pc, code); |
| 380 frame_index_++; |
| 381 total_frames_++; |
| 382 return true; |
| 383 } |
| 384 return Append(pc); |
| 345 } | 385 } |
| 346 | 386 |
| 347 bool Append(uword pc) { | 387 bool Append(uword pc) { |
| 388 if (sample_ == NULL) { |
| 389 DumpStackFrame(frame_index_, pc); |
| 390 frame_index_++; |
| 391 total_frames_++; |
| 392 return true; |
| 393 } |
| 348 if (total_frames_ >= FLAG_max_profile_depth) { | 394 if (total_frames_ >= FLAG_max_profile_depth) { |
| 349 sample_->set_truncated_trace(true); | 395 sample_->set_truncated_trace(true); |
| 350 return false; | 396 return false; |
| 351 } | 397 } |
| 352 ASSERT(sample_ != NULL); | 398 ASSERT(sample_ != NULL); |
| 353 if (frame_index_ == kSampleSize) { | 399 if (frame_index_ == kSampleSize) { |
| 354 Sample* new_sample = sample_buffer_->ReserveSampleAndLink(sample_); | 400 Sample* new_sample = sample_buffer_->ReserveSampleAndLink(sample_); |
| 355 if (new_sample == NULL) { | 401 if (new_sample == NULL) { |
| 356 // Could not reserve new sample- mark this as truncated. | 402 // Could not reserve new sample- mark this as truncated. |
| 357 sample_->set_truncated_trace(true); | 403 sample_->set_truncated_trace(true); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 385 SampleBuffer* sample_buffer) | 431 SampleBuffer* sample_buffer) |
| 386 : ProfilerStackWalker(isolate, sample, sample_buffer), | 432 : ProfilerStackWalker(isolate, sample, sample_buffer), |
| 387 frame_iterator_(thread) { | 433 frame_iterator_(thread) { |
| 388 } | 434 } |
| 389 | 435 |
| 390 void walk() { | 436 void walk() { |
| 391 // Mark that this sample was collected from an exit frame. | 437 // Mark that this sample was collected from an exit frame. |
| 392 sample_->set_exit_frame_sample(true); | 438 sample_->set_exit_frame_sample(true); |
| 393 | 439 |
| 394 StackFrame* frame = frame_iterator_.NextFrame(); | 440 StackFrame* frame = frame_iterator_.NextFrame(); |
| 395 while (frame != NULL) { | 441 if (sample_ == NULL) { |
| 396 if (!Append(frame->pc())) { | 442 // Only when we are dumping the stack trace for debug purposes. |
| 397 return; | 443 Code& code = Code::Handle(); |
| 444 while (frame != NULL) { |
| 445 code ^= frame->LookupDartCode(); |
| 446 if (!Append(frame->pc(), code)) { |
| 447 return; |
| 448 } |
| 449 frame = frame_iterator_.NextFrame(); |
| 398 } | 450 } |
| 399 frame = frame_iterator_.NextFrame(); | 451 } else { |
| 452 while (frame != NULL) { |
| 453 if (!Append(frame->pc())) { |
| 454 return; |
| 455 } |
| 456 frame = frame_iterator_.NextFrame(); |
| 457 } |
| 400 } | 458 } |
| 401 } | 459 } |
| 402 | 460 |
| 403 private: | 461 private: |
| 404 DartFrameIterator frame_iterator_; | 462 DartFrameIterator frame_iterator_; |
| 405 }; | 463 }; |
| 406 | 464 |
| 407 | 465 |
| 408 // Executing Dart code, walk the stack. | 466 // Executing Dart code, walk the stack. |
| 409 class ProfilerDartStackWalker : public ProfilerStackWalker { | 467 class ProfilerDartStackWalker : public ProfilerStackWalker { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 : ProfilerStackWalker(isolate, sample, sample_buffer), | 632 : ProfilerStackWalker(isolate, sample, sample_buffer), |
| 575 stack_upper_(stack_upper), | 633 stack_upper_(stack_upper), |
| 576 original_pc_(pc), | 634 original_pc_(pc), |
| 577 original_fp_(fp), | 635 original_fp_(fp), |
| 578 original_sp_(sp), | 636 original_sp_(sp), |
| 579 lower_bound_(stack_lower) { | 637 lower_bound_(stack_lower) { |
| 580 } | 638 } |
| 581 | 639 |
| 582 void walk() { | 640 void walk() { |
| 583 const uword kMaxStep = VirtualMemory::PageSize(); | 641 const uword kMaxStep = VirtualMemory::PageSize(); |
| 584 | |
| 585 Append(original_pc_); | 642 Append(original_pc_); |
| 586 | 643 |
| 587 uword* pc = reinterpret_cast<uword*>(original_pc_); | 644 uword* pc = reinterpret_cast<uword*>(original_pc_); |
| 588 uword* fp = reinterpret_cast<uword*>(original_fp_); | 645 uword* fp = reinterpret_cast<uword*>(original_fp_); |
| 589 uword* previous_fp = fp; | 646 uword* previous_fp = fp; |
| 590 | 647 |
| 591 uword gap = original_fp_ - original_sp_; | 648 uword gap = original_fp_ - original_sp_; |
| 592 if (gap >= kMaxStep) { | 649 if (gap >= kMaxStep) { |
| 593 // Gap between frame pointer and stack pointer is | 650 // Gap between frame pointer and stack pointer is |
| 594 // too large. | 651 // too large. |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 static uintptr_t GetProgramCounter() { | 931 static uintptr_t GetProgramCounter() { |
| 875 return reinterpret_cast<uintptr_t>(_ReturnAddress()); | 932 return reinterpret_cast<uintptr_t>(_ReturnAddress()); |
| 876 } | 933 } |
| 877 #else | 934 #else |
| 878 static uintptr_t __attribute__((noinline)) GetProgramCounter() { | 935 static uintptr_t __attribute__((noinline)) GetProgramCounter() { |
| 879 return reinterpret_cast<uintptr_t>( | 936 return reinterpret_cast<uintptr_t>( |
| 880 __builtin_extract_return_addr(__builtin_return_address(0))); | 937 __builtin_extract_return_addr(__builtin_return_address(0))); |
| 881 } | 938 } |
| 882 #endif | 939 #endif |
| 883 | 940 |
| 941 |
| 942 void Profiler::DumpStackTrace(bool native_stack_trace) { |
| 943 Thread* thread = Thread::Current(); |
| 944 ASSERT(thread != NULL); |
| 945 OSThread* os_thread = thread->os_thread(); |
| 946 ASSERT(os_thread != NULL); |
| 947 Isolate* isolate = thread->isolate(); |
| 948 if (!CheckIsolate(isolate)) { |
| 949 return; |
| 950 } |
| 951 |
| 952 const bool exited_dart_code = thread->HasExitedDartCode(); |
| 953 |
| 954 OS::Print("Dumping %s stack trace for thread %" Px "\n", |
| 955 native_stack_trace ? "native" : "dart-only", |
| 956 static_cast<uintptr_t>(os_thread->trace_id())); |
| 957 |
| 958 uintptr_t sp = Thread::GetCurrentStackPointer(); |
| 959 uintptr_t fp = 0; |
| 960 uintptr_t pc = GetProgramCounter(); |
| 961 |
| 962 COPY_FP_REGISTER(fp); |
| 963 |
| 964 uword stack_lower = 0; |
| 965 uword stack_upper = 0; |
| 966 |
| 967 if (!InitialRegisterCheck(pc, fp, sp)) { |
| 968 OS::Print( |
| 969 "Stack dump aborted because InitialRegisterCheck.\n"); |
| 970 return; |
| 971 } |
| 972 |
| 973 if (!GetAndValidateIsolateStackBounds(thread, |
| 974 fp, |
| 975 sp, |
| 976 &stack_lower, |
| 977 &stack_upper)) { |
| 978 OS::Print( |
| 979 "Stack dump aborted because GetAndValidateIsolateStackBounds.\n"); |
| 980 return; |
| 981 } |
| 982 |
| 983 if (native_stack_trace) { |
| 984 ProfilerNativeStackWalker native_stack_walker(isolate, |
| 985 NULL, |
| 986 NULL, |
| 987 stack_lower, |
| 988 stack_upper, |
| 989 pc, |
| 990 fp, |
| 991 sp); |
| 992 native_stack_walker.walk(); |
| 993 } else if (exited_dart_code) { |
| 994 ProfilerDartExitStackWalker dart_exit_stack_walker(thread, |
| 995 isolate, |
| 996 NULL, |
| 997 NULL); |
| 998 dart_exit_stack_walker.walk(); |
| 999 } else { |
| 1000 ProfilerDartStackWalker dart_stack_walker(isolate, |
| 1001 NULL, |
| 1002 NULL, |
| 1003 stack_lower, |
| 1004 stack_upper, |
| 1005 pc, |
| 1006 fp, |
| 1007 sp); |
| 1008 } |
| 1009 } |
| 1010 |
| 1011 |
| 884 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { | 1012 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { |
| 885 ASSERT(thread != NULL); | 1013 ASSERT(thread != NULL); |
| 886 OSThread* os_thread = thread->os_thread(); | 1014 OSThread* os_thread = thread->os_thread(); |
| 887 ASSERT(os_thread != NULL); | 1015 ASSERT(os_thread != NULL); |
| 888 Isolate* isolate = thread->isolate(); | 1016 Isolate* isolate = thread->isolate(); |
| 889 if (!CheckIsolate(isolate)) { | 1017 if (!CheckIsolate(isolate)) { |
| 890 return; | 1018 return; |
| 891 } | 1019 } |
| 892 | 1020 |
| 893 const bool exited_dart_code = thread->HasExitedDartCode(); | 1021 const bool exited_dart_code = thread->HasExitedDartCode(); |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1435 | 1563 |
| 1436 | 1564 |
| 1437 ProcessedSampleBuffer::ProcessedSampleBuffer() | 1565 ProcessedSampleBuffer::ProcessedSampleBuffer() |
| 1438 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { | 1566 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { |
| 1439 ASSERT(code_lookup_table_ != NULL); | 1567 ASSERT(code_lookup_table_ != NULL); |
| 1440 } | 1568 } |
| 1441 | 1569 |
| 1442 #endif // !PRODUCT | 1570 #endif // !PRODUCT |
| 1443 | 1571 |
| 1444 } // namespace dart | 1572 } // namespace dart |
| OLD | NEW |