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 |