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