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" |
(...skipping 23 matching lines...) Expand all Loading... |
34 int64_t bail_out_check_isolate; | 34 int64_t bail_out_check_isolate; |
35 // Count of single frame sampling reasons: | 35 // Count of single frame sampling reasons: |
36 int64_t single_frame_sample_deoptimizing; | 36 int64_t single_frame_sample_deoptimizing; |
37 int64_t single_frame_sample_register_check; | 37 int64_t single_frame_sample_register_check; |
38 int64_t single_frame_sample_get_and_validate_stack_bounds; | 38 int64_t single_frame_sample_get_and_validate_stack_bounds; |
39 // Count of stack walkers used: | 39 // Count of stack walkers used: |
40 int64_t stack_walker_native; | 40 int64_t stack_walker_native; |
41 int64_t stack_walker_dart_exit; | 41 int64_t stack_walker_dart_exit; |
42 int64_t stack_walker_dart; | 42 int64_t stack_walker_dart; |
43 int64_t stack_walker_none; | 43 int64_t stack_walker_none; |
44 // Count of failed checks: | |
45 int64_t failure_native_allocation_sample; | |
46 }; | 44 }; |
47 | 45 |
48 | 46 |
49 class Profiler : public AllStatic { | 47 class Profiler : public AllStatic { |
50 public: | 48 public: |
51 static void InitOnce(); | 49 static void InitOnce(); |
52 static void Shutdown(); | 50 static void Shutdown(); |
53 | 51 |
54 static void SetSampleDepth(intptr_t depth); | 52 static void SetSampleDepth(intptr_t depth); |
55 static void SetSamplePeriod(intptr_t period); | 53 static void SetSamplePeriod(intptr_t period); |
56 | 54 |
57 static SampleBuffer* sample_buffer() { return sample_buffer_; } | 55 static SampleBuffer* sample_buffer() { return sample_buffer_; } |
58 | 56 |
59 static void DumpStackTrace(void* context); | 57 static void DumpStackTrace(void* context); |
60 static void DumpStackTrace(); | 58 static void DumpStackTrace(); |
61 | 59 |
62 static void SampleAllocation(Thread* thread, intptr_t cid); | 60 static void SampleAllocation(Thread* thread, intptr_t cid); |
63 static Sample* SampleNativeAllocation(intptr_t skip_count); | |
64 | 61 |
65 // SampleThread is called from inside the signal handler and hence it is very | 62 // SampleThread is called from inside the signal handler and hence it is very |
66 // critical that the implementation of SampleThread does not do any of the | 63 // critical that the implementation of SampleThread does not do any of the |
67 // following: | 64 // following: |
68 // * Accessing TLS -- Because on Windows the callback will be running in a | 65 // * Accessing TLS -- Because on Windows the callback will be running in a |
69 // different thread. | 66 // different thread. |
70 // * Allocating memory -- Because this takes locks which may already be | 67 // * Allocating memory -- Because this takes locks which may already be |
71 // held, resulting in a dead lock. | 68 // held, resulting in a dead lock. |
72 // * Taking a lock -- See above. | 69 // * Taking a lock -- See above. |
73 static void SampleThread(Thread* thread, const InterruptedThreadState& state); | 70 static void SampleThread(Thread* thread, const InterruptedThreadState& state); |
(...skipping 13 matching lines...) Expand all Loading... |
87 static SampleBuffer* sample_buffer_; | 84 static SampleBuffer* sample_buffer_; |
88 | 85 |
89 static ProfilerCounters counters_; | 86 static ProfilerCounters counters_; |
90 | 87 |
91 friend class Thread; | 88 friend class Thread; |
92 }; | 89 }; |
93 | 90 |
94 | 91 |
95 class SampleVisitor : public ValueObject { | 92 class SampleVisitor : public ValueObject { |
96 public: | 93 public: |
97 explicit SampleVisitor(Dart_Port port) : port_(port), visited_(0) {} | 94 explicit SampleVisitor(Isolate* isolate) : isolate_(isolate), visited_(0) {} |
98 virtual ~SampleVisitor() {} | 95 virtual ~SampleVisitor() {} |
99 | 96 |
100 virtual void VisitSample(Sample* sample) = 0; | 97 virtual void VisitSample(Sample* sample) = 0; |
101 | 98 |
102 intptr_t visited() const { return visited_; } | 99 intptr_t visited() const { return visited_; } |
103 | 100 |
104 void IncrementVisited() { visited_++; } | 101 void IncrementVisited() { visited_++; } |
105 | 102 |
106 Dart_Port port() const { return port_; } | 103 Isolate* isolate() const { return isolate_; } |
107 | 104 |
108 private: | 105 private: |
109 Dart_Port port_; | 106 Isolate* isolate_; |
110 intptr_t visited_; | 107 intptr_t visited_; |
111 | 108 |
112 DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor); | 109 DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor); |
113 }; | 110 }; |
114 | 111 |
115 | 112 |
116 class SampleFilter : public ValueObject { | 113 class SampleFilter : public ValueObject { |
117 public: | 114 public: |
118 SampleFilter(Dart_Port port, | 115 SampleFilter(Isolate* isolate, |
119 intptr_t thread_task_mask, | 116 intptr_t thread_task_mask, |
120 int64_t time_origin_micros, | 117 int64_t time_origin_micros, |
121 int64_t time_extent_micros) | 118 int64_t time_extent_micros) |
122 : port_(port), | 119 : isolate_(isolate), |
123 thread_task_mask_(thread_task_mask), | 120 thread_task_mask_(thread_task_mask), |
124 time_origin_micros_(time_origin_micros), | 121 time_origin_micros_(time_origin_micros), |
125 time_extent_micros_(time_extent_micros) { | 122 time_extent_micros_(time_extent_micros) { |
126 ASSERT(thread_task_mask != 0); | 123 ASSERT(thread_task_mask != 0); |
127 ASSERT(time_origin_micros_ >= -1); | 124 ASSERT(time_origin_micros_ >= -1); |
128 ASSERT(time_extent_micros_ >= -1); | 125 ASSERT(time_extent_micros_ >= -1); |
129 } | 126 } |
130 virtual ~SampleFilter() {} | 127 virtual ~SampleFilter() {} |
131 | 128 |
132 // Override this function. | 129 // Override this function. |
133 // Return |true| if |sample| passes the filter. | 130 // Return |true| if |sample| passes the filter. |
134 virtual bool FilterSample(Sample* sample) { return true; } | 131 virtual bool FilterSample(Sample* sample) { return true; } |
135 | 132 |
136 Dart_Port port() const { return port_; } | 133 Isolate* isolate() const { return isolate_; } |
137 | 134 |
138 // Returns |true| if |sample| passes the time filter. | 135 // Returns |true| if |sample| passes the time filter. |
139 bool TimeFilterSample(Sample* sample); | 136 bool TimeFilterSample(Sample* sample); |
140 | 137 |
141 // Returns |true| if |sample| passes the thread task filter. | 138 // Returns |true| if |sample| passes the thread task filter. |
142 bool TaskFilterSample(Sample* sample); | 139 bool TaskFilterSample(Sample* sample); |
143 | 140 |
144 private: | 141 private: |
145 Dart_Port port_; | 142 Isolate* isolate_; |
146 intptr_t thread_task_mask_; | 143 intptr_t thread_task_mask_; |
147 int64_t time_origin_micros_; | 144 int64_t time_origin_micros_; |
148 int64_t time_extent_micros_; | 145 int64_t time_extent_micros_; |
149 }; | 146 }; |
150 | 147 |
151 | 148 |
152 class ClearProfileVisitor : public SampleVisitor { | 149 class ClearProfileVisitor : public SampleVisitor { |
153 public: | 150 public: |
154 explicit ClearProfileVisitor(Isolate* isolate); | 151 explicit ClearProfileVisitor(Isolate* isolate); |
155 | 152 |
156 virtual void VisitSample(Sample* sample); | 153 virtual void VisitSample(Sample* sample); |
157 }; | 154 }; |
158 | 155 |
159 | 156 |
160 // Each Sample holds a stack trace from an isolate. | 157 // Each Sample holds a stack trace from an isolate. |
161 class Sample { | 158 class Sample { |
162 public: | 159 public: |
163 void Init(Dart_Port port, int64_t timestamp, ThreadId tid) { | 160 void Init(Isolate* isolate, int64_t timestamp, ThreadId tid) { |
164 Clear(); | 161 Clear(); |
165 timestamp_ = timestamp; | 162 timestamp_ = timestamp; |
166 tid_ = tid; | 163 tid_ = tid; |
167 port_ = port; | 164 isolate_ = isolate; |
168 } | 165 } |
169 | 166 |
170 Dart_Port port() const { return port_; } | 167 // Isolate sample was taken from. |
| 168 Isolate* isolate() const { return isolate_; } |
171 | 169 |
172 // Thread sample was taken on. | 170 // Thread sample was taken on. |
173 ThreadId tid() const { return tid_; } | 171 ThreadId tid() const { return tid_; } |
174 | 172 |
175 void Clear() { | 173 void Clear() { |
176 port_ = ILLEGAL_PORT; | 174 isolate_ = NULL; |
177 pc_marker_ = 0; | 175 pc_marker_ = 0; |
178 for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) { | 176 for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) { |
179 stack_buffer_[i] = 0; | 177 stack_buffer_[i] = 0; |
180 } | 178 } |
181 vm_tag_ = VMTag::kInvalidTagId; | 179 vm_tag_ = VMTag::kInvalidTagId; |
182 user_tag_ = UserTags::kDefaultUserTag; | 180 user_tag_ = UserTags::kDefaultUserTag; |
183 lr_ = 0; | 181 lr_ = 0; |
184 metadata_ = 0; | 182 metadata_ = 0; |
185 state_ = 0; | 183 state_ = 0; |
186 continuation_index_ = -1; | 184 continuation_index_ = -1; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 } | 261 } |
264 | 262 |
265 bool is_allocation_sample() const { | 263 bool is_allocation_sample() const { |
266 return ClassAllocationSampleBit::decode(state_); | 264 return ClassAllocationSampleBit::decode(state_); |
267 } | 265 } |
268 | 266 |
269 void set_is_allocation_sample(bool allocation_sample) { | 267 void set_is_allocation_sample(bool allocation_sample) { |
270 state_ = ClassAllocationSampleBit::update(allocation_sample, state_); | 268 state_ = ClassAllocationSampleBit::update(allocation_sample, state_); |
271 } | 269 } |
272 | 270 |
273 bool is_native_allocation_sample() const { | |
274 return NativeAllocationSampleBit::decode(state_); | |
275 } | |
276 | |
277 void set_is_native_allocation_sample(bool native_allocation_sample) { | |
278 state_ = | |
279 NativeAllocationSampleBit::update(native_allocation_sample, state_); | |
280 } | |
281 | |
282 Thread::TaskKind thread_task() const { return ThreadTaskBit::decode(state_); } | 271 Thread::TaskKind thread_task() const { return ThreadTaskBit::decode(state_); } |
283 | 272 |
284 void set_thread_task(Thread::TaskKind task) { | 273 void set_thread_task(Thread::TaskKind task) { |
285 state_ = ThreadTaskBit::update(task, state_); | 274 state_ = ThreadTaskBit::update(task, state_); |
286 } | 275 } |
287 | 276 |
288 bool is_continuation_sample() const { | 277 bool is_continuation_sample() const { |
289 return ContinuationSampleBit::decode(state_); | 278 return ContinuationSampleBit::decode(state_); |
290 } | 279 } |
291 | 280 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 enum StateBits { | 324 enum StateBits { |
336 kHeadSampleBit = 0, | 325 kHeadSampleBit = 0, |
337 kLeafFrameIsDartBit = 1, | 326 kLeafFrameIsDartBit = 1, |
338 kIgnoreBit = 2, | 327 kIgnoreBit = 2, |
339 kExitFrameBit = 3, | 328 kExitFrameBit = 3, |
340 kMissingFrameInsertedBit = 4, | 329 kMissingFrameInsertedBit = 4, |
341 kTruncatedTraceBit = 5, | 330 kTruncatedTraceBit = 5, |
342 kClassAllocationSampleBit = 6, | 331 kClassAllocationSampleBit = 6, |
343 kContinuationSampleBit = 7, | 332 kContinuationSampleBit = 7, |
344 kThreadTaskBit = 8, // 5 bits. | 333 kThreadTaskBit = 8, // 5 bits. |
345 kNativeAllocationSampleBit = 13, | 334 kNextFreeBit = 13, |
346 kNextFreeBit = 14, | |
347 }; | 335 }; |
348 class HeadSampleBit : public BitField<uword, bool, kHeadSampleBit, 1> {}; | 336 class HeadSampleBit : public BitField<uword, bool, kHeadSampleBit, 1> {}; |
349 class LeafFrameIsDart : public BitField<uword, bool, kLeafFrameIsDartBit, 1> { | 337 class LeafFrameIsDart : public BitField<uword, bool, kLeafFrameIsDartBit, 1> { |
350 }; | 338 }; |
351 class IgnoreBit : public BitField<uword, bool, kIgnoreBit, 1> {}; | 339 class IgnoreBit : public BitField<uword, bool, kIgnoreBit, 1> {}; |
352 class ExitFrameBit : public BitField<uword, bool, kExitFrameBit, 1> {}; | 340 class ExitFrameBit : public BitField<uword, bool, kExitFrameBit, 1> {}; |
353 class MissingFrameInsertedBit | 341 class MissingFrameInsertedBit |
354 : public BitField<uword, bool, kMissingFrameInsertedBit, 1> {}; | 342 : public BitField<uword, bool, kMissingFrameInsertedBit, 1> {}; |
355 class TruncatedTraceBit | 343 class TruncatedTraceBit |
356 : public BitField<uword, bool, kTruncatedTraceBit, 1> {}; | 344 : public BitField<uword, bool, kTruncatedTraceBit, 1> {}; |
357 class ClassAllocationSampleBit | 345 class ClassAllocationSampleBit |
358 : public BitField<uword, bool, kClassAllocationSampleBit, 1> {}; | 346 : public BitField<uword, bool, kClassAllocationSampleBit, 1> {}; |
359 class ContinuationSampleBit | 347 class ContinuationSampleBit |
360 : public BitField<uword, bool, kContinuationSampleBit, 1> {}; | 348 : public BitField<uword, bool, kContinuationSampleBit, 1> {}; |
361 class ThreadTaskBit | 349 class ThreadTaskBit |
362 : public BitField<uword, Thread::TaskKind, kThreadTaskBit, 5> {}; | 350 : public BitField<uword, Thread::TaskKind, kThreadTaskBit, 5> {}; |
363 class NativeAllocationSampleBit | |
364 : public BitField<uword, bool, kNativeAllocationSampleBit, 1> {}; | |
365 | 351 |
366 int64_t timestamp_; | 352 int64_t timestamp_; |
367 ThreadId tid_; | 353 ThreadId tid_; |
368 Dart_Port port_; | 354 Isolate* isolate_; |
369 uword pc_marker_; | 355 uword pc_marker_; |
370 uword stack_buffer_[kStackBufferSizeInWords]; | 356 uword stack_buffer_[kStackBufferSizeInWords]; |
371 uword vm_tag_; | 357 uword vm_tag_; |
372 uword user_tag_; | 358 uword user_tag_; |
373 uword metadata_; | 359 uword metadata_; |
374 uword lr_; | 360 uword lr_; |
375 uword state_; | 361 uword state_; |
376 intptr_t continuation_index_; | 362 intptr_t continuation_index_; |
377 | 363 |
378 /* There are a variable number of words that follow, the words hold the | 364 /* There are a variable number of words that follow, the words hold the |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 for (intptr_t i = 0; i < length; i++) { | 467 for (intptr_t i = 0; i < length; i++) { |
482 Sample* sample = At(i); | 468 Sample* sample = At(i); |
483 if (!sample->head_sample()) { | 469 if (!sample->head_sample()) { |
484 // An inner sample in a chain of samples. | 470 // An inner sample in a chain of samples. |
485 continue; | 471 continue; |
486 } | 472 } |
487 if (sample->ignore_sample()) { | 473 if (sample->ignore_sample()) { |
488 // Bad sample. | 474 // Bad sample. |
489 continue; | 475 continue; |
490 } | 476 } |
491 if (sample->port() != visitor->port()) { | 477 if (sample->isolate() != visitor->isolate()) { |
492 // Another isolate. | 478 // Another isolate. |
493 continue; | 479 continue; |
494 } | 480 } |
495 if (sample->timestamp() == 0) { | 481 if (sample->timestamp() == 0) { |
496 // Empty. | 482 // Empty. |
497 continue; | 483 continue; |
498 } | 484 } |
499 if (sample->At(0) == 0) { | 485 if (sample->At(0) == 0) { |
500 // No frames. | 486 // No frames. |
501 continue; | 487 continue; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 private: | 609 private: |
624 ZoneGrowableArray<ProcessedSample*> samples_; | 610 ZoneGrowableArray<ProcessedSample*> samples_; |
625 CodeLookupTable* code_lookup_table_; | 611 CodeLookupTable* code_lookup_table_; |
626 | 612 |
627 DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer); | 613 DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer); |
628 }; | 614 }; |
629 | 615 |
630 } // namespace dart | 616 } // namespace dart |
631 | 617 |
632 #endif // RUNTIME_VM_PROFILER_H_ | 618 #endif // RUNTIME_VM_PROFILER_H_ |
OLD | NEW |