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 #ifndef RUNTIME_VM_PROFILER_H_ | 5 #ifndef RUNTIME_VM_PROFILER_H_ |
6 #define RUNTIME_VM_PROFILER_H_ | 6 #define RUNTIME_VM_PROFILER_H_ |
7 | 7 |
8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
9 #include "vm/bitfield.h" | 9 #include "vm/bitfield.h" |
10 #include "vm/code_observers.h" | 10 #include "vm/code_observers.h" |
11 #include "vm/globals.h" | 11 #include "vm/globals.h" |
12 #include "vm/growable_array.h" | 12 #include "vm/growable_array.h" |
13 #include "vm/malloc_hooks.h" | |
14 #include "vm/object.h" | 13 #include "vm/object.h" |
15 #include "vm/tags.h" | 14 #include "vm/tags.h" |
16 #include "vm/thread_interrupter.h" | 15 #include "vm/thread_interrupter.h" |
17 | 16 |
18 // Profiler sampling and stack walking support. | 17 // Profiler sampling and stack walking support. |
19 // NOTE: For service related code, see profile_service.h. | 18 // NOTE: For service related code, see profile_service.h. |
20 | 19 |
21 namespace dart { | 20 namespace dart { |
22 | 21 |
23 // Forward declarations. | 22 // Forward declarations. |
(...skipping 30 matching lines...) Expand all Loading... |
54 | 53 |
55 static void SetSampleDepth(intptr_t depth); | 54 static void SetSampleDepth(intptr_t depth); |
56 static void SetSamplePeriod(intptr_t period); | 55 static void SetSamplePeriod(intptr_t period); |
57 | 56 |
58 static SampleBuffer* sample_buffer() { return sample_buffer_; } | 57 static SampleBuffer* sample_buffer() { return sample_buffer_; } |
59 | 58 |
60 static void DumpStackTrace(void* context); | 59 static void DumpStackTrace(void* context); |
61 static void DumpStackTrace(); | 60 static void DumpStackTrace(); |
62 | 61 |
63 static void SampleAllocation(Thread* thread, intptr_t cid); | 62 static void SampleAllocation(Thread* thread, intptr_t cid); |
64 static Sample* SampleNativeAllocation(intptr_t skip_count, | 63 static Sample* SampleNativeAllocation(intptr_t skip_count); |
65 uword address, | |
66 uintptr_t allocation_size); | |
67 | 64 |
68 // SampleThread is called from inside the signal handler and hence it is very | 65 // SampleThread is called from inside the signal handler and hence it is very |
69 // critical that the implementation of SampleThread does not do any of the | 66 // critical that the implementation of SampleThread does not do any of the |
70 // following: | 67 // following: |
71 // * Accessing TLS -- Because on Windows the callback will be running in a | 68 // * Accessing TLS -- Because on Windows the callback will be running in a |
72 // different thread. | 69 // different thread. |
73 // * Allocating memory -- Because this takes locks which may already be | 70 // * Allocating memory -- Because this takes locks which may already be |
74 // held, resulting in a dead lock. | 71 // held, resulting in a dead lock. |
75 // * Taking a lock -- See above. | 72 // * Taking a lock -- See above. |
76 static void SampleThread(Thread* thread, const InterruptedThreadState& state); | 73 static void SampleThread(Thread* thread, const InterruptedThreadState& state); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 virtual bool FilterSample(Sample* sample) { return true; } | 134 virtual bool FilterSample(Sample* sample) { return true; } |
138 | 135 |
139 Dart_Port port() const { return port_; } | 136 Dart_Port port() const { return port_; } |
140 | 137 |
141 // Returns |true| if |sample| passes the time filter. | 138 // Returns |true| if |sample| passes the time filter. |
142 bool TimeFilterSample(Sample* sample); | 139 bool TimeFilterSample(Sample* sample); |
143 | 140 |
144 // Returns |true| if |sample| passes the thread task filter. | 141 // Returns |true| if |sample| passes the thread task filter. |
145 bool TaskFilterSample(Sample* sample); | 142 bool TaskFilterSample(Sample* sample); |
146 | 143 |
147 static const intptr_t kNoTaskFilter = -1; | |
148 | |
149 private: | 144 private: |
150 Dart_Port port_; | 145 Dart_Port port_; |
151 intptr_t thread_task_mask_; | 146 intptr_t thread_task_mask_; |
152 int64_t time_origin_micros_; | 147 int64_t time_origin_micros_; |
153 int64_t time_extent_micros_; | 148 int64_t time_extent_micros_; |
154 }; | 149 }; |
155 | 150 |
156 | 151 |
157 class ClearProfileVisitor : public SampleVisitor { | 152 class ClearProfileVisitor : public SampleVisitor { |
158 public: | 153 public: |
(...skipping 22 matching lines...) Expand all Loading... |
181 port_ = ILLEGAL_PORT; | 176 port_ = ILLEGAL_PORT; |
182 pc_marker_ = 0; | 177 pc_marker_ = 0; |
183 for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) { | 178 for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) { |
184 stack_buffer_[i] = 0; | 179 stack_buffer_[i] = 0; |
185 } | 180 } |
186 vm_tag_ = VMTag::kInvalidTagId; | 181 vm_tag_ = VMTag::kInvalidTagId; |
187 user_tag_ = UserTags::kDefaultUserTag; | 182 user_tag_ = UserTags::kDefaultUserTag; |
188 lr_ = 0; | 183 lr_ = 0; |
189 metadata_ = 0; | 184 metadata_ = 0; |
190 state_ = 0; | 185 state_ = 0; |
191 native_allocation_address_ = 0; | |
192 native_allocation_size_bytes_ = 0; | |
193 continuation_index_ = -1; | 186 continuation_index_ = -1; |
194 uword* pcs = GetPCArray(); | 187 uword* pcs = GetPCArray(); |
195 for (intptr_t i = 0; i < pcs_length_; i++) { | 188 for (intptr_t i = 0; i < pcs_length_; i++) { |
196 pcs[i] = 0; | 189 pcs[i] = 0; |
197 } | 190 } |
198 set_head_sample(true); | 191 set_head_sample(true); |
199 } | 192 } |
200 | 193 |
201 // Timestamp sample was taken at. | 194 // Timestamp sample was taken at. |
202 int64_t timestamp() const { return timestamp_; } | 195 int64_t timestamp() const { return timestamp_; } |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 | 272 |
280 bool is_native_allocation_sample() const { | 273 bool is_native_allocation_sample() const { |
281 return NativeAllocationSampleBit::decode(state_); | 274 return NativeAllocationSampleBit::decode(state_); |
282 } | 275 } |
283 | 276 |
284 void set_is_native_allocation_sample(bool native_allocation_sample) { | 277 void set_is_native_allocation_sample(bool native_allocation_sample) { |
285 state_ = | 278 state_ = |
286 NativeAllocationSampleBit::update(native_allocation_sample, state_); | 279 NativeAllocationSampleBit::update(native_allocation_sample, state_); |
287 } | 280 } |
288 | 281 |
289 void set_native_allocation_address(uword address) { | |
290 native_allocation_address_ = address; | |
291 } | |
292 | |
293 uword native_allocation_address() const { return native_allocation_address_; } | |
294 | |
295 uintptr_t native_allocation_size_bytes() const { | |
296 return native_allocation_size_bytes_; | |
297 } | |
298 | |
299 void set_native_allocation_size_bytes(uintptr_t size) { | |
300 native_allocation_size_bytes_ = size; | |
301 } | |
302 | |
303 Thread::TaskKind thread_task() const { return ThreadTaskBit::decode(state_); } | 282 Thread::TaskKind thread_task() const { return ThreadTaskBit::decode(state_); } |
304 | 283 |
305 void set_thread_task(Thread::TaskKind task) { | 284 void set_thread_task(Thread::TaskKind task) { |
306 state_ = ThreadTaskBit::update(task, state_); | 285 state_ = ThreadTaskBit::update(task, state_); |
307 } | 286 } |
308 | 287 |
309 bool is_continuation_sample() const { | 288 bool is_continuation_sample() const { |
310 return ContinuationSampleBit::decode(state_); | 289 return ContinuationSampleBit::decode(state_); |
311 } | 290 } |
312 | 291 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 int64_t timestamp_; | 366 int64_t timestamp_; |
388 ThreadId tid_; | 367 ThreadId tid_; |
389 Dart_Port port_; | 368 Dart_Port port_; |
390 uword pc_marker_; | 369 uword pc_marker_; |
391 uword stack_buffer_[kStackBufferSizeInWords]; | 370 uword stack_buffer_[kStackBufferSizeInWords]; |
392 uword vm_tag_; | 371 uword vm_tag_; |
393 uword user_tag_; | 372 uword user_tag_; |
394 uword metadata_; | 373 uword metadata_; |
395 uword lr_; | 374 uword lr_; |
396 uword state_; | 375 uword state_; |
397 uword native_allocation_address_; | |
398 uintptr_t native_allocation_size_bytes_; | |
399 intptr_t continuation_index_; | 376 intptr_t continuation_index_; |
400 | 377 |
401 /* There are a variable number of words that follow, the words hold the | 378 /* There are a variable number of words that follow, the words hold the |
402 * sampled pc values. Access via GetPCArray() */ | 379 * sampled pc values. Access via GetPCArray() */ |
403 | 380 |
404 DISALLOW_COPY_AND_ASSIGN(Sample); | 381 DISALLOW_COPY_AND_ASSIGN(Sample); |
405 }; | 382 }; |
406 | 383 |
407 | 384 |
408 class NativeAllocationSampleFilter : public SampleFilter { | |
409 public: | |
410 NativeAllocationSampleFilter(int64_t time_origin_micros, | |
411 int64_t time_extent_micros) | |
412 : SampleFilter(ILLEGAL_PORT, | |
413 SampleFilter::kNoTaskFilter, | |
414 time_origin_micros, | |
415 time_extent_micros) {} | |
416 | |
417 bool FilterSample(Sample* sample) { | |
418 if (!sample->is_native_allocation_sample()) { | |
419 return false; | |
420 } | |
421 // If the sample is an allocation sample, we need to check that the | |
422 // memory at the address hasn't been freed, and if the address associated | |
423 // with the allocation has been freed and then reissued. | |
424 void* alloc_address = | |
425 reinterpret_cast<void*>(sample->native_allocation_address()); | |
426 Sample* recorded_sample = MallocHooks::GetSample(alloc_address); | |
427 return (sample == recorded_sample); | |
428 } | |
429 }; | |
430 | |
431 | |
432 // A Code object descriptor. | 385 // A Code object descriptor. |
433 class CodeDescriptor : public ZoneAllocated { | 386 class CodeDescriptor : public ZoneAllocated { |
434 public: | 387 public: |
435 explicit CodeDescriptor(const Code& code); | 388 explicit CodeDescriptor(const Code& code); |
436 | 389 |
437 uword Start() const; | 390 uword Start() const; |
438 | 391 |
439 uword Size() const; | 392 uword Size() const; |
440 | 393 |
441 int64_t CompileTimestamp() const; | 394 int64_t CompileTimestamp() const; |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 // The user tag. | 557 // The user tag. |
605 uword user_tag() const { return user_tag_; } | 558 uword user_tag() const { return user_tag_; } |
606 void set_user_tag(uword tag) { user_tag_ = tag; } | 559 void set_user_tag(uword tag) { user_tag_ = tag; } |
607 | 560 |
608 // The class id if this is an allocation profile sample. -1 otherwise. | 561 // The class id if this is an allocation profile sample. -1 otherwise. |
609 intptr_t allocation_cid() const { return allocation_cid_; } | 562 intptr_t allocation_cid() const { return allocation_cid_; } |
610 void set_allocation_cid(intptr_t cid) { allocation_cid_ = cid; } | 563 void set_allocation_cid(intptr_t cid) { allocation_cid_ = cid; } |
611 | 564 |
612 bool IsAllocationSample() const { return allocation_cid_ > 0; } | 565 bool IsAllocationSample() const { return allocation_cid_ > 0; } |
613 | 566 |
614 bool is_native_allocation_sample() const { | |
615 return native_allocation_size_bytes_ != 0; | |
616 } | |
617 | |
618 uintptr_t native_allocation_size_bytes() const { | |
619 return native_allocation_size_bytes_; | |
620 } | |
621 void set_native_allocation_size_bytes(uintptr_t allocation_size) { | |
622 native_allocation_size_bytes_ = allocation_size; | |
623 } | |
624 | |
625 // Was the stack trace truncated? | 567 // Was the stack trace truncated? |
626 bool truncated() const { return truncated_; } | 568 bool truncated() const { return truncated_; } |
627 void set_truncated(bool truncated) { truncated_ = truncated; } | 569 void set_truncated(bool truncated) { truncated_ = truncated; } |
628 | 570 |
629 // Was the first frame in the stack trace executing? | 571 // Was the first frame in the stack trace executing? |
630 bool first_frame_executing() const { return first_frame_executing_; } | 572 bool first_frame_executing() const { return first_frame_executing_; } |
631 void set_first_frame_executing(bool first_frame_executing) { | 573 void set_first_frame_executing(bool first_frame_executing) { |
632 first_frame_executing_ = first_frame_executing; | 574 first_frame_executing_ = first_frame_executing; |
633 } | 575 } |
634 | 576 |
(...skipping 14 matching lines...) Expand all Loading... |
649 uword* stack_buffer); | 591 uword* stack_buffer); |
650 | 592 |
651 ZoneGrowableArray<uword> pcs_; | 593 ZoneGrowableArray<uword> pcs_; |
652 int64_t timestamp_; | 594 int64_t timestamp_; |
653 ThreadId tid_; | 595 ThreadId tid_; |
654 uword vm_tag_; | 596 uword vm_tag_; |
655 uword user_tag_; | 597 uword user_tag_; |
656 intptr_t allocation_cid_; | 598 intptr_t allocation_cid_; |
657 bool truncated_; | 599 bool truncated_; |
658 bool first_frame_executing_; | 600 bool first_frame_executing_; |
659 uword native_allocation_address_; | |
660 uintptr_t native_allocation_size_bytes_; | |
661 ProfileTrieNode* timeline_trie_; | 601 ProfileTrieNode* timeline_trie_; |
662 | 602 |
663 friend class SampleBuffer; | 603 friend class SampleBuffer; |
664 DISALLOW_COPY_AND_ASSIGN(ProcessedSample); | 604 DISALLOW_COPY_AND_ASSIGN(ProcessedSample); |
665 }; | 605 }; |
666 | 606 |
667 | 607 |
668 // A collection of |ProcessedSample|s. | 608 // A collection of |ProcessedSample|s. |
669 class ProcessedSampleBuffer : public ZoneAllocated { | 609 class ProcessedSampleBuffer : public ZoneAllocated { |
670 public: | 610 public: |
(...skipping 12 matching lines...) Expand all Loading... |
683 private: | 623 private: |
684 ZoneGrowableArray<ProcessedSample*> samples_; | 624 ZoneGrowableArray<ProcessedSample*> samples_; |
685 CodeLookupTable* code_lookup_table_; | 625 CodeLookupTable* code_lookup_table_; |
686 | 626 |
687 DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer); | 627 DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer); |
688 }; | 628 }; |
689 | 629 |
690 } // namespace dart | 630 } // namespace dart |
691 | 631 |
692 #endif // RUNTIME_VM_PROFILER_H_ | 632 #endif // RUNTIME_VM_PROFILER_H_ |
OLD | NEW |