| 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 15 matching lines...) Expand all Loading... |
| 26 | 26 |
| 27 namespace dart { | 27 namespace dart { |
| 28 | 28 |
| 29 static const intptr_t kSampleSize = 8; | 29 static const intptr_t kSampleSize = 8; |
| 30 static const intptr_t kMaxSamplesPerTick = 4; | 30 static const intptr_t kMaxSamplesPerTick = 4; |
| 31 | 31 |
| 32 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates."); | 32 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates."); |
| 33 | 33 |
| 34 #if defined(TARGET_OS_ANDROID) || defined(TARGET_ARCH_ARM64) || \ | 34 #if defined(TARGET_OS_ANDROID) || defined(TARGET_ARCH_ARM64) || \ |
| 35 defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS) | 35 defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS) |
| 36 DEFINE_FLAG(int, profile_period, 10000, | 36 DEFINE_FLAG(int, |
| 37 "Time between profiler samples in microseconds. Minimum 50."); | 37 profile_period, |
| 38 10000, |
| 39 "Time between profiler samples in microseconds. Minimum 50."); |
| 38 #else | 40 #else |
| 39 DEFINE_FLAG(int, profile_period, 1000, | 41 DEFINE_FLAG(int, |
| 40 "Time between profiler samples in microseconds. Minimum 50."); | 42 profile_period, |
| 43 1000, |
| 44 "Time between profiler samples in microseconds. Minimum 50."); |
| 41 #endif | 45 #endif |
| 42 DEFINE_FLAG(int, max_profile_depth, kSampleSize * kMaxSamplesPerTick, | 46 DEFINE_FLAG(int, |
| 47 max_profile_depth, |
| 48 kSampleSize* kMaxSamplesPerTick, |
| 43 "Maximum number stack frames walked. Minimum 1. Maximum 255."); | 49 "Maximum number stack frames walked. Minimum 1. Maximum 255."); |
| 44 #if defined(USING_SIMULATOR) | 50 #if defined(USING_SIMULATOR) |
| 45 DEFINE_FLAG(bool, profile_vm, true, | 51 DEFINE_FLAG(bool, profile_vm, true, "Always collect native stack traces."); |
| 46 "Always collect native stack traces."); | |
| 47 #else | 52 #else |
| 48 DEFINE_FLAG(bool, profile_vm, false, | 53 DEFINE_FLAG(bool, profile_vm, false, "Always collect native stack traces."); |
| 49 "Always collect native stack traces."); | |
| 50 #endif | 54 #endif |
| 51 | 55 |
| 52 #ifndef PRODUCT | 56 #ifndef PRODUCT |
| 53 | 57 |
| 54 bool Profiler::initialized_ = false; | 58 bool Profiler::initialized_ = false; |
| 55 SampleBuffer* Profiler::sample_buffer_ = NULL; | 59 SampleBuffer* Profiler::sample_buffer_ = NULL; |
| 56 ProfilerCounters Profiler::counters_; | 60 ProfilerCounters Profiler::counters_; |
| 57 | 61 |
| 58 void Profiler::InitOnce() { | 62 void Profiler::InitOnce() { |
| 59 // Place some sane restrictions on user controlled flags. | 63 // Place some sane restrictions on user controlled flags. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 } | 110 } |
| 107 } | 111 } |
| 108 | 112 |
| 109 | 113 |
| 110 intptr_t Sample::pcs_length_ = 0; | 114 intptr_t Sample::pcs_length_ = 0; |
| 111 intptr_t Sample::instance_size_ = 0; | 115 intptr_t Sample::instance_size_ = 0; |
| 112 | 116 |
| 113 | 117 |
| 114 void Sample::InitOnce() { | 118 void Sample::InitOnce() { |
| 115 pcs_length_ = kSampleSize; | 119 pcs_length_ = kSampleSize; |
| 116 instance_size_ = | 120 instance_size_ = sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT. |
| 117 sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT. | |
| 118 } | 121 } |
| 119 | 122 |
| 120 | 123 |
| 121 uword* Sample::GetPCArray() const { | 124 uword* Sample::GetPCArray() const { |
| 122 return reinterpret_cast<uword*>( | 125 return reinterpret_cast<uword*>(reinterpret_cast<uintptr_t>(this) + |
| 123 reinterpret_cast<uintptr_t>(this) + sizeof(*this)); | 126 sizeof(*this)); |
| 124 } | 127 } |
| 125 | 128 |
| 126 | 129 |
| 127 SampleBuffer::SampleBuffer(intptr_t capacity) { | 130 SampleBuffer::SampleBuffer(intptr_t capacity) { |
| 128 ASSERT(Sample::instance_size() > 0); | 131 ASSERT(Sample::instance_size() > 0); |
| 129 samples_ = reinterpret_cast<Sample*>( | 132 samples_ = |
| 130 calloc(capacity, Sample::instance_size())); | 133 reinterpret_cast<Sample*>(calloc(capacity, Sample::instance_size())); |
| 131 if (FLAG_trace_profiler) { | 134 if (FLAG_trace_profiler) { |
| 132 OS::Print("Profiler holds %" Pd " samples\n", capacity); | 135 OS::Print("Profiler holds %" Pd " samples\n", capacity); |
| 133 OS::Print("Profiler sample is %" Pd " bytes\n", Sample::instance_size()); | 136 OS::Print("Profiler sample is %" Pd " bytes\n", Sample::instance_size()); |
| 134 OS::Print("Profiler memory usage = %" Pd " bytes\n", | 137 OS::Print("Profiler memory usage = %" Pd " bytes\n", |
| 135 capacity * Sample::instance_size()); | 138 capacity * Sample::instance_size()); |
| 136 } | 139 } |
| 137 capacity_ = capacity; | 140 capacity_ = capacity; |
| 138 cursor_ = 0; | 141 cursor_ = 0; |
| 139 } | 142 } |
| 140 | 143 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 } | 190 } |
| 188 | 191 |
| 189 ReturnAddressLocator(uword pc, uword* stack_buffer, const Code& code) | 192 ReturnAddressLocator(uword pc, uword* stack_buffer, const Code& code) |
| 190 : stack_buffer_(stack_buffer), | 193 : stack_buffer_(stack_buffer), |
| 191 pc_(pc), | 194 pc_(pc), |
| 192 code_(Code::ZoneHandle(code.raw())) { | 195 code_(Code::ZoneHandle(code.raw())) { |
| 193 ASSERT(!code_.IsNull()); | 196 ASSERT(!code_.IsNull()); |
| 194 ASSERT(code_.ContainsInstructionAt(pc_)); | 197 ASSERT(code_.ContainsInstructionAt(pc_)); |
| 195 } | 198 } |
| 196 | 199 |
| 197 uword pc() { | 200 uword pc() { return pc_; } |
| 198 return pc_; | |
| 199 } | |
| 200 | 201 |
| 201 // Returns false on failure. | 202 // Returns false on failure. |
| 202 bool LocateReturnAddress(uword* return_address); | 203 bool LocateReturnAddress(uword* return_address); |
| 203 | 204 |
| 204 // Returns offset into code object. | 205 // Returns offset into code object. |
| 205 intptr_t RelativePC() { | 206 intptr_t RelativePC() { |
| 206 ASSERT(pc() >= code_.PayloadStart()); | 207 ASSERT(pc() >= code_.PayloadStart()); |
| 207 return static_cast<intptr_t>(pc() - code_.PayloadStart()); | 208 return static_cast<intptr_t>(pc() - code_.PayloadStart()); |
| 208 } | 209 } |
| 209 | 210 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) { | 297 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) { |
| 297 ASSERT(return_address != NULL); | 298 ASSERT(return_address != NULL); |
| 298 return false; | 299 return false; |
| 299 } | 300 } |
| 300 #else | 301 #else |
| 301 #error ReturnAddressLocator implementation missing for this architecture. | 302 #error ReturnAddressLocator implementation missing for this architecture. |
| 302 #endif | 303 #endif |
| 303 | 304 |
| 304 | 305 |
| 305 bool SampleFilter::TimeFilterSample(Sample* sample) { | 306 bool SampleFilter::TimeFilterSample(Sample* sample) { |
| 306 if ((time_origin_micros_ == -1) || | 307 if ((time_origin_micros_ == -1) || (time_extent_micros_ == -1)) { |
| 307 (time_extent_micros_ == -1)) { | |
| 308 // No time filter passed in, always pass. | 308 // No time filter passed in, always pass. |
| 309 return true; | 309 return true; |
| 310 } | 310 } |
| 311 const int64_t timestamp = sample->timestamp(); | 311 const int64_t timestamp = sample->timestamp(); |
| 312 int64_t delta = timestamp - time_origin_micros_; | 312 int64_t delta = timestamp - time_origin_micros_; |
| 313 return (delta >= 0) && (delta <= time_extent_micros_); | 313 return (delta >= 0) && (delta <= time_extent_micros_); |
| 314 } | 314 } |
| 315 | 315 |
| 316 | 316 |
| 317 bool SampleFilter::TaskFilterSample(Sample* sample) { | 317 bool SampleFilter::TaskFilterSample(Sample* sample) { |
| 318 const intptr_t task = static_cast<intptr_t>(sample->thread_task()); | 318 const intptr_t task = static_cast<intptr_t>(sample->thread_task()); |
| 319 return (task & thread_task_mask_) != 0; | 319 return (task & thread_task_mask_) != 0; |
| 320 } | 320 } |
| 321 | 321 |
| 322 | 322 |
| 323 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) | 323 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) |
| 324 : SampleVisitor(isolate) { | 324 : SampleVisitor(isolate) {} |
| 325 } | |
| 326 | 325 |
| 327 | 326 |
| 328 void ClearProfileVisitor::VisitSample(Sample* sample) { | 327 void ClearProfileVisitor::VisitSample(Sample* sample) { |
| 329 sample->Clear(); | 328 sample->Clear(); |
| 330 } | 329 } |
| 331 | 330 |
| 332 | 331 |
| 333 static void DumpStackFrame(intptr_t frame_index, uword pc) { | 332 static void DumpStackFrame(intptr_t frame_index, uword pc) { |
| 334 uintptr_t start = 0; | 333 uintptr_t start = 0; |
| 335 char* native_symbol_name = | 334 char* native_symbol_name = NativeSymbolResolver::LookupSymbolName(pc, &start); |
| 336 NativeSymbolResolver::LookupSymbolName(pc, &start); | |
| 337 if (native_symbol_name == NULL) { | 335 if (native_symbol_name == NULL) { |
| 338 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc); | 336 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc); |
| 339 } else { | 337 } else { |
| 340 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name); | 338 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name); |
| 341 NativeSymbolResolver::FreeSymbolName(native_symbol_name); | 339 NativeSymbolResolver::FreeSymbolName(native_symbol_name); |
| 342 } | 340 } |
| 343 } | 341 } |
| 344 | 342 |
| 345 | 343 |
| 346 static void DumpStackFrame(intptr_t frame_index, | 344 static void DumpStackFrame(intptr_t frame_index, uword pc, const Code& code) { |
| 347 uword pc, | |
| 348 const Code& code) { | |
| 349 if (code.IsNull()) { | 345 if (code.IsNull()) { |
| 350 DumpStackFrame(frame_index, pc); | 346 DumpStackFrame(frame_index, pc); |
| 351 } else { | 347 } else { |
| 352 OS::PrintErr("Frame[%" Pd "] = Dart:`%s` [0x%" Px "]\n", | 348 OS::PrintErr("Frame[%" Pd "] = Dart:`%s` [0x%" Px "]\n", frame_index, |
| 353 frame_index, code.ToCString(), pc); | 349 code.ToCString(), pc); |
| 354 } | 350 } |
| 355 } | 351 } |
| 356 | 352 |
| 357 | 353 |
| 358 class ProfilerStackWalker : public ValueObject { | 354 class ProfilerStackWalker : public ValueObject { |
| 359 public: | 355 public: |
| 360 ProfilerStackWalker(Isolate* isolate, | 356 ProfilerStackWalker(Isolate* isolate, |
| 361 Sample* head_sample, | 357 Sample* head_sample, |
| 362 SampleBuffer* sample_buffer) | 358 SampleBuffer* sample_buffer) |
| 363 : isolate_(isolate), | 359 : isolate_(isolate), |
| 364 sample_(head_sample), | 360 sample_(head_sample), |
| 365 sample_buffer_(sample_buffer), | 361 sample_buffer_(sample_buffer), |
| 366 frame_index_(0), | 362 frame_index_(0), |
| 367 total_frames_(0) { | 363 total_frames_(0) { |
| 368 ASSERT(isolate_ != NULL); | 364 ASSERT(isolate_ != NULL); |
| 369 if (sample_ == NULL) { | 365 if (sample_ == NULL) { |
| 370 ASSERT(sample_buffer_ == NULL); | 366 ASSERT(sample_buffer_ == NULL); |
| 371 } else { | 367 } else { |
| 372 ASSERT(sample_buffer_ != NULL); | 368 ASSERT(sample_buffer_ != NULL); |
| 373 ASSERT(sample_->head_sample()); | 369 ASSERT(sample_->head_sample()); |
| 374 } | 370 } |
| 375 } | 371 } |
| 376 | 372 |
| 377 bool Append(uword pc, const Code& code) { | 373 bool Append(uword pc, const Code& code) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 | 419 |
| 424 | 420 |
| 425 // Given an exit frame, walk the Dart stack. | 421 // Given an exit frame, walk the Dart stack. |
| 426 class ProfilerDartExitStackWalker : public ProfilerStackWalker { | 422 class ProfilerDartExitStackWalker : public ProfilerStackWalker { |
| 427 public: | 423 public: |
| 428 ProfilerDartExitStackWalker(Thread* thread, | 424 ProfilerDartExitStackWalker(Thread* thread, |
| 429 Isolate* isolate, | 425 Isolate* isolate, |
| 430 Sample* sample, | 426 Sample* sample, |
| 431 SampleBuffer* sample_buffer) | 427 SampleBuffer* sample_buffer) |
| 432 : ProfilerStackWalker(isolate, sample, sample_buffer), | 428 : ProfilerStackWalker(isolate, sample, sample_buffer), |
| 433 frame_iterator_(thread) { | 429 frame_iterator_(thread) {} |
| 434 } | |
| 435 | 430 |
| 436 void walk() { | 431 void walk() { |
| 437 // Mark that this sample was collected from an exit frame. | 432 // Mark that this sample was collected from an exit frame. |
| 438 sample_->set_exit_frame_sample(true); | 433 sample_->set_exit_frame_sample(true); |
| 439 | 434 |
| 440 StackFrame* frame = frame_iterator_.NextFrame(); | 435 StackFrame* frame = frame_iterator_.NextFrame(); |
| 441 if (sample_ == NULL) { | 436 if (sample_ == NULL) { |
| 442 // Only when we are dumping the stack trace for debug purposes. | 437 // Only when we are dumping the stack trace for debug purposes. |
| 443 Code& code = Code::Handle(); | 438 Code& code = Code::Handle(); |
| 444 while (frame != NULL) { | 439 while (frame != NULL) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 | 583 |
| 589 uword* ExitLink() const { | 584 uword* ExitLink() const { |
| 590 ASSERT(fp_ != NULL); | 585 ASSERT(fp_ != NULL); |
| 591 uword* exit_link_ptr = fp_ + kExitLinkSlotFromEntryFp; | 586 uword* exit_link_ptr = fp_ + kExitLinkSlotFromEntryFp; |
| 592 // MSan/ASan are unaware of frames initialized by generated code. | 587 // MSan/ASan are unaware of frames initialized by generated code. |
| 593 MSAN_UNPOISON(exit_link_ptr, kWordSize); | 588 MSAN_UNPOISON(exit_link_ptr, kWordSize); |
| 594 ASAN_UNPOISON(exit_link_ptr, kWordSize); | 589 ASAN_UNPOISON(exit_link_ptr, kWordSize); |
| 595 return reinterpret_cast<uword*>(*exit_link_ptr); | 590 return reinterpret_cast<uword*>(*exit_link_ptr); |
| 596 } | 591 } |
| 597 | 592 |
| 598 bool ValidFramePointer() const { | 593 bool ValidFramePointer() const { return ValidFramePointer(fp_); } |
| 599 return ValidFramePointer(fp_); | |
| 600 } | |
| 601 | 594 |
| 602 bool ValidFramePointer(uword* fp) const { | 595 bool ValidFramePointer(uword* fp) const { |
| 603 if (fp == NULL) { | 596 if (fp == NULL) { |
| 604 return false; | 597 return false; |
| 605 } | 598 } |
| 606 uword cursor = reinterpret_cast<uword>(fp); | 599 uword cursor = reinterpret_cast<uword>(fp); |
| 607 cursor += sizeof(fp); | 600 cursor += sizeof(fp); |
| 608 return (cursor >= stack_lower_) && (cursor < stack_upper_); | 601 return (cursor >= stack_lower_) && (cursor < stack_upper_); |
| 609 } | 602 } |
| 610 | 603 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 628 uword stack_lower, | 621 uword stack_lower, |
| 629 uword stack_upper, | 622 uword stack_upper, |
| 630 uword pc, | 623 uword pc, |
| 631 uword fp, | 624 uword fp, |
| 632 uword sp) | 625 uword sp) |
| 633 : ProfilerStackWalker(isolate, sample, sample_buffer), | 626 : ProfilerStackWalker(isolate, sample, sample_buffer), |
| 634 stack_upper_(stack_upper), | 627 stack_upper_(stack_upper), |
| 635 original_pc_(pc), | 628 original_pc_(pc), |
| 636 original_fp_(fp), | 629 original_fp_(fp), |
| 637 original_sp_(sp), | 630 original_sp_(sp), |
| 638 lower_bound_(stack_lower) { | 631 lower_bound_(stack_lower) {} |
| 639 } | |
| 640 | 632 |
| 641 void walk() { | 633 void walk() { |
| 642 const uword kMaxStep = VirtualMemory::PageSize(); | 634 const uword kMaxStep = VirtualMemory::PageSize(); |
| 643 Append(original_pc_); | 635 Append(original_pc_); |
| 644 | 636 |
| 645 uword* pc = reinterpret_cast<uword*>(original_pc_); | 637 uword* pc = reinterpret_cast<uword*>(original_pc_); |
| 646 uword* fp = reinterpret_cast<uword*>(original_fp_); | 638 uword* fp = reinterpret_cast<uword*>(original_fp_); |
| 647 uword* previous_fp = fp; | 639 uword* previous_fp = fp; |
| 648 | 640 |
| 649 uword gap = original_fp_ - original_sp_; | 641 uword gap = original_fp_ - original_sp_; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 uword pc, | 763 uword pc, |
| 772 uword fp, | 764 uword fp, |
| 773 uword sp, | 765 uword sp, |
| 774 ProfilerCounters* counters) { | 766 ProfilerCounters* counters) { |
| 775 ASSERT(counters != NULL); | 767 ASSERT(counters != NULL); |
| 776 #if defined(TARGET_OS_WINDOWS) | 768 #if defined(TARGET_OS_WINDOWS) |
| 777 // Use structured exception handling to trap guard page access on Windows. | 769 // Use structured exception handling to trap guard page access on Windows. |
| 778 __try { | 770 __try { |
| 779 #endif | 771 #endif |
| 780 | 772 |
| 781 if (in_dart_code) { | 773 if (in_dart_code) { |
| 782 // We can only trust the stack pointer if we are executing Dart code. | 774 // We can only trust the stack pointer if we are executing Dart code. |
| 783 // See http://dartbug.com/20421 for details. | 775 // See http://dartbug.com/20421 for details. |
| 784 CopyStackBuffer(sample, sp); | 776 CopyStackBuffer(sample, sp); |
| 785 } | 777 } |
| 786 | 778 |
| 787 if (FLAG_profile_vm) { | 779 if (FLAG_profile_vm) { |
| 788 // Always walk the native stack collecting both native and Dart frames. | 780 // Always walk the native stack collecting both native and Dart frames. |
| 789 AtomicOperations::IncrementInt64By(&counters->stack_walker_native, 1); | 781 AtomicOperations::IncrementInt64By(&counters->stack_walker_native, 1); |
| 790 native_stack_walker->walk(); | 782 native_stack_walker->walk(); |
| 791 } else if (StubCode::HasBeenInitialized() && exited_dart_code) { | 783 } else if (StubCode::HasBeenInitialized() && exited_dart_code) { |
| 792 AtomicOperations::IncrementInt64By(&counters->stack_walker_dart_exit, 1); | 784 AtomicOperations::IncrementInt64By(&counters->stack_walker_dart_exit, 1); |
| 793 // We have a valid exit frame info, use the Dart stack walker. | 785 // We have a valid exit frame info, use the Dart stack walker. |
| 794 dart_exit_stack_walker->walk(); | 786 dart_exit_stack_walker->walk(); |
| 795 } else if (StubCode::HasBeenInitialized() && in_dart_code) { | 787 } else if (StubCode::HasBeenInitialized() && in_dart_code) { |
| 796 AtomicOperations::IncrementInt64By(&counters->stack_walker_dart, 1); | 788 AtomicOperations::IncrementInt64By(&counters->stack_walker_dart, 1); |
| 797 // We are executing Dart code. We have frame pointers. | 789 // We are executing Dart code. We have frame pointers. |
| 798 dart_stack_walker->walk(); | 790 dart_stack_walker->walk(); |
| 799 } else { | 791 } else { |
| 800 AtomicOperations::IncrementInt64By(&counters->stack_walker_none, 1); | 792 AtomicOperations::IncrementInt64By(&counters->stack_walker_none, 1); |
| 801 sample->SetAt(0, pc); | 793 sample->SetAt(0, pc); |
| 802 } | 794 } |
| 803 | 795 |
| 804 #if defined(TARGET_OS_WINDOWS) | 796 #if defined(TARGET_OS_WINDOWS) |
| 805 // Use structured exception handling to trap guard page access. | 797 // Use structured exception handling to trap guard page access. |
| 806 } __except(GuardPageExceptionFilter(GetExceptionInformation())) { | 798 } __except (GuardPageExceptionFilter(GetExceptionInformation())) { // NOLINT |
| 807 // Sample collection triggered a guard page fault: | 799 // Sample collection triggered a guard page fault: |
| 808 // 1) discard entire sample. | 800 // 1) discard entire sample. |
| 809 sample->set_ignore_sample(true); | 801 sample->set_ignore_sample(true); |
| 810 | 802 |
| 811 // 2) Reenable guard bit on page that triggered the fault. | 803 // 2) Reenable guard bit on page that triggered the fault. |
| 812 // https://goo.gl/5mCsXW | 804 // https://goo.gl/5mCsXW |
| 813 DWORD new_protect = PAGE_READWRITE | PAGE_GUARD; | 805 DWORD new_protect = PAGE_READWRITE | PAGE_GUARD; |
| 814 DWORD old_protect = 0; | 806 DWORD old_protect = 0; |
| 815 BOOL success = VirtualProtect(reinterpret_cast<void*>(fault_address), | 807 BOOL success = |
| 816 sizeof(fault_address), | 808 VirtualProtect(reinterpret_cast<void*>(fault_address), |
| 817 new_protect, | 809 sizeof(fault_address), new_protect, &old_protect); |
| 818 &old_protect); | |
| 819 USE(success); | 810 USE(success); |
| 820 ASSERT(success); | 811 ASSERT(success); |
| 821 ASSERT(old_protect == PAGE_READWRITE); | 812 ASSERT(old_protect == PAGE_READWRITE); |
| 822 } | 813 } |
| 823 #endif | 814 #endif |
| 824 } | 815 } |
| 825 | 816 |
| 826 | 817 |
| 827 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within | 818 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within |
| 828 // it. Return |false| if anything looks suspicious. | 819 // it. Return |false| if anything looks suspicious. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 static bool CheckIsolate(Isolate* isolate) { | 926 static bool CheckIsolate(Isolate* isolate) { |
| 936 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { | 927 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { |
| 937 // No isolate. | 928 // No isolate. |
| 938 return false; | 929 return false; |
| 939 } | 930 } |
| 940 return isolate != Dart::vm_isolate(); | 931 return isolate != Dart::vm_isolate(); |
| 941 } | 932 } |
| 942 | 933 |
| 943 | 934 |
| 944 #if defined(TARGET_OS_WINDOWS) | 935 #if defined(TARGET_OS_WINDOWS) |
| 945 __declspec(noinline) | 936 __declspec(noinline) static uintptr_t GetProgramCounter() { |
| 946 static uintptr_t GetProgramCounter() { | |
| 947 return reinterpret_cast<uintptr_t>(_ReturnAddress()); | 937 return reinterpret_cast<uintptr_t>(_ReturnAddress()); |
| 948 } | 938 } |
| 949 #else | 939 #else |
| 950 static uintptr_t __attribute__((noinline)) GetProgramCounter() { | 940 static uintptr_t __attribute__((noinline)) GetProgramCounter() { |
| 951 return reinterpret_cast<uintptr_t>( | 941 return reinterpret_cast<uintptr_t>( |
| 952 __builtin_extract_return_addr(__builtin_return_address(0))); | 942 __builtin_extract_return_addr(__builtin_return_address(0))); |
| 953 } | 943 } |
| 954 #endif | 944 #endif |
| 955 | 945 |
| 956 | 946 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 983 uintptr_t sp = Thread::GetCurrentStackPointer(); | 973 uintptr_t sp = Thread::GetCurrentStackPointer(); |
| 984 uintptr_t fp = 0; | 974 uintptr_t fp = 0; |
| 985 uintptr_t pc = GetProgramCounter(); | 975 uintptr_t pc = GetProgramCounter(); |
| 986 | 976 |
| 987 COPY_FP_REGISTER(fp); | 977 COPY_FP_REGISTER(fp); |
| 988 | 978 |
| 989 uword stack_lower = 0; | 979 uword stack_lower = 0; |
| 990 uword stack_upper = 0; | 980 uword stack_upper = 0; |
| 991 | 981 |
| 992 if (!InitialRegisterCheck(pc, fp, sp)) { | 982 if (!InitialRegisterCheck(pc, fp, sp)) { |
| 993 OS::PrintErr( | 983 OS::PrintErr("Stack dump aborted because InitialRegisterCheck.\n"); |
| 994 "Stack dump aborted because InitialRegisterCheck.\n"); | |
| 995 return; | 984 return; |
| 996 } | 985 } |
| 997 | 986 |
| 998 if (!GetAndValidateIsolateStackBounds(thread, | 987 if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower, |
| 999 fp, | |
| 1000 sp, | |
| 1001 &stack_lower, | |
| 1002 &stack_upper)) { | 988 &stack_upper)) { |
| 1003 OS::PrintErr( | 989 OS::PrintErr( |
| 1004 "Stack dump aborted because GetAndValidateIsolateStackBounds.\n"); | 990 "Stack dump aborted because GetAndValidateIsolateStackBounds.\n"); |
| 1005 return; | 991 return; |
| 1006 } | 992 } |
| 1007 | 993 |
| 1008 if (native_stack_trace) { | 994 if (native_stack_trace) { |
| 1009 ProfilerNativeStackWalker native_stack_walker(isolate, | 995 ProfilerNativeStackWalker native_stack_walker( |
| 1010 NULL, | 996 isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp); |
| 1011 NULL, | |
| 1012 stack_lower, | |
| 1013 stack_upper, | |
| 1014 pc, | |
| 1015 fp, | |
| 1016 sp); | |
| 1017 native_stack_walker.walk(); | 997 native_stack_walker.walk(); |
| 1018 } else if (exited_dart_code) { | 998 } else if (exited_dart_code) { |
| 1019 ProfilerDartExitStackWalker dart_exit_stack_walker(thread, | 999 ProfilerDartExitStackWalker dart_exit_stack_walker(thread, isolate, NULL, |
| 1020 isolate, | |
| 1021 NULL, | |
| 1022 NULL); | 1000 NULL); |
| 1023 dart_exit_stack_walker.walk(); | 1001 dart_exit_stack_walker.walk(); |
| 1024 } else { | 1002 } else { |
| 1025 ProfilerDartStackWalker dart_stack_walker(isolate, | 1003 ProfilerDartStackWalker dart_stack_walker(isolate, NULL, NULL, stack_lower, |
| 1026 NULL, | 1004 stack_upper, pc, fp, sp); |
| 1027 NULL, | |
| 1028 stack_lower, | |
| 1029 stack_upper, | |
| 1030 pc, | |
| 1031 fp, | |
| 1032 sp); | |
| 1033 } | 1005 } |
| 1034 OS::PrintErr("-- End of DumpStackTrace\n"); | 1006 OS::PrintErr("-- End of DumpStackTrace\n"); |
| 1035 } | 1007 } |
| 1036 | 1008 |
| 1037 | 1009 |
| 1038 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { | 1010 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { |
| 1039 ASSERT(thread != NULL); | 1011 ASSERT(thread != NULL); |
| 1040 OSThread* os_thread = thread->os_thread(); | 1012 OSThread* os_thread = thread->os_thread(); |
| 1041 ASSERT(os_thread != NULL); | 1013 ASSERT(os_thread != NULL); |
| 1042 Isolate* isolate = thread->isolate(); | 1014 Isolate* isolate = thread->isolate(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1059 | 1031 |
| 1060 COPY_FP_REGISTER(fp); | 1032 COPY_FP_REGISTER(fp); |
| 1061 | 1033 |
| 1062 uword stack_lower = 0; | 1034 uword stack_lower = 0; |
| 1063 uword stack_upper = 0; | 1035 uword stack_upper = 0; |
| 1064 | 1036 |
| 1065 if (!InitialRegisterCheck(pc, fp, sp)) { | 1037 if (!InitialRegisterCheck(pc, fp, sp)) { |
| 1066 return; | 1038 return; |
| 1067 } | 1039 } |
| 1068 | 1040 |
| 1069 if (!GetAndValidateIsolateStackBounds(thread, | 1041 if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower, |
| 1070 fp, | |
| 1071 sp, | |
| 1072 &stack_lower, | |
| 1073 &stack_upper)) { | 1042 &stack_upper)) { |
| 1074 // Could not get stack boundary. | 1043 // Could not get stack boundary. |
| 1075 return; | 1044 return; |
| 1076 } | 1045 } |
| 1077 | 1046 |
| 1078 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1047 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
| 1079 sample->SetAllocationCid(cid); | 1048 sample->SetAllocationCid(cid); |
| 1080 ProfilerNativeStackWalker native_stack_walker(isolate, | 1049 ProfilerNativeStackWalker native_stack_walker( |
| 1081 sample, | 1050 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); |
| 1082 sample_buffer, | |
| 1083 stack_lower, | |
| 1084 stack_upper, | |
| 1085 pc, | |
| 1086 fp, | |
| 1087 sp); | |
| 1088 native_stack_walker.walk(); | 1051 native_stack_walker.walk(); |
| 1089 } else if (exited_dart_code) { | 1052 } else if (exited_dart_code) { |
| 1090 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1053 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
| 1091 sample->SetAllocationCid(cid); | 1054 sample->SetAllocationCid(cid); |
| 1092 ProfilerDartExitStackWalker dart_exit_stack_walker(thread, | 1055 ProfilerDartExitStackWalker dart_exit_stack_walker(thread, isolate, sample, |
| 1093 isolate, | |
| 1094 sample, | |
| 1095 sample_buffer); | 1056 sample_buffer); |
| 1096 dart_exit_stack_walker.walk(); | 1057 dart_exit_stack_walker.walk(); |
| 1097 } else { | 1058 } else { |
| 1098 // Fall back. | 1059 // Fall back. |
| 1099 uintptr_t pc = GetProgramCounter(); | 1060 uintptr_t pc = GetProgramCounter(); |
| 1100 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1061 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
| 1101 sample->SetAllocationCid(cid); | 1062 sample->SetAllocationCid(cid); |
| 1102 sample->SetAt(0, pc); | 1063 sample->SetAt(0, pc); |
| 1103 } | 1064 } |
| 1104 } | 1065 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 const bool in_dart_code = thread->IsExecutingDartCode(); | 1117 const bool in_dart_code = thread->IsExecutingDartCode(); |
| 1157 | 1118 |
| 1158 uintptr_t sp = 0; | 1119 uintptr_t sp = 0; |
| 1159 uintptr_t fp = state.fp; | 1120 uintptr_t fp = state.fp; |
| 1160 uintptr_t pc = state.pc; | 1121 uintptr_t pc = state.pc; |
| 1161 #if defined(USING_SIMULATOR) | 1122 #if defined(USING_SIMULATOR) |
| 1162 Simulator* simulator = NULL; | 1123 Simulator* simulator = NULL; |
| 1163 #endif | 1124 #endif |
| 1164 | 1125 |
| 1165 if (in_dart_code) { | 1126 if (in_dart_code) { |
| 1166 // If we're in Dart code, use the Dart stack pointer. | 1127 // If we're in Dart code, use the Dart stack pointer. |
| 1167 #if defined(TARGET_ARCH_DBC) | 1128 #if defined(TARGET_ARCH_DBC) |
| 1168 simulator = isolate->simulator(); | 1129 simulator = isolate->simulator(); |
| 1169 sp = simulator->get_sp(); | 1130 sp = simulator->get_sp(); |
| 1170 fp = simulator->get_fp(); | 1131 fp = simulator->get_fp(); |
| 1171 pc = simulator->get_pc(); | 1132 pc = simulator->get_pc(); |
| 1172 #elif defined(USING_SIMULATOR) | 1133 #elif defined(USING_SIMULATOR) |
| 1173 simulator = isolate->simulator(); | 1134 simulator = isolate->simulator(); |
| 1174 sp = simulator->get_register(SPREG); | 1135 sp = simulator->get_register(SPREG); |
| 1175 fp = simulator->get_register(FPREG); | 1136 fp = simulator->get_register(FPREG); |
| 1176 pc = simulator->get_pc(); | 1137 pc = simulator->get_pc(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1196 | 1157 |
| 1197 if (!InitialRegisterCheck(pc, fp, sp)) { | 1158 if (!InitialRegisterCheck(pc, fp, sp)) { |
| 1198 AtomicOperations::IncrementInt64By( | 1159 AtomicOperations::IncrementInt64By( |
| 1199 &counters_.single_frame_sample_register_check, 1); | 1160 &counters_.single_frame_sample_register_check, 1); |
| 1200 SampleThreadSingleFrame(thread, pc); | 1161 SampleThreadSingleFrame(thread, pc); |
| 1201 return; | 1162 return; |
| 1202 } | 1163 } |
| 1203 | 1164 |
| 1204 uword stack_lower = 0; | 1165 uword stack_lower = 0; |
| 1205 uword stack_upper = 0; | 1166 uword stack_upper = 0; |
| 1206 if (!GetAndValidateIsolateStackBounds(thread, | 1167 if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower, |
| 1207 fp, | |
| 1208 sp, | |
| 1209 &stack_lower, | |
| 1210 &stack_upper)) { | 1168 &stack_upper)) { |
| 1211 AtomicOperations::IncrementInt64By( | 1169 AtomicOperations::IncrementInt64By( |
| 1212 &counters_.single_frame_sample_get_and_validate_stack_bounds, 1); | 1170 &counters_.single_frame_sample_get_and_validate_stack_bounds, 1); |
| 1213 // Could not get stack boundary. | 1171 // Could not get stack boundary. |
| 1214 SampleThreadSingleFrame(thread, pc); | 1172 SampleThreadSingleFrame(thread, pc); |
| 1215 return; | 1173 return; |
| 1216 } | 1174 } |
| 1217 | 1175 |
| 1218 // At this point we have a valid stack boundary for this isolate and | 1176 // At this point we have a valid stack boundary for this isolate and |
| 1219 // know that our initial stack and frame pointers are within the boundary. | 1177 // know that our initial stack and frame pointers are within the boundary. |
| 1220 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | 1178 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
| 1221 if (sample_buffer == NULL) { | 1179 if (sample_buffer == NULL) { |
| 1222 // Profiler not initialized. | 1180 // Profiler not initialized. |
| 1223 return; | 1181 return; |
| 1224 } | 1182 } |
| 1225 | 1183 |
| 1226 // Setup sample. | 1184 // Setup sample. |
| 1227 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1185 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
| 1228 // Increment counter for vm tag. | 1186 // Increment counter for vm tag. |
| 1229 VMTagCounters* counters = isolate->vm_tag_counters(); | 1187 VMTagCounters* counters = isolate->vm_tag_counters(); |
| 1230 ASSERT(counters != NULL); | 1188 ASSERT(counters != NULL); |
| 1231 if (thread->IsMutatorThread()) { | 1189 if (thread->IsMutatorThread()) { |
| 1232 counters->Increment(sample->vm_tag()); | 1190 counters->Increment(sample->vm_tag()); |
| 1233 } | 1191 } |
| 1234 | 1192 |
| 1235 ProfilerNativeStackWalker native_stack_walker(isolate, | 1193 ProfilerNativeStackWalker native_stack_walker( |
| 1236 sample, | 1194 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); |
| 1237 sample_buffer, | |
| 1238 stack_lower, | |
| 1239 stack_upper, | |
| 1240 pc, | |
| 1241 fp, | |
| 1242 sp); | |
| 1243 | 1195 |
| 1244 ProfilerDartExitStackWalker dart_exit_stack_walker(thread, | 1196 ProfilerDartExitStackWalker dart_exit_stack_walker(thread, isolate, sample, |
| 1245 isolate, | |
| 1246 sample, | |
| 1247 sample_buffer); | 1197 sample_buffer); |
| 1248 | 1198 |
| 1249 ProfilerDartStackWalker dart_stack_walker(isolate, | 1199 ProfilerDartStackWalker dart_stack_walker( |
| 1250 sample, | 1200 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); |
| 1251 sample_buffer, | |
| 1252 stack_lower, | |
| 1253 stack_upper, | |
| 1254 pc, | |
| 1255 fp, | |
| 1256 sp); | |
| 1257 | 1201 |
| 1258 const bool exited_dart_code = thread->HasExitedDartCode(); | 1202 const bool exited_dart_code = thread->HasExitedDartCode(); |
| 1259 | 1203 |
| 1260 // All memory access is done inside CollectSample. | 1204 // All memory access is done inside CollectSample. |
| 1261 CollectSample(isolate, | 1205 CollectSample(isolate, exited_dart_code, in_dart_code, sample, |
| 1262 exited_dart_code, | 1206 &native_stack_walker, &dart_exit_stack_walker, |
| 1263 in_dart_code, | 1207 &dart_stack_walker, pc, fp, sp, &counters_); |
| 1264 sample, | |
| 1265 &native_stack_walker, | |
| 1266 &dart_exit_stack_walker, | |
| 1267 &dart_stack_walker, | |
| 1268 pc, | |
| 1269 fp, | |
| 1270 sp, | |
| 1271 &counters_); | |
| 1272 } | 1208 } |
| 1273 | 1209 |
| 1274 | 1210 |
| 1275 | |
| 1276 CodeDescriptor::CodeDescriptor(const Code& code) : code_(code) { | 1211 CodeDescriptor::CodeDescriptor(const Code& code) : code_(code) { |
| 1277 ASSERT(!code_.IsNull()); | 1212 ASSERT(!code_.IsNull()); |
| 1278 } | 1213 } |
| 1279 | 1214 |
| 1280 | 1215 |
| 1281 uword CodeDescriptor::Start() const { | 1216 uword CodeDescriptor::Start() const { |
| 1282 return code_.PayloadStart(); | 1217 return code_.PayloadStart(); |
| 1283 } | 1218 } |
| 1284 | 1219 |
| 1285 | 1220 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1297 Build(thread); | 1232 Build(thread); |
| 1298 } | 1233 } |
| 1299 | 1234 |
| 1300 | 1235 |
| 1301 class CodeLookupTableBuilder : public ObjectVisitor { | 1236 class CodeLookupTableBuilder : public ObjectVisitor { |
| 1302 public: | 1237 public: |
| 1303 explicit CodeLookupTableBuilder(CodeLookupTable* table) : table_(table) { | 1238 explicit CodeLookupTableBuilder(CodeLookupTable* table) : table_(table) { |
| 1304 ASSERT(table_ != NULL); | 1239 ASSERT(table_ != NULL); |
| 1305 } | 1240 } |
| 1306 | 1241 |
| 1307 ~CodeLookupTableBuilder() { | 1242 ~CodeLookupTableBuilder() {} |
| 1308 } | |
| 1309 | 1243 |
| 1310 void VisitObject(RawObject* raw_obj) { | 1244 void VisitObject(RawObject* raw_obj) { |
| 1311 uword tags = raw_obj->ptr()->tags_; | 1245 uword tags = raw_obj->ptr()->tags_; |
| 1312 if (RawObject::ClassIdTag::decode(tags) == kCodeCid) { | 1246 if (RawObject::ClassIdTag::decode(tags) == kCodeCid) { |
| 1313 RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj); | 1247 RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj); |
| 1314 const Code& code = Code::Handle(raw_code); | 1248 const Code& code = Code::Handle(raw_code); |
| 1315 ASSERT(!code.IsNull()); | 1249 ASSERT(!code.IsNull()); |
| 1316 const Instructions& instructions = | 1250 const Instructions& instructions = |
| 1317 Instructions::Handle(code.instructions()); | 1251 Instructions::Handle(code.instructions()); |
| 1318 ASSERT(!instructions.IsNull()); | 1252 ASSERT(!instructions.IsNull()); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 return NULL; | 1335 return NULL; |
| 1402 } | 1336 } |
| 1403 | 1337 |
| 1404 | 1338 |
| 1405 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( | 1339 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( |
| 1406 SampleFilter* filter) { | 1340 SampleFilter* filter) { |
| 1407 ASSERT(filter != NULL); | 1341 ASSERT(filter != NULL); |
| 1408 Thread* thread = Thread::Current(); | 1342 Thread* thread = Thread::Current(); |
| 1409 Zone* zone = thread->zone(); | 1343 Zone* zone = thread->zone(); |
| 1410 | 1344 |
| 1411 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer(); | 1345 ProcessedSampleBuffer* buffer = new (zone) ProcessedSampleBuffer(); |
| 1412 | 1346 |
| 1413 const intptr_t length = capacity(); | 1347 const intptr_t length = capacity(); |
| 1414 for (intptr_t i = 0; i < length; i++) { | 1348 for (intptr_t i = 0; i < length; i++) { |
| 1415 Sample* sample = At(i); | 1349 Sample* sample = At(i); |
| 1416 if (sample->ignore_sample()) { | 1350 if (sample->ignore_sample()) { |
| 1417 // Bad sample. | 1351 // Bad sample. |
| 1418 continue; | 1352 continue; |
| 1419 } | 1353 } |
| 1420 if (!sample->head_sample()) { | 1354 if (!sample->head_sample()) { |
| 1421 // An inner sample in a chain of samples. | 1355 // An inner sample in a chain of samples. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1450 return buffer; | 1384 return buffer; |
| 1451 } | 1385 } |
| 1452 | 1386 |
| 1453 | 1387 |
| 1454 ProcessedSample* SampleBuffer::BuildProcessedSample( | 1388 ProcessedSample* SampleBuffer::BuildProcessedSample( |
| 1455 Sample* sample, | 1389 Sample* sample, |
| 1456 const CodeLookupTable& clt) { | 1390 const CodeLookupTable& clt) { |
| 1457 Thread* thread = Thread::Current(); | 1391 Thread* thread = Thread::Current(); |
| 1458 Zone* zone = thread->zone(); | 1392 Zone* zone = thread->zone(); |
| 1459 | 1393 |
| 1460 ProcessedSample* processed_sample = new(zone) ProcessedSample(); | 1394 ProcessedSample* processed_sample = new (zone) ProcessedSample(); |
| 1461 | 1395 |
| 1462 // Copy state bits from sample. | 1396 // Copy state bits from sample. |
| 1463 processed_sample->set_timestamp(sample->timestamp()); | 1397 processed_sample->set_timestamp(sample->timestamp()); |
| 1464 processed_sample->set_tid(sample->tid()); | 1398 processed_sample->set_tid(sample->tid()); |
| 1465 processed_sample->set_vm_tag(sample->vm_tag()); | 1399 processed_sample->set_vm_tag(sample->vm_tag()); |
| 1466 processed_sample->set_user_tag(sample->user_tag()); | 1400 processed_sample->set_user_tag(sample->user_tag()); |
| 1467 if (sample->is_allocation_sample()) { | 1401 if (sample->is_allocation_sample()) { |
| 1468 processed_sample->set_allocation_cid(sample->allocation_cid()); | 1402 processed_sample->set_allocation_cid(sample->allocation_cid()); |
| 1469 } | 1403 } |
| 1470 processed_sample->set_first_frame_executing(!sample->exit_frame_sample()); | 1404 processed_sample->set_first_frame_executing(!sample->exit_frame_sample()); |
| 1471 | 1405 |
| 1472 // Copy stack trace from sample(s). | 1406 // Copy stack trace from sample(s). |
| 1473 bool truncated = false; | 1407 bool truncated = false; |
| 1474 Sample* current = sample; | 1408 Sample* current = sample; |
| 1475 while (current != NULL) { | 1409 while (current != NULL) { |
| 1476 for (intptr_t i = 0; i < kSampleSize; i++) { | 1410 for (intptr_t i = 0; i < kSampleSize; i++) { |
| 1477 if (current->At(i) == 0) { | 1411 if (current->At(i) == 0) { |
| 1478 break; | 1412 break; |
| 1479 } | 1413 } |
| 1480 processed_sample->Add(current->At(i)); | 1414 processed_sample->Add(current->At(i)); |
| 1481 } | 1415 } |
| 1482 | 1416 |
| 1483 truncated = truncated || current->truncated_trace(); | 1417 truncated = truncated || current->truncated_trace(); |
| 1484 current = Next(current); | 1418 current = Next(current); |
| 1485 } | 1419 } |
| 1486 | 1420 |
| 1487 if (!sample->exit_frame_sample()) { | 1421 if (!sample->exit_frame_sample()) { |
| 1488 processed_sample->FixupCaller(clt, | 1422 processed_sample->FixupCaller(clt, sample->pc_marker(), |
| 1489 sample->pc_marker(), | |
| 1490 sample->GetStackBuffer()); | 1423 sample->GetStackBuffer()); |
| 1491 } | 1424 } |
| 1492 | 1425 |
| 1493 processed_sample->set_truncated(truncated); | 1426 processed_sample->set_truncated(truncated); |
| 1494 return processed_sample; | 1427 return processed_sample; |
| 1495 } | 1428 } |
| 1496 | 1429 |
| 1497 | 1430 |
| 1498 Sample* SampleBuffer::Next(Sample* sample) { | 1431 Sample* SampleBuffer::Next(Sample* sample) { |
| 1499 if (!sample->is_continuation_sample()) | 1432 if (!sample->is_continuation_sample()) return NULL; |
| 1500 return NULL; | |
| 1501 Sample* next_sample = At(sample->continuation_index()); | 1433 Sample* next_sample = At(sample->continuation_index()); |
| 1502 // Sanity check. | 1434 // Sanity check. |
| 1503 ASSERT(sample != next_sample); | 1435 ASSERT(sample != next_sample); |
| 1504 // Detect invalid chaining. | 1436 // Detect invalid chaining. |
| 1505 if (sample->isolate() != next_sample->isolate()) { | 1437 if (sample->isolate() != next_sample->isolate()) { |
| 1506 return NULL; | 1438 return NULL; |
| 1507 } | 1439 } |
| 1508 if (sample->timestamp() != next_sample->timestamp()) { | 1440 if (sample->timestamp() != next_sample->timestamp()) { |
| 1509 return NULL; | 1441 return NULL; |
| 1510 } | 1442 } |
| 1511 if (sample->tid() != next_sample->tid()) { | 1443 if (sample->tid() != next_sample->tid()) { |
| 1512 return NULL; | 1444 return NULL; |
| 1513 } | 1445 } |
| 1514 return next_sample; | 1446 return next_sample; |
| 1515 } | 1447 } |
| 1516 | 1448 |
| 1517 | 1449 |
| 1518 ProcessedSample::ProcessedSample() | 1450 ProcessedSample::ProcessedSample() |
| 1519 : pcs_(kSampleSize), | 1451 : pcs_(kSampleSize), |
| 1520 timestamp_(0), | 1452 timestamp_(0), |
| 1521 vm_tag_(0), | 1453 vm_tag_(0), |
| 1522 user_tag_(0), | 1454 user_tag_(0), |
| 1523 allocation_cid_(-1), | 1455 allocation_cid_(-1), |
| 1524 truncated_(false), | 1456 truncated_(false), |
| 1525 timeline_trie_(NULL) { | 1457 timeline_trie_(NULL) {} |
| 1526 } | |
| 1527 | 1458 |
| 1528 | 1459 |
| 1529 void ProcessedSample::FixupCaller(const CodeLookupTable& clt, | 1460 void ProcessedSample::FixupCaller(const CodeLookupTable& clt, |
| 1530 uword pc_marker, | 1461 uword pc_marker, |
| 1531 uword* stack_buffer) { | 1462 uword* stack_buffer) { |
| 1532 const CodeDescriptor* cd = clt.FindCode(At(0)); | 1463 const CodeDescriptor* cd = clt.FindCode(At(0)); |
| 1533 if (cd == NULL) { | 1464 if (cd == NULL) { |
| 1534 // No Dart code. | 1465 // No Dart code. |
| 1535 return; | 1466 return; |
| 1536 } | 1467 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1598 | 1529 |
| 1599 | 1530 |
| 1600 ProcessedSampleBuffer::ProcessedSampleBuffer() | 1531 ProcessedSampleBuffer::ProcessedSampleBuffer() |
| 1601 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { | 1532 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { |
| 1602 ASSERT(code_lookup_table_ != NULL); | 1533 ASSERT(code_lookup_table_ != NULL); |
| 1603 } | 1534 } |
| 1604 | 1535 |
| 1605 #endif // !PRODUCT | 1536 #endif // !PRODUCT |
| 1606 | 1537 |
| 1607 } // namespace dart | 1538 } // namespace dart |
| OLD | NEW |