Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: runtime/vm/profiler.cc

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_service.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 sample_buffer_ = new SampleBuffer(); 72 sample_buffer_ = new SampleBuffer();
73 Profiler::InitAllocationSampleBuffer(); 73 Profiler::InitAllocationSampleBuffer();
74 // Zero counters. 74 // Zero counters.
75 memset(&counters_, 0, sizeof(counters_)); 75 memset(&counters_, 0, sizeof(counters_));
76 NativeSymbolResolver::InitOnce(); 76 NativeSymbolResolver::InitOnce();
77 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period); 77 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
78 ThreadInterrupter::Startup(); 78 ThreadInterrupter::Startup();
79 initialized_ = true; 79 initialized_ = true;
80 } 80 }
81 81
82
83 void Profiler::InitAllocationSampleBuffer() { 82 void Profiler::InitAllocationSampleBuffer() {
84 if (FLAG_profiler_native_memory && 83 if (FLAG_profiler_native_memory &&
85 (Profiler::allocation_sample_buffer_ == NULL)) { 84 (Profiler::allocation_sample_buffer_ == NULL)) {
86 Profiler::allocation_sample_buffer_ = new AllocationSampleBuffer(); 85 Profiler::allocation_sample_buffer_ = new AllocationSampleBuffer();
87 } 86 }
88 } 87 }
89 88
90
91 void Profiler::Shutdown() { 89 void Profiler::Shutdown() {
92 if (!FLAG_profiler) { 90 if (!FLAG_profiler) {
93 return; 91 return;
94 } 92 }
95 ASSERT(initialized_); 93 ASSERT(initialized_);
96 ThreadInterrupter::Shutdown(); 94 ThreadInterrupter::Shutdown();
97 NativeSymbolResolver::ShutdownOnce(); 95 NativeSymbolResolver::ShutdownOnce();
98 } 96 }
99 97
100
101 void Profiler::SetSampleDepth(intptr_t depth) { 98 void Profiler::SetSampleDepth(intptr_t depth) {
102 const int kMinimumDepth = 2; 99 const int kMinimumDepth = 2;
103 const int kMaximumDepth = 255; 100 const int kMaximumDepth = 255;
104 if (depth < kMinimumDepth) { 101 if (depth < kMinimumDepth) {
105 FLAG_max_profile_depth = kMinimumDepth; 102 FLAG_max_profile_depth = kMinimumDepth;
106 } else if (depth > kMaximumDepth) { 103 } else if (depth > kMaximumDepth) {
107 FLAG_max_profile_depth = kMaximumDepth; 104 FLAG_max_profile_depth = kMaximumDepth;
108 } else { 105 } else {
109 FLAG_max_profile_depth = depth; 106 FLAG_max_profile_depth = depth;
110 } 107 }
111 } 108 }
112 109
113
114 void Profiler::SetSamplePeriod(intptr_t period) { 110 void Profiler::SetSamplePeriod(intptr_t period) {
115 const int kMinimumProfilePeriod = 50; 111 const int kMinimumProfilePeriod = 50;
116 if (period < kMinimumProfilePeriod) { 112 if (period < kMinimumProfilePeriod) {
117 FLAG_profile_period = kMinimumProfilePeriod; 113 FLAG_profile_period = kMinimumProfilePeriod;
118 } else { 114 } else {
119 FLAG_profile_period = period; 115 FLAG_profile_period = period;
120 } 116 }
121 } 117 }
122 118
123
124 intptr_t Sample::pcs_length_ = 0; 119 intptr_t Sample::pcs_length_ = 0;
125 intptr_t Sample::instance_size_ = 0; 120 intptr_t Sample::instance_size_ = 0;
126 121
127
128 void Sample::InitOnce() { 122 void Sample::InitOnce() {
129 pcs_length_ = kSampleSize; 123 pcs_length_ = kSampleSize;
130 instance_size_ = sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT. 124 instance_size_ = sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT.
131 } 125 }
132 126
133
134 uword* Sample::GetPCArray() const { 127 uword* Sample::GetPCArray() const {
135 return reinterpret_cast<uword*>(reinterpret_cast<uintptr_t>(this) + 128 return reinterpret_cast<uword*>(reinterpret_cast<uintptr_t>(this) +
136 sizeof(*this)); 129 sizeof(*this));
137 } 130 }
138 131
139
140 SampleBuffer::SampleBuffer(intptr_t capacity) { 132 SampleBuffer::SampleBuffer(intptr_t capacity) {
141 ASSERT(Sample::instance_size() > 0); 133 ASSERT(Sample::instance_size() > 0);
142 134
143 const intptr_t size = Utils::RoundUp(capacity * Sample::instance_size(), 135 const intptr_t size = Utils::RoundUp(capacity * Sample::instance_size(),
144 VirtualMemory::PageSize()); 136 VirtualMemory::PageSize());
145 const bool kNotExecutable = false; 137 const bool kNotExecutable = false;
146 memory_ = VirtualMemory::Reserve(size); 138 memory_ = VirtualMemory::Reserve(size);
147 if ((memory_ == NULL) || !memory_->Commit(kNotExecutable, "dart-profiler")) { 139 if ((memory_ == NULL) || !memory_->Commit(kNotExecutable, "dart-profiler")) {
148 OUT_OF_MEMORY(); 140 OUT_OF_MEMORY();
149 } 141 }
150 142
151 samples_ = reinterpret_cast<Sample*>(memory_->address()); 143 samples_ = reinterpret_cast<Sample*>(memory_->address());
152 capacity_ = capacity; 144 capacity_ = capacity;
153 cursor_ = 0; 145 cursor_ = 0;
154 146
155 if (FLAG_trace_profiler) { 147 if (FLAG_trace_profiler) {
156 OS::Print("Profiler holds %" Pd " samples\n", capacity); 148 OS::Print("Profiler holds %" Pd " samples\n", capacity);
157 OS::Print("Profiler sample is %" Pd " bytes\n", Sample::instance_size()); 149 OS::Print("Profiler sample is %" Pd " bytes\n", Sample::instance_size());
158 OS::Print("Profiler memory usage = %" Pd " bytes\n", size); 150 OS::Print("Profiler memory usage = %" Pd " bytes\n", size);
159 } 151 }
160 } 152 }
161 153
162
163 AllocationSampleBuffer::AllocationSampleBuffer(intptr_t capacity) 154 AllocationSampleBuffer::AllocationSampleBuffer(intptr_t capacity)
164 : SampleBuffer(capacity), mutex_(new Mutex()) {} 155 : SampleBuffer(capacity), mutex_(new Mutex()) {}
165 156
166
167 SampleBuffer::~SampleBuffer() { 157 SampleBuffer::~SampleBuffer() {
168 delete memory_; 158 delete memory_;
169 } 159 }
170 160
171
172 AllocationSampleBuffer::~AllocationSampleBuffer() { 161 AllocationSampleBuffer::~AllocationSampleBuffer() {
173 delete mutex_; 162 delete mutex_;
174 } 163 }
175 164
176
177 Sample* SampleBuffer::At(intptr_t idx) const { 165 Sample* SampleBuffer::At(intptr_t idx) const {
178 ASSERT(idx >= 0); 166 ASSERT(idx >= 0);
179 ASSERT(idx < capacity_); 167 ASSERT(idx < capacity_);
180 intptr_t offset = idx * Sample::instance_size(); 168 intptr_t offset = idx * Sample::instance_size();
181 uint8_t* samples = reinterpret_cast<uint8_t*>(samples_); 169 uint8_t* samples = reinterpret_cast<uint8_t*>(samples_);
182 return reinterpret_cast<Sample*>(samples + offset); 170 return reinterpret_cast<Sample*>(samples + offset);
183 } 171 }
184 172
185
186 intptr_t SampleBuffer::ReserveSampleSlot() { 173 intptr_t SampleBuffer::ReserveSampleSlot() {
187 ASSERT(samples_ != NULL); 174 ASSERT(samples_ != NULL);
188 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); 175 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
189 // Map back into sample buffer range. 176 // Map back into sample buffer range.
190 cursor = cursor % capacity_; 177 cursor = cursor % capacity_;
191 return cursor; 178 return cursor;
192 } 179 }
193 180
194
195 Sample* SampleBuffer::ReserveSample() { 181 Sample* SampleBuffer::ReserveSample() {
196 return At(ReserveSampleSlot()); 182 return At(ReserveSampleSlot());
197 } 183 }
198 184
199
200 Sample* SampleBuffer::ReserveSampleAndLink(Sample* previous) { 185 Sample* SampleBuffer::ReserveSampleAndLink(Sample* previous) {
201 ASSERT(previous != NULL); 186 ASSERT(previous != NULL);
202 intptr_t next_index = ReserveSampleSlot(); 187 intptr_t next_index = ReserveSampleSlot();
203 Sample* next = At(next_index); 188 Sample* next = At(next_index);
204 next->Init(previous->port(), previous->timestamp(), previous->tid()); 189 next->Init(previous->port(), previous->timestamp(), previous->tid());
205 next->set_head_sample(false); 190 next->set_head_sample(false);
206 // Mark that previous continues at next. 191 // Mark that previous continues at next.
207 previous->SetContinuationIndex(next_index); 192 previous->SetContinuationIndex(next_index);
208 return next; 193 return next;
209 } 194 }
210 195
211
212 void AllocationSampleBuffer::FreeAllocationSample(Sample* sample) { 196 void AllocationSampleBuffer::FreeAllocationSample(Sample* sample) {
213 MutexLocker ml(mutex_); 197 MutexLocker ml(mutex_);
214 while (sample != NULL) { 198 while (sample != NULL) {
215 intptr_t continuation_index = -1; 199 intptr_t continuation_index = -1;
216 if (sample->is_continuation_sample()) { 200 if (sample->is_continuation_sample()) {
217 continuation_index = sample->continuation_index(); 201 continuation_index = sample->continuation_index();
218 } 202 }
219 sample->Clear(); 203 sample->Clear();
220 sample->set_next_free(free_sample_list_); 204 sample->set_next_free(free_sample_list_);
221 free_sample_list_ = sample; 205 free_sample_list_ = sample;
222 206
223 if (continuation_index != -1) { 207 if (continuation_index != -1) {
224 sample = At(continuation_index); 208 sample = At(continuation_index);
225 } else { 209 } else {
226 sample = NULL; 210 sample = NULL;
227 } 211 }
228 } 212 }
229 } 213 }
230 214
231
232 intptr_t AllocationSampleBuffer::ReserveSampleSlotLocked() { 215 intptr_t AllocationSampleBuffer::ReserveSampleSlotLocked() {
233 if (free_sample_list_ != NULL) { 216 if (free_sample_list_ != NULL) {
234 Sample* free_sample = free_sample_list_; 217 Sample* free_sample = free_sample_list_;
235 free_sample_list_ = free_sample->next_free(); 218 free_sample_list_ = free_sample->next_free();
236 free_sample->set_next_free(NULL); 219 free_sample->set_next_free(NULL);
237 uint8_t* samples_array_ptr = reinterpret_cast<uint8_t*>(samples_); 220 uint8_t* samples_array_ptr = reinterpret_cast<uint8_t*>(samples_);
238 uint8_t* free_sample_ptr = reinterpret_cast<uint8_t*>(free_sample); 221 uint8_t* free_sample_ptr = reinterpret_cast<uint8_t*>(free_sample);
239 return static_cast<intptr_t>((free_sample_ptr - samples_array_ptr) / 222 return static_cast<intptr_t>((free_sample_ptr - samples_array_ptr) /
240 Sample::instance_size()); 223 Sample::instance_size());
241 } else if (cursor_ < static_cast<uintptr_t>(capacity_ - 1)) { 224 } else if (cursor_ < static_cast<uintptr_t>(capacity_ - 1)) {
242 return cursor_++; 225 return cursor_++;
243 } else { 226 } else {
244 return -1; 227 return -1;
245 } 228 }
246 } 229 }
247 230
248
249 Sample* AllocationSampleBuffer::ReserveSampleAndLink(Sample* previous) { 231 Sample* AllocationSampleBuffer::ReserveSampleAndLink(Sample* previous) {
250 MutexLocker ml(mutex_); 232 MutexLocker ml(mutex_);
251 ASSERT(previous != NULL); 233 ASSERT(previous != NULL);
252 intptr_t next_index = ReserveSampleSlotLocked(); 234 intptr_t next_index = ReserveSampleSlotLocked();
253 if (next_index < 0) { 235 if (next_index < 0) {
254 // Could not find a free sample. 236 // Could not find a free sample.
255 return NULL; 237 return NULL;
256 } 238 }
257 Sample* next = At(next_index); 239 Sample* next = At(next_index);
258 next->Init(previous->port(), previous->timestamp(), previous->tid()); 240 next->Init(previous->port(), previous->timestamp(), previous->tid());
259 next->set_native_allocation_address(previous->native_allocation_address()); 241 next->set_native_allocation_address(previous->native_allocation_address());
260 next->set_native_allocation_size_bytes( 242 next->set_native_allocation_size_bytes(
261 previous->native_allocation_size_bytes()); 243 previous->native_allocation_size_bytes());
262 next->set_head_sample(false); 244 next->set_head_sample(false);
263 // Mark that previous continues at next. 245 // Mark that previous continues at next.
264 previous->SetContinuationIndex(next_index); 246 previous->SetContinuationIndex(next_index);
265 return next; 247 return next;
266 } 248 }
267 249
268
269 Sample* AllocationSampleBuffer::ReserveSample() { 250 Sample* AllocationSampleBuffer::ReserveSample() {
270 MutexLocker ml(mutex_); 251 MutexLocker ml(mutex_);
271 intptr_t index = ReserveSampleSlotLocked(); 252 intptr_t index = ReserveSampleSlotLocked();
272 if (index < 0) { 253 if (index < 0) {
273 return NULL; 254 return NULL;
274 } 255 }
275 return At(index); 256 return At(index);
276 } 257 }
277 258
278
279 // Attempts to find the true return address when a Dart frame is being setup 259 // Attempts to find the true return address when a Dart frame is being setup
280 // or torn down. 260 // or torn down.
281 // NOTE: Architecture specific implementations below. 261 // NOTE: Architecture specific implementations below.
282 class ReturnAddressLocator : public ValueObject { 262 class ReturnAddressLocator : public ValueObject {
283 public: 263 public:
284 ReturnAddressLocator(Sample* sample, const Code& code) 264 ReturnAddressLocator(Sample* sample, const Code& code)
285 : stack_buffer_(sample->GetStackBuffer()), 265 : stack_buffer_(sample->GetStackBuffer()),
286 pc_(sample->pc()), 266 pc_(sample->pc()),
287 code_(Code::ZoneHandle(code.raw())) { 267 code_(Code::ZoneHandle(code.raw())) {
288 ASSERT(!code_.IsNull()); 268 ASSERT(!code_.IsNull());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 ASSERT(i < Sample::kStackBufferSizeInWords); 301 ASSERT(i < Sample::kStackBufferSizeInWords);
322 return stack_buffer_[i]; 302 return stack_buffer_[i];
323 } 303 }
324 304
325 private: 305 private:
326 uword* stack_buffer_; 306 uword* stack_buffer_;
327 uword pc_; 307 uword pc_;
328 const Code& code_; 308 const Code& code_;
329 }; 309 };
330 310
331
332 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) 311 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
333 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) { 312 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
334 ASSERT(return_address != NULL); 313 ASSERT(return_address != NULL);
335 const intptr_t offset = RelativePC(); 314 const intptr_t offset = RelativePC();
336 ASSERT(offset >= 0); 315 ASSERT(offset >= 0);
337 const intptr_t size = code_.Size(); 316 const intptr_t size = code_.Size();
338 ASSERT(offset < size); 317 ASSERT(offset < size);
339 const intptr_t prologue_offset = code_.GetPrologueOffset(); 318 const intptr_t prologue_offset = code_.GetPrologueOffset();
340 if (offset < prologue_offset) { 319 if (offset < prologue_offset) {
341 // Before the prologue, return address is at the top of the stack. 320 // Before the prologue, return address is at the top of the stack.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 } 369 }
391 #elif defined(TARGET_ARCH_DBC) 370 #elif defined(TARGET_ARCH_DBC)
392 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) { 371 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
393 ASSERT(return_address != NULL); 372 ASSERT(return_address != NULL);
394 return false; 373 return false;
395 } 374 }
396 #else 375 #else
397 #error ReturnAddressLocator implementation missing for this architecture. 376 #error ReturnAddressLocator implementation missing for this architecture.
398 #endif 377 #endif
399 378
400
401 bool SampleFilter::TimeFilterSample(Sample* sample) { 379 bool SampleFilter::TimeFilterSample(Sample* sample) {
402 if ((time_origin_micros_ == -1) || (time_extent_micros_ == -1)) { 380 if ((time_origin_micros_ == -1) || (time_extent_micros_ == -1)) {
403 // No time filter passed in, always pass. 381 // No time filter passed in, always pass.
404 return true; 382 return true;
405 } 383 }
406 const int64_t timestamp = sample->timestamp(); 384 const int64_t timestamp = sample->timestamp();
407 int64_t delta = timestamp - time_origin_micros_; 385 int64_t delta = timestamp - time_origin_micros_;
408 return (delta >= 0) && (delta <= time_extent_micros_); 386 return (delta >= 0) && (delta <= time_extent_micros_);
409 } 387 }
410 388
411
412 bool SampleFilter::TaskFilterSample(Sample* sample) { 389 bool SampleFilter::TaskFilterSample(Sample* sample) {
413 const intptr_t task = static_cast<intptr_t>(sample->thread_task()); 390 const intptr_t task = static_cast<intptr_t>(sample->thread_task());
414 if (thread_task_mask_ == kNoTaskFilter) { 391 if (thread_task_mask_ == kNoTaskFilter) {
415 return true; 392 return true;
416 } 393 }
417 return (task & thread_task_mask_) != 0; 394 return (task & thread_task_mask_) != 0;
418 } 395 }
419 396
420
421 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) 397 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate)
422 : SampleVisitor(isolate->main_port()) {} 398 : SampleVisitor(isolate->main_port()) {}
423 399
424
425 void ClearProfileVisitor::VisitSample(Sample* sample) { 400 void ClearProfileVisitor::VisitSample(Sample* sample) {
426 sample->Clear(); 401 sample->Clear();
427 } 402 }
428 403
429
430 static void DumpStackFrame(intptr_t frame_index, uword pc) { 404 static void DumpStackFrame(intptr_t frame_index, uword pc) {
431 Isolate* isolate = Isolate::Current(); 405 Isolate* isolate = Isolate::Current();
432 if ((isolate != NULL) && isolate->is_runnable()) { 406 if ((isolate != NULL) && isolate->is_runnable()) {
433 Code& code = Code::Handle(Code::LookupCodeInVmIsolate(pc)); 407 Code& code = Code::Handle(Code::LookupCodeInVmIsolate(pc));
434 if (!code.IsNull()) { 408 if (!code.IsNull()) {
435 OS::PrintErr(" [0x%" Pp "] %s\n", pc, code.QualifiedName()); 409 OS::PrintErr(" [0x%" Pp "] %s\n", pc, code.QualifiedName());
436 return; 410 return;
437 } 411 }
438 code = Code::LookupCode(pc); 412 code = Code::LookupCode(pc);
439 if (!code.IsNull()) { 413 if (!code.IsNull()) {
440 OS::PrintErr(" [0x%" Pp "] %s\n", pc, code.QualifiedName()); 414 OS::PrintErr(" [0x%" Pp "] %s\n", pc, code.QualifiedName());
441 return; 415 return;
442 } 416 }
443 } 417 }
444 418
445 uintptr_t start = 0; 419 uintptr_t start = 0;
446 char* native_symbol_name = NativeSymbolResolver::LookupSymbolName(pc, &start); 420 char* native_symbol_name = NativeSymbolResolver::LookupSymbolName(pc, &start);
447 if (native_symbol_name == NULL) { 421 if (native_symbol_name == NULL) {
448 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc); 422 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc);
449 } else { 423 } else {
450 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name); 424 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name);
451 NativeSymbolResolver::FreeSymbolName(native_symbol_name); 425 NativeSymbolResolver::FreeSymbolName(native_symbol_name);
452 } 426 }
453 } 427 }
454 428
455
456 class ProfilerStackWalker : public ValueObject { 429 class ProfilerStackWalker : public ValueObject {
457 public: 430 public:
458 ProfilerStackWalker(Dart_Port port_id, 431 ProfilerStackWalker(Dart_Port port_id,
459 Sample* head_sample, 432 Sample* head_sample,
460 SampleBuffer* sample_buffer, 433 SampleBuffer* sample_buffer,
461 intptr_t skip_count = 0) 434 intptr_t skip_count = 0)
462 : port_id_(port_id), 435 : port_id_(port_id),
463 sample_(head_sample), 436 sample_(head_sample),
464 sample_buffer_(sample_buffer), 437 sample_buffer_(sample_buffer),
465 skip_count_(skip_count), 438 skip_count_(skip_count),
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 protected: 484 protected:
512 Dart_Port port_id_; 485 Dart_Port port_id_;
513 Sample* sample_; 486 Sample* sample_;
514 SampleBuffer* sample_buffer_; 487 SampleBuffer* sample_buffer_;
515 intptr_t skip_count_; 488 intptr_t skip_count_;
516 intptr_t frames_skipped_; 489 intptr_t frames_skipped_;
517 intptr_t frame_index_; 490 intptr_t frame_index_;
518 intptr_t total_frames_; 491 intptr_t total_frames_;
519 }; 492 };
520 493
521
522 // Executing Dart code, walk the stack. 494 // Executing Dart code, walk the stack.
523 class ProfilerDartStackWalker : public ProfilerStackWalker { 495 class ProfilerDartStackWalker : public ProfilerStackWalker {
524 public: 496 public:
525 ProfilerDartStackWalker(Thread* thread, 497 ProfilerDartStackWalker(Thread* thread,
526 Sample* sample, 498 Sample* sample,
527 SampleBuffer* sample_buffer, 499 SampleBuffer* sample_buffer,
528 uword stack_lower, 500 uword stack_lower,
529 uword stack_upper, 501 uword stack_upper,
530 uword pc, 502 uword pc,
531 uword fp, 503 uword fp,
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 } 677 }
706 678
707 uword* pc_; 679 uword* pc_;
708 uword* fp_; 680 uword* fp_;
709 uword* sp_; 681 uword* sp_;
710 const uword stack_upper_; 682 const uword stack_upper_;
711 const uword stack_lower_; 683 const uword stack_lower_;
712 bool has_exit_frame_; 684 bool has_exit_frame_;
713 }; 685 };
714 686
715
716 // If the VM is compiled without frame pointers (which is the default on 687 // If the VM is compiled without frame pointers (which is the default on
717 // recent GCC versions with optimizing enabled) the stack walking code may 688 // recent GCC versions with optimizing enabled) the stack walking code may
718 // fail. 689 // fail.
719 // 690 //
720 class ProfilerNativeStackWalker : public ProfilerStackWalker { 691 class ProfilerNativeStackWalker : public ProfilerStackWalker {
721 public: 692 public:
722 ProfilerNativeStackWalker(Dart_Port port_id, 693 ProfilerNativeStackWalker(Dart_Port port_id,
723 Sample* sample, 694 Sample* sample,
724 SampleBuffer* sample_buffer, 695 SampleBuffer* sample_buffer,
725 uword stack_lower, 696 uword stack_lower,
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 return r; 789 return r;
819 } 790 }
820 791
821 const uword stack_upper_; 792 const uword stack_upper_;
822 const uword original_pc_; 793 const uword original_pc_;
823 const uword original_fp_; 794 const uword original_fp_;
824 const uword original_sp_; 795 const uword original_sp_;
825 uword lower_bound_; 796 uword lower_bound_;
826 }; 797 };
827 798
828
829 static void CopyStackBuffer(Sample* sample, uword sp_addr) { 799 static void CopyStackBuffer(Sample* sample, uword sp_addr) {
830 ASSERT(sample != NULL); 800 ASSERT(sample != NULL);
831 uword* sp = reinterpret_cast<uword*>(sp_addr); 801 uword* sp = reinterpret_cast<uword*>(sp_addr);
832 uword* buffer = sample->GetStackBuffer(); 802 uword* buffer = sample->GetStackBuffer();
833 if (sp != NULL) { 803 if (sp != NULL) {
834 for (intptr_t i = 0; i < Sample::kStackBufferSizeInWords; i++) { 804 for (intptr_t i = 0; i < Sample::kStackBufferSizeInWords; i++) {
835 MSAN_UNPOISON(sp, kWordSize); 805 MSAN_UNPOISON(sp, kWordSize);
836 ASAN_UNPOISON(sp, kWordSize); 806 ASAN_UNPOISON(sp, kWordSize);
837 buffer[i] = *sp; 807 buffer[i] = *sp;
838 sp++; 808 sp++;
839 } 809 }
840 } 810 }
841 } 811 }
842 812
843
844 #if defined(HOST_OS_WINDOWS) 813 #if defined(HOST_OS_WINDOWS)
845 // On Windows this code is synchronously executed from the thread interrupter 814 // On Windows this code is synchronously executed from the thread interrupter
846 // thread. This means we can safely have a static fault_address. 815 // thread. This means we can safely have a static fault_address.
847 static uword fault_address = 0; 816 static uword fault_address = 0;
848 static LONG GuardPageExceptionFilter(EXCEPTION_POINTERS* ep) { 817 static LONG GuardPageExceptionFilter(EXCEPTION_POINTERS* ep) {
849 fault_address = 0; 818 fault_address = 0;
850 if (ep->ExceptionRecord->ExceptionCode != STATUS_GUARD_PAGE_VIOLATION) { 819 if (ep->ExceptionRecord->ExceptionCode != STATUS_GUARD_PAGE_VIOLATION) {
851 return EXCEPTION_CONTINUE_SEARCH; 820 return EXCEPTION_CONTINUE_SEARCH;
852 } 821 }
853 // https://goo.gl/p5Fe10 822 // https://goo.gl/p5Fe10
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 BOOL success = 881 BOOL success =
913 VirtualProtect(reinterpret_cast<void*>(fault_address), 882 VirtualProtect(reinterpret_cast<void*>(fault_address),
914 sizeof(fault_address), new_protect, &old_protect); 883 sizeof(fault_address), new_protect, &old_protect);
915 USE(success); 884 USE(success);
916 ASSERT(success); 885 ASSERT(success);
917 ASSERT(old_protect == PAGE_READWRITE); 886 ASSERT(old_protect == PAGE_READWRITE);
918 } 887 }
919 #endif 888 #endif
920 } 889 }
921 890
922
923 static bool ValidateThreadStackBounds(uintptr_t fp, 891 static bool ValidateThreadStackBounds(uintptr_t fp,
924 uintptr_t sp, 892 uintptr_t sp,
925 uword stack_lower, 893 uword stack_lower,
926 uword stack_upper) { 894 uword stack_upper) {
927 if (stack_lower >= stack_upper) { 895 if (stack_lower >= stack_upper) {
928 // Stack boundary is invalid. 896 // Stack boundary is invalid.
929 return false; 897 return false;
930 } 898 }
931 899
932 if ((sp < stack_lower) || (sp >= stack_upper)) { 900 if ((sp < stack_lower) || (sp >= stack_upper)) {
933 // Stack pointer is outside thread's stack boundary. 901 // Stack pointer is outside thread's stack boundary.
934 return false; 902 return false;
935 } 903 }
936 904
937 if ((fp < stack_lower) || (fp >= stack_upper)) { 905 if ((fp < stack_lower) || (fp >= stack_upper)) {
938 // Frame pointer is outside threads's stack boundary. 906 // Frame pointer is outside threads's stack boundary.
939 return false; 907 return false;
940 } 908 }
941 909
942 return true; 910 return true;
943 } 911 }
944 912
945
946 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within 913 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within
947 // it. If |get_os_thread_bounds| is true then if |isolate| stackbounds are 914 // it. If |get_os_thread_bounds| is true then if |isolate| stackbounds are
948 // not available we fallback to using underlying OS thread bounds. This only 915 // not available we fallback to using underlying OS thread bounds. This only
949 // works for the current thread. 916 // works for the current thread.
950 // Return |false| if anything looks suspicious. 917 // Return |false| if anything looks suspicious.
951 static bool GetAndValidateThreadStackBounds(Thread* thread, 918 static bool GetAndValidateThreadStackBounds(Thread* thread,
952 uintptr_t fp, 919 uintptr_t fp,
953 uintptr_t sp, 920 uintptr_t sp,
954 uword* stack_lower, 921 uword* stack_lower,
955 uword* stack_upper, 922 uword* stack_upper,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 } 958 }
992 959
993 if (!use_simulator_stack_bounds && (sp > *stack_lower)) { 960 if (!use_simulator_stack_bounds && (sp > *stack_lower)) {
994 // The stack pointer gives us a tighter lower bound. 961 // The stack pointer gives us a tighter lower bound.
995 *stack_lower = sp; 962 *stack_lower = sp;
996 } 963 }
997 964
998 return ValidateThreadStackBounds(fp, sp, *stack_lower, *stack_upper); 965 return ValidateThreadStackBounds(fp, sp, *stack_lower, *stack_upper);
999 } 966 }
1000 967
1001
1002 // Some simple sanity checking of |pc|, |fp|, and |sp|. 968 // Some simple sanity checking of |pc|, |fp|, and |sp|.
1003 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { 969 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) {
1004 if ((sp == 0) || (fp == 0) || (pc == 0)) { 970 if ((sp == 0) || (fp == 0) || (pc == 0)) {
1005 // None of these registers should be zero. 971 // None of these registers should be zero.
1006 return false; 972 return false;
1007 } 973 }
1008 974
1009 if (sp > fp) { 975 if (sp > fp) {
1010 // Assuming the stack grows down, we should never have a stack pointer above 976 // Assuming the stack grows down, we should never have a stack pointer above
1011 // the frame pointer. 977 // the frame pointer.
1012 return false; 978 return false;
1013 } 979 }
1014 980
1015 return true; 981 return true;
1016 } 982 }
1017 983
1018
1019 static Sample* SetupSample(Thread* thread, 984 static Sample* SetupSample(Thread* thread,
1020 SampleBuffer* sample_buffer, 985 SampleBuffer* sample_buffer,
1021 ThreadId tid) { 986 ThreadId tid) {
1022 ASSERT(thread != NULL); 987 ASSERT(thread != NULL);
1023 Isolate* isolate = thread->isolate(); 988 Isolate* isolate = thread->isolate();
1024 ASSERT(sample_buffer != NULL); 989 ASSERT(sample_buffer != NULL);
1025 Sample* sample = sample_buffer->ReserveSample(); 990 Sample* sample = sample_buffer->ReserveSample();
1026 sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid); 991 sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid);
1027 uword vm_tag = thread->vm_tag(); 992 uword vm_tag = thread->vm_tag();
1028 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) 993 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
1029 // When running in the simulator, the runtime entry function address 994 // When running in the simulator, the runtime entry function address
1030 // (stored as the vm tag) is the address of a redirect function. 995 // (stored as the vm tag) is the address of a redirect function.
1031 // Attempt to find the real runtime entry function address and use that. 996 // Attempt to find the real runtime entry function address and use that.
1032 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); 997 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag);
1033 if (redirect_vm_tag != 0) { 998 if (redirect_vm_tag != 0) {
1034 vm_tag = redirect_vm_tag; 999 vm_tag = redirect_vm_tag;
1035 } 1000 }
1036 #endif 1001 #endif
1037 sample->set_vm_tag(vm_tag); 1002 sample->set_vm_tag(vm_tag);
1038 sample->set_user_tag(isolate->user_tag()); 1003 sample->set_user_tag(isolate->user_tag());
1039 sample->set_thread_task(thread->task_kind()); 1004 sample->set_thread_task(thread->task_kind());
1040 return sample; 1005 return sample;
1041 } 1006 }
1042 1007
1043
1044 static Sample* SetupSampleNative(SampleBuffer* sample_buffer, ThreadId tid) { 1008 static Sample* SetupSampleNative(SampleBuffer* sample_buffer, ThreadId tid) {
1045 Sample* sample = sample_buffer->ReserveSample(); 1009 Sample* sample = sample_buffer->ReserveSample();
1046 if (sample == NULL) { 1010 if (sample == NULL) {
1047 return NULL; 1011 return NULL;
1048 } 1012 }
1049 sample->Init(ILLEGAL_PORT, OS::GetCurrentMonotonicMicros(), tid); 1013 sample->Init(ILLEGAL_PORT, OS::GetCurrentMonotonicMicros(), tid);
1050 Thread* thread = Thread::Current(); 1014 Thread* thread = Thread::Current();
1051 1015
1052 // Note: setting thread task in order to be consistent with other samples. The 1016 // Note: setting thread task in order to be consistent with other samples. The
1053 // task kind is not used by NativeAllocationSampleFilter for filtering 1017 // task kind is not used by NativeAllocationSampleFilter for filtering
1054 // purposes as some samples may be collected when no thread exists. 1018 // purposes as some samples may be collected when no thread exists.
1055 if (thread != NULL) { 1019 if (thread != NULL) {
1056 sample->set_thread_task(thread->task_kind()); 1020 sample->set_thread_task(thread->task_kind());
1057 } 1021 }
1058 return sample; 1022 return sample;
1059 } 1023 }
1060 1024
1061
1062 static bool CheckIsolate(Isolate* isolate) { 1025 static bool CheckIsolate(Isolate* isolate) {
1063 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { 1026 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
1064 // No isolate. 1027 // No isolate.
1065 return false; 1028 return false;
1066 } 1029 }
1067 return isolate != Dart::vm_isolate(); 1030 return isolate != Dart::vm_isolate();
1068 } 1031 }
1069 1032
1070
1071 void Profiler::DumpStackTrace(void* context) { 1033 void Profiler::DumpStackTrace(void* context) {
1072 #if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) 1034 #if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS)
1073 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 1035 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
1074 mcontext_t mcontext = ucontext->uc_mcontext; 1036 mcontext_t mcontext = ucontext->uc_mcontext;
1075 uword pc = SignalHandler::GetProgramCounter(mcontext); 1037 uword pc = SignalHandler::GetProgramCounter(mcontext);
1076 uword fp = SignalHandler::GetFramePointer(mcontext); 1038 uword fp = SignalHandler::GetFramePointer(mcontext);
1077 uword sp = SignalHandler::GetCStackPointer(mcontext); 1039 uword sp = SignalHandler::GetCStackPointer(mcontext);
1078 DumpStackTrace(sp, fp, pc, true /* for_crash */); 1040 DumpStackTrace(sp, fp, pc, true /* for_crash */);
1079 #else 1041 #else
1080 // TODO(fschneider): Add support for more platforms. 1042 // TODO(fschneider): Add support for more platforms.
1081 // Do nothing on unsupported platforms. 1043 // Do nothing on unsupported platforms.
1082 #endif 1044 #endif
1083 } 1045 }
1084 1046
1085
1086 void Profiler::DumpStackTrace(bool for_crash) { 1047 void Profiler::DumpStackTrace(bool for_crash) {
1087 uintptr_t sp = Thread::GetCurrentStackPointer(); 1048 uintptr_t sp = Thread::GetCurrentStackPointer();
1088 uintptr_t fp = 0; 1049 uintptr_t fp = 0;
1089 uintptr_t pc = OS::GetProgramCounter(); 1050 uintptr_t pc = OS::GetProgramCounter();
1090 1051
1091 COPY_FP_REGISTER(fp); 1052 COPY_FP_REGISTER(fp);
1092 1053
1093 DumpStackTrace(sp, fp, pc, for_crash); 1054 DumpStackTrace(sp, fp, pc, for_crash);
1094 } 1055 }
1095 1056
1096
1097 void Profiler::DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash) { 1057 void Profiler::DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash) {
1098 if (for_crash) { 1058 if (for_crash) {
1099 // Allow only one stack trace to prevent recursively printing stack traces 1059 // Allow only one stack trace to prevent recursively printing stack traces
1100 // if we hit an assert while printing the stack. 1060 // if we hit an assert while printing the stack.
1101 static uintptr_t started_dump = 0; 1061 static uintptr_t started_dump = 0;
1102 if (AtomicOperations::FetchAndIncrement(&started_dump) != 0) { 1062 if (AtomicOperations::FetchAndIncrement(&started_dump) != 0) {
1103 OS::PrintErr("Aborting re-entrant request for stack trace.\n"); 1063 OS::PrintErr("Aborting re-entrant request for stack trace.\n");
1104 return; 1064 return;
1105 } 1065 }
1106 } 1066 }
(...skipping 28 matching lines...) Expand all
1135 return; 1095 return;
1136 } 1096 }
1137 1097
1138 ProfilerNativeStackWalker native_stack_walker( 1098 ProfilerNativeStackWalker native_stack_walker(
1139 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, NULL, NULL, 1099 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, NULL, NULL,
1140 stack_lower, stack_upper, pc, fp, sp); 1100 stack_lower, stack_upper, pc, fp, sp);
1141 native_stack_walker.walk(); 1101 native_stack_walker.walk();
1142 OS::PrintErr("-- End of DumpStackTrace\n"); 1102 OS::PrintErr("-- End of DumpStackTrace\n");
1143 } 1103 }
1144 1104
1145
1146 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { 1105 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
1147 ASSERT(thread != NULL); 1106 ASSERT(thread != NULL);
1148 OSThread* os_thread = thread->os_thread(); 1107 OSThread* os_thread = thread->os_thread();
1149 ASSERT(os_thread != NULL); 1108 ASSERT(os_thread != NULL);
1150 Isolate* isolate = thread->isolate(); 1109 Isolate* isolate = thread->isolate();
1151 if (!CheckIsolate(isolate)) { 1110 if (!CheckIsolate(isolate)) {
1152 return; 1111 return;
1153 } 1112 }
1154 1113
1155 const bool exited_dart_code = thread->HasExitedDartCode(); 1114 const bool exited_dart_code = thread->HasExitedDartCode();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 dart_exit_stack_walker.walk(); 1153 dart_exit_stack_walker.walk();
1195 } else { 1154 } else {
1196 // Fall back. 1155 // Fall back.
1197 uintptr_t pc = OS::GetProgramCounter(); 1156 uintptr_t pc = OS::GetProgramCounter();
1198 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1157 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1199 sample->SetAllocationCid(cid); 1158 sample->SetAllocationCid(cid);
1200 sample->SetAt(0, pc); 1159 sample->SetAt(0, pc);
1201 } 1160 }
1202 } 1161 }
1203 1162
1204
1205 Sample* Profiler::SampleNativeAllocation(intptr_t skip_count, 1163 Sample* Profiler::SampleNativeAllocation(intptr_t skip_count,
1206 uword address, 1164 uword address,
1207 uintptr_t allocation_size) { 1165 uintptr_t allocation_size) {
1208 AllocationSampleBuffer* sample_buffer = Profiler::allocation_sample_buffer(); 1166 AllocationSampleBuffer* sample_buffer = Profiler::allocation_sample_buffer();
1209 if (sample_buffer == NULL) { 1167 if (sample_buffer == NULL) {
1210 return NULL; 1168 return NULL;
1211 } 1169 }
1212 1170
1213 uintptr_t sp = Thread::GetCurrentStackPointer(); 1171 uintptr_t sp = Thread::GetCurrentStackPointer();
1214 uintptr_t fp = 0; 1172 uintptr_t fp = 0;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1249 1207
1250 ProfilerNativeStackWalker native_stack_walker( 1208 ProfilerNativeStackWalker native_stack_walker(
1251 ILLEGAL_PORT, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, 1209 ILLEGAL_PORT, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp,
1252 skip_count); 1210 skip_count);
1253 1211
1254 native_stack_walker.walk(); 1212 native_stack_walker.walk();
1255 1213
1256 return sample; 1214 return sample;
1257 } 1215 }
1258 1216
1259
1260 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) { 1217 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) {
1261 ASSERT(thread != NULL); 1218 ASSERT(thread != NULL);
1262 OSThread* os_thread = thread->os_thread(); 1219 OSThread* os_thread = thread->os_thread();
1263 ASSERT(os_thread != NULL); 1220 ASSERT(os_thread != NULL);
1264 Isolate* isolate = thread->isolate(); 1221 Isolate* isolate = thread->isolate();
1265 1222
1266 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 1223 SampleBuffer* sample_buffer = Profiler::sample_buffer();
1267 if (sample_buffer == NULL) { 1224 if (sample_buffer == NULL) {
1268 // Profiler not initialized. 1225 // Profiler not initialized.
1269 return; 1226 return;
1270 } 1227 }
1271 1228
1272 // Setup sample. 1229 // Setup sample.
1273 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1230 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1274 // Increment counter for vm tag. 1231 // Increment counter for vm tag.
1275 VMTagCounters* counters = isolate->vm_tag_counters(); 1232 VMTagCounters* counters = isolate->vm_tag_counters();
1276 ASSERT(counters != NULL); 1233 ASSERT(counters != NULL);
1277 if (thread->IsMutatorThread()) { 1234 if (thread->IsMutatorThread()) {
1278 counters->Increment(sample->vm_tag()); 1235 counters->Increment(sample->vm_tag());
1279 } 1236 }
1280 1237
1281 // Write the single pc value. 1238 // Write the single pc value.
1282 sample->SetAt(0, pc); 1239 sample->SetAt(0, pc);
1283 } 1240 }
1284 1241
1285
1286 void Profiler::SampleThread(Thread* thread, 1242 void Profiler::SampleThread(Thread* thread,
1287 const InterruptedThreadState& state) { 1243 const InterruptedThreadState& state) {
1288 ASSERT(thread != NULL); 1244 ASSERT(thread != NULL);
1289 OSThread* os_thread = thread->os_thread(); 1245 OSThread* os_thread = thread->os_thread();
1290 ASSERT(os_thread != NULL); 1246 ASSERT(os_thread != NULL);
1291 Isolate* isolate = thread->isolate(); 1247 Isolate* isolate = thread->isolate();
1292 1248
1293 // Thread is not doing VM work. 1249 // Thread is not doing VM work.
1294 if (thread->task_kind() == Thread::kUnknownTask) { 1250 if (thread->task_kind() == Thread::kUnknownTask) {
1295 AtomicOperations::IncrementInt64By(&counters_.bail_out_unknown_task, 1); 1251 AtomicOperations::IncrementInt64By(&counters_.bail_out_unknown_task, 1);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1388 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, 1344 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer,
1389 stack_lower, stack_upper, pc, fp, 1345 stack_lower, stack_upper, pc, fp,
1390 sp, exited_dart_code, false); 1346 sp, exited_dart_code, false);
1391 1347
1392 // All memory access is done inside CollectSample. 1348 // All memory access is done inside CollectSample.
1393 CollectSample(isolate, exited_dart_code, in_dart_code, sample, 1349 CollectSample(isolate, exited_dart_code, in_dart_code, sample,
1394 &native_stack_walker, &dart_stack_walker, pc, fp, sp, 1350 &native_stack_walker, &dart_stack_walker, pc, fp, sp,
1395 &counters_); 1351 &counters_);
1396 } 1352 }
1397 1353
1398
1399 CodeDescriptor::CodeDescriptor(const Code& code) : code_(code) { 1354 CodeDescriptor::CodeDescriptor(const Code& code) : code_(code) {
1400 ASSERT(!code_.IsNull()); 1355 ASSERT(!code_.IsNull());
1401 } 1356 }
1402 1357
1403
1404 uword CodeDescriptor::Start() const { 1358 uword CodeDescriptor::Start() const {
1405 return code_.PayloadStart(); 1359 return code_.PayloadStart();
1406 } 1360 }
1407 1361
1408
1409 uword CodeDescriptor::Size() const { 1362 uword CodeDescriptor::Size() const {
1410 return code_.Size(); 1363 return code_.Size();
1411 } 1364 }
1412 1365
1413
1414 int64_t CodeDescriptor::CompileTimestamp() const { 1366 int64_t CodeDescriptor::CompileTimestamp() const {
1415 return code_.compile_timestamp(); 1367 return code_.compile_timestamp();
1416 } 1368 }
1417 1369
1418
1419 CodeLookupTable::CodeLookupTable(Thread* thread) { 1370 CodeLookupTable::CodeLookupTable(Thread* thread) {
1420 Build(thread); 1371 Build(thread);
1421 } 1372 }
1422 1373
1423
1424 class CodeLookupTableBuilder : public ObjectVisitor { 1374 class CodeLookupTableBuilder : public ObjectVisitor {
1425 public: 1375 public:
1426 explicit CodeLookupTableBuilder(CodeLookupTable* table) : table_(table) { 1376 explicit CodeLookupTableBuilder(CodeLookupTable* table) : table_(table) {
1427 ASSERT(table_ != NULL); 1377 ASSERT(table_ != NULL);
1428 } 1378 }
1429 1379
1430 ~CodeLookupTableBuilder() {} 1380 ~CodeLookupTableBuilder() {}
1431 1381
1432 void VisitObject(RawObject* raw_obj) { 1382 void VisitObject(RawObject* raw_obj) {
1433 uint32_t tags = raw_obj->ptr()->tags_; 1383 uint32_t tags = raw_obj->ptr()->tags_;
1434 if (RawObject::ClassIdTag::decode(tags) == kCodeCid) { 1384 if (RawObject::ClassIdTag::decode(tags) == kCodeCid) {
1435 RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj); 1385 RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj);
1436 const Code& code = Code::Handle(raw_code); 1386 const Code& code = Code::Handle(raw_code);
1437 ASSERT(!code.IsNull()); 1387 ASSERT(!code.IsNull());
1438 const Instructions& instructions = 1388 const Instructions& instructions =
1439 Instructions::Handle(code.instructions()); 1389 Instructions::Handle(code.instructions());
1440 ASSERT(!instructions.IsNull()); 1390 ASSERT(!instructions.IsNull());
1441 table_->Add(code); 1391 table_->Add(code);
1442 } 1392 }
1443 } 1393 }
1444 1394
1445 private: 1395 private:
1446 CodeLookupTable* table_; 1396 CodeLookupTable* table_;
1447 }; 1397 };
1448 1398
1449
1450 void CodeLookupTable::Build(Thread* thread) { 1399 void CodeLookupTable::Build(Thread* thread) {
1451 ASSERT(thread != NULL); 1400 ASSERT(thread != NULL);
1452 Isolate* isolate = thread->isolate(); 1401 Isolate* isolate = thread->isolate();
1453 ASSERT(isolate != NULL); 1402 ASSERT(isolate != NULL);
1454 Isolate* vm_isolate = Dart::vm_isolate(); 1403 Isolate* vm_isolate = Dart::vm_isolate();
1455 ASSERT(vm_isolate != NULL); 1404 ASSERT(vm_isolate != NULL);
1456 1405
1457 // Clear. 1406 // Clear.
1458 code_objects_.Clear(); 1407 code_objects_.Clear();
1459 1408
(...skipping 18 matching lines...) Expand all
1478 const CodeDescriptor* b = At(i + 1); 1427 const CodeDescriptor* b = At(i + 1);
1479 ASSERT(a->Start() < b->Start()); 1428 ASSERT(a->Start() < b->Start());
1480 ASSERT(FindCode(a->Start()) == a); 1429 ASSERT(FindCode(a->Start()) == a);
1481 ASSERT(FindCode(b->Start()) == b); 1430 ASSERT(FindCode(b->Start()) == b);
1482 ASSERT(FindCode(a->Start() + a->Size() - 1) == a); 1431 ASSERT(FindCode(a->Start() + a->Size() - 1) == a);
1483 ASSERT(FindCode(b->Start() + b->Size() - 1) == b); 1432 ASSERT(FindCode(b->Start() + b->Size() - 1) == b);
1484 } 1433 }
1485 #endif 1434 #endif
1486 } 1435 }
1487 1436
1488
1489 void CodeLookupTable::Add(const Code& code) { 1437 void CodeLookupTable::Add(const Code& code) {
1490 ASSERT(!code.IsNull()); 1438 ASSERT(!code.IsNull());
1491 CodeDescriptor* cd = new CodeDescriptor(code); 1439 CodeDescriptor* cd = new CodeDescriptor(code);
1492 code_objects_.Add(cd); 1440 code_objects_.Add(cd);
1493 } 1441 }
1494 1442
1495
1496 const CodeDescriptor* CodeLookupTable::FindCode(uword pc) const { 1443 const CodeDescriptor* CodeLookupTable::FindCode(uword pc) const {
1497 intptr_t first = 0; 1444 intptr_t first = 0;
1498 intptr_t count = length(); 1445 intptr_t count = length();
1499 while (count > 0) { 1446 while (count > 0) {
1500 intptr_t current = first; 1447 intptr_t current = first;
1501 intptr_t step = count / 2; 1448 intptr_t step = count / 2;
1502 current += step; 1449 current += step;
1503 const CodeDescriptor* cd = At(current); 1450 const CodeDescriptor* cd = At(current);
1504 if (pc >= cd->Start()) { 1451 if (pc >= cd->Start()) {
1505 first = ++current; 1452 first = ++current;
(...skipping 10 matching lines...) Expand all
1516 first--; 1463 first--;
1517 ASSERT(first >= 0); 1464 ASSERT(first >= 0);
1518 ASSERT(first < length()); 1465 ASSERT(first < length());
1519 const CodeDescriptor* cd = At(first); 1466 const CodeDescriptor* cd = At(first);
1520 if (cd->Contains(pc)) { 1467 if (cd->Contains(pc)) {
1521 return cd; 1468 return cd;
1522 } 1469 }
1523 return NULL; 1470 return NULL;
1524 } 1471 }
1525 1472
1526
1527 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( 1473 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer(
1528 SampleFilter* filter) { 1474 SampleFilter* filter) {
1529 ASSERT(filter != NULL); 1475 ASSERT(filter != NULL);
1530 Thread* thread = Thread::Current(); 1476 Thread* thread = Thread::Current();
1531 Zone* zone = thread->zone(); 1477 Zone* zone = thread->zone();
1532 1478
1533 ProcessedSampleBuffer* buffer = new (zone) ProcessedSampleBuffer(); 1479 ProcessedSampleBuffer* buffer = new (zone) ProcessedSampleBuffer();
1534 1480
1535 const intptr_t length = capacity(); 1481 const intptr_t length = capacity();
1536 for (intptr_t i = 0; i < length; i++) { 1482 for (intptr_t i = 0; i < length; i++) {
(...skipping 30 matching lines...) Expand all
1567 } 1513 }
1568 if (!filter->FilterSample(sample)) { 1514 if (!filter->FilterSample(sample)) {
1569 // Did not pass filter. 1515 // Did not pass filter.
1570 continue; 1516 continue;
1571 } 1517 }
1572 buffer->Add(BuildProcessedSample(sample, buffer->code_lookup_table())); 1518 buffer->Add(BuildProcessedSample(sample, buffer->code_lookup_table()));
1573 } 1519 }
1574 return buffer; 1520 return buffer;
1575 } 1521 }
1576 1522
1577
1578 ProcessedSample* SampleBuffer::BuildProcessedSample( 1523 ProcessedSample* SampleBuffer::BuildProcessedSample(
1579 Sample* sample, 1524 Sample* sample,
1580 const CodeLookupTable& clt) { 1525 const CodeLookupTable& clt) {
1581 Thread* thread = Thread::Current(); 1526 Thread* thread = Thread::Current();
1582 Zone* zone = thread->zone(); 1527 Zone* zone = thread->zone();
1583 1528
1584 ProcessedSample* processed_sample = new (zone) ProcessedSample(); 1529 ProcessedSample* processed_sample = new (zone) ProcessedSample();
1585 1530
1586 // Copy state bits from sample. 1531 // Copy state bits from sample.
1587 processed_sample->set_native_allocation_size_bytes( 1532 processed_sample->set_native_allocation_size_bytes(
(...skipping 24 matching lines...) Expand all
1612 1557
1613 if (!sample->exit_frame_sample()) { 1558 if (!sample->exit_frame_sample()) {
1614 processed_sample->FixupCaller(clt, sample->pc_marker(), 1559 processed_sample->FixupCaller(clt, sample->pc_marker(),
1615 sample->GetStackBuffer()); 1560 sample->GetStackBuffer());
1616 } 1561 }
1617 1562
1618 processed_sample->set_truncated(truncated); 1563 processed_sample->set_truncated(truncated);
1619 return processed_sample; 1564 return processed_sample;
1620 } 1565 }
1621 1566
1622
1623 Sample* SampleBuffer::Next(Sample* sample) { 1567 Sample* SampleBuffer::Next(Sample* sample) {
1624 if (!sample->is_continuation_sample()) return NULL; 1568 if (!sample->is_continuation_sample()) return NULL;
1625 Sample* next_sample = At(sample->continuation_index()); 1569 Sample* next_sample = At(sample->continuation_index());
1626 // Sanity check. 1570 // Sanity check.
1627 ASSERT(sample != next_sample); 1571 ASSERT(sample != next_sample);
1628 // Detect invalid chaining. 1572 // Detect invalid chaining.
1629 if (sample->port() != next_sample->port()) { 1573 if (sample->port() != next_sample->port()) {
1630 return NULL; 1574 return NULL;
1631 } 1575 }
1632 if (sample->timestamp() != next_sample->timestamp()) { 1576 if (sample->timestamp() != next_sample->timestamp()) {
1633 return NULL; 1577 return NULL;
1634 } 1578 }
1635 if (sample->tid() != next_sample->tid()) { 1579 if (sample->tid() != next_sample->tid()) {
1636 return NULL; 1580 return NULL;
1637 } 1581 }
1638 return next_sample; 1582 return next_sample;
1639 } 1583 }
1640 1584
1641
1642 ProcessedSample::ProcessedSample() 1585 ProcessedSample::ProcessedSample()
1643 : pcs_(kSampleSize), 1586 : pcs_(kSampleSize),
1644 timestamp_(0), 1587 timestamp_(0),
1645 vm_tag_(0), 1588 vm_tag_(0),
1646 user_tag_(0), 1589 user_tag_(0),
1647 allocation_cid_(-1), 1590 allocation_cid_(-1),
1648 truncated_(false), 1591 truncated_(false),
1649 timeline_trie_(NULL) {} 1592 timeline_trie_(NULL) {}
1650 1593
1651
1652 void ProcessedSample::FixupCaller(const CodeLookupTable& clt, 1594 void ProcessedSample::FixupCaller(const CodeLookupTable& clt,
1653 uword pc_marker, 1595 uword pc_marker,
1654 uword* stack_buffer) { 1596 uword* stack_buffer) {
1655 const CodeDescriptor* cd = clt.FindCode(At(0)); 1597 const CodeDescriptor* cd = clt.FindCode(At(0));
1656 if (cd == NULL) { 1598 if (cd == NULL) {
1657 // No Dart code. 1599 // No Dart code.
1658 return; 1600 return;
1659 } 1601 }
1660 if (cd->CompileTimestamp() > timestamp()) { 1602 if (cd->CompileTimestamp() > timestamp()) {
1661 // Code compiled after sample. Ignore. 1603 // Code compiled after sample. Ignore.
1662 return; 1604 return;
1663 } 1605 }
1664 CheckForMissingDartFrame(clt, cd, pc_marker, stack_buffer); 1606 CheckForMissingDartFrame(clt, cd, pc_marker, stack_buffer);
1665 } 1607 }
1666 1608
1667
1668 void ProcessedSample::CheckForMissingDartFrame(const CodeLookupTable& clt, 1609 void ProcessedSample::CheckForMissingDartFrame(const CodeLookupTable& clt,
1669 const CodeDescriptor* cd, 1610 const CodeDescriptor* cd,
1670 uword pc_marker, 1611 uword pc_marker,
1671 uword* stack_buffer) { 1612 uword* stack_buffer) {
1672 ASSERT(cd != NULL); 1613 ASSERT(cd != NULL);
1673 const Code& code = Code::Handle(cd->code()); 1614 const Code& code = Code::Handle(cd->code());
1674 ASSERT(!code.IsNull()); 1615 ASSERT(!code.IsNull());
1675 // Some stubs (and intrinsics) do not push a frame onto the stack leaving 1616 // Some stubs (and intrinsics) do not push a frame onto the stack leaving
1676 // the frame pointer in the caller. 1617 // the frame pointer in the caller.
1677 // 1618 //
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1712 if (clt.FindCode(return_address) == NULL) { 1653 if (clt.FindCode(return_address) == NULL) {
1713 // Return address is not from a Dart code object. Do not insert. 1654 // Return address is not from a Dart code object. Do not insert.
1714 return; 1655 return;
1715 } 1656 }
1716 1657
1717 if (return_address != 0) { 1658 if (return_address != 0) {
1718 InsertAt(1, return_address); 1659 InsertAt(1, return_address);
1719 } 1660 }
1720 } 1661 }
1721 1662
1722
1723 ProcessedSampleBuffer::ProcessedSampleBuffer() 1663 ProcessedSampleBuffer::ProcessedSampleBuffer()
1724 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { 1664 : code_lookup_table_(new CodeLookupTable(Thread::Current())) {
1725 ASSERT(code_lookup_table_ != NULL); 1665 ASSERT(code_lookup_table_ != NULL);
1726 } 1666 }
1727 1667
1728 #endif // !PRODUCT 1668 #endif // !PRODUCT
1729 1669
1730 } // namespace dart 1670 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698