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