| 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 VM_PROFILER_H_ | 5 #ifndef VM_PROFILER_H_ |
| 6 #define VM_PROFILER_H_ | 6 #define VM_PROFILER_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/code_observers.h" | 9 #include "vm/code_observers.h" |
| 10 #include "vm/globals.h" | 10 #include "vm/globals.h" |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 return isolate_; | 111 return isolate_; |
| 112 } | 112 } |
| 113 | 113 |
| 114 private: | 114 private: |
| 115 Isolate* isolate_; | 115 Isolate* isolate_; |
| 116 intptr_t visited_; | 116 intptr_t visited_; |
| 117 | 117 |
| 118 DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor); | 118 DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor); |
| 119 }; | 119 }; |
| 120 | 120 |
| 121 // The maximum number of stack frames a sample can hold. | |
| 122 #define kSampleFramesSize 256 | |
| 123 | |
| 124 // Each Sample holds a stack trace from an isolate. | 121 // Each Sample holds a stack trace from an isolate. |
| 125 class Sample { | 122 class Sample { |
| 126 public: | 123 public: |
| 127 void Init(Isolate* isolate, int64_t timestamp, ThreadId tid) { | 124 void Init(Isolate* isolate, int64_t timestamp, ThreadId tid) { |
| 128 timestamp_ = timestamp; | 125 timestamp_ = timestamp; |
| 129 tid_ = tid; | 126 tid_ = tid; |
| 130 isolate_ = isolate; | 127 isolate_ = isolate; |
| 131 pc_marker_ = 0; | 128 pc_marker_ = 0; |
| 132 vm_tag_ = VMTag::kInvalidTagId; | 129 vm_tag_ = VMTag::kInvalidTagId; |
| 133 user_tag_ = UserTags::kDefaultUserTag; | 130 user_tag_ = UserTags::kDefaultUserTag; |
| 134 sp_ = 0; | 131 sp_ = 0; |
| 135 fp_ = 0; | 132 fp_ = 0; |
| 136 state_ = 0; | 133 state_ = 0; |
| 137 for (intptr_t i = 0; i < kSampleFramesSize; i++) { | 134 uword* pcs = GetPCArray(); |
| 138 pcs_[i] = 0; | 135 for (intptr_t i = 0; i < pcs_length_; i++) { |
| 136 pcs[i] = 0; |
| 139 } | 137 } |
| 140 } | 138 } |
| 141 | 139 |
| 142 // Isolate sample was taken from. | 140 // Isolate sample was taken from. |
| 143 Isolate* isolate() const { | 141 Isolate* isolate() const { |
| 144 return isolate_; | 142 return isolate_; |
| 145 } | 143 } |
| 146 | 144 |
| 147 // Timestamp sample was taken at. | 145 // Timestamp sample was taken at. |
| 148 int64_t timestamp() const { | 146 int64_t timestamp() const { |
| 149 return timestamp_; | 147 return timestamp_; |
| 150 } | 148 } |
| 151 | 149 |
| 152 // Get stack trace entry. | 150 // Get stack trace entry. |
| 153 uword At(intptr_t i) const { | 151 uword At(intptr_t i) const { |
| 154 ASSERT(i >= 0); | 152 ASSERT(i >= 0); |
| 155 ASSERT(i < kSampleFramesSize); | 153 ASSERT(i < pcs_length_); |
| 156 return pcs_[i]; | 154 uword* pcs = GetPCArray(); |
| 155 return pcs[i]; |
| 157 } | 156 } |
| 158 | 157 |
| 159 // Set stack trace entry. | 158 // Set stack trace entry. |
| 160 void SetAt(intptr_t i, uword pc) { | 159 void SetAt(intptr_t i, uword pc) { |
| 161 ASSERT(i >= 0); | 160 ASSERT(i >= 0); |
| 162 ASSERT(i < kSampleFramesSize); | 161 ASSERT(i < pcs_length_); |
| 163 pcs_[i] = pc; | 162 uword* pcs = GetPCArray(); |
| 163 pcs[i] = pc; |
| 164 } | 164 } |
| 165 | 165 |
| 166 uword vm_tag() const { | 166 uword vm_tag() const { |
| 167 return vm_tag_; | 167 return vm_tag_; |
| 168 } | 168 } |
| 169 void set_vm_tag(uword tag) { | 169 void set_vm_tag(uword tag) { |
| 170 ASSERT(tag != VMTag::kInvalidTagId); | 170 ASSERT(tag != VMTag::kInvalidTagId); |
| 171 vm_tag_ = tag; | 171 vm_tag_ = tag; |
| 172 } | 172 } |
| 173 | 173 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 196 | 196 |
| 197 uword fp() const { | 197 uword fp() const { |
| 198 return fp_; | 198 return fp_; |
| 199 } | 199 } |
| 200 | 200 |
| 201 void set_fp(uword fp) { | 201 void set_fp(uword fp) { |
| 202 fp_ = fp; | 202 fp_ = fp; |
| 203 } | 203 } |
| 204 | 204 |
| 205 void InsertCallerForTopFrame(uword pc) { | 205 void InsertCallerForTopFrame(uword pc) { |
| 206 if (pcs_length_ == 1) { |
| 207 // Only sampling top frame. |
| 208 return; |
| 209 } |
| 210 uword* pcs = GetPCArray(); |
| 206 // The caller for the top frame is store at index 1. | 211 // The caller for the top frame is store at index 1. |
| 207 // Shift all entries down by one. | 212 // Shift all entries down by one. |
| 208 for (intptr_t i = kSampleFramesSize - 1; i >= 2; i--) { | 213 for (intptr_t i = pcs_length_ - 1; i >= 2; i--) { |
| 209 pcs_[i] = pcs_[i - 1]; | 214 pcs[i] = pcs[i - 1]; |
| 210 } | 215 } |
| 211 // Insert caller for top frame. | 216 // Insert caller for top frame. |
| 212 pcs_[1] = pc; | 217 pcs[1] = pc; |
| 213 } | 218 } |
| 214 | 219 |
| 215 bool processed() const { | 220 bool processed() const { |
| 216 return ProcessedBit::decode(state_); | 221 return ProcessedBit::decode(state_); |
| 217 } | 222 } |
| 218 | 223 |
| 219 void set_processed(bool processed) { | 224 void set_processed(bool processed) { |
| 220 state_ = ProcessedBit::update(processed, state_); | 225 state_ = ProcessedBit::update(processed, state_); |
| 221 } | 226 } |
| 222 | 227 |
| 223 bool leaf_frame_is_dart() const { | 228 bool leaf_frame_is_dart() const { |
| 224 return LeafFrameIsDart::decode(state_); | 229 return LeafFrameIsDart::decode(state_); |
| 225 } | 230 } |
| 226 | 231 |
| 227 void set_leaf_frame_is_dart(bool leaf_frame_is_dart) { | 232 void set_leaf_frame_is_dart(bool leaf_frame_is_dart) { |
| 228 state_ = LeafFrameIsDart::update(leaf_frame_is_dart, state_); | 233 state_ = LeafFrameIsDart::update(leaf_frame_is_dart, state_); |
| 229 } | 234 } |
| 230 | 235 |
| 236 static void InitOnce(); |
| 237 |
| 238 static intptr_t instance_size() { |
| 239 return instance_size_; |
| 240 } |
| 241 |
| 242 uword* GetPCArray() const; |
| 243 |
| 231 private: | 244 private: |
| 245 static intptr_t instance_size_; |
| 246 static intptr_t pcs_length_; |
| 232 enum StateBits { | 247 enum StateBits { |
| 233 kProcessedBit = 0, | 248 kProcessedBit = 0, |
| 234 kLeafFrameIsDartBit = 1, | 249 kLeafFrameIsDartBit = 1, |
| 235 }; | 250 }; |
| 236 class ProcessedBit : public BitField<bool, kProcessedBit, 1> {}; | 251 class ProcessedBit : public BitField<bool, kProcessedBit, 1> {}; |
| 237 class LeafFrameIsDart : public BitField<bool, kLeafFrameIsDartBit, 1> {}; | 252 class LeafFrameIsDart : public BitField<bool, kLeafFrameIsDartBit, 1> {}; |
| 238 | 253 |
| 239 int64_t timestamp_; | 254 int64_t timestamp_; |
| 240 ThreadId tid_; | 255 ThreadId tid_; |
| 241 Isolate* isolate_; | 256 Isolate* isolate_; |
| 242 uword pc_marker_; | 257 uword pc_marker_; |
| 243 uword vm_tag_; | 258 uword vm_tag_; |
| 244 uword user_tag_; | 259 uword user_tag_; |
| 245 uword sp_; | 260 uword sp_; |
| 246 uword fp_; | 261 uword fp_; |
| 247 uword state_; | 262 uword state_; |
| 248 uword pcs_[kSampleFramesSize]; | 263 |
| 264 /* There are a variable number of words that follow, the words hold the |
| 265 * sampled pc values. Access via GetPCArray() */ |
| 266 |
| 267 DISALLOW_COPY_AND_ASSIGN(Sample); |
| 249 }; | 268 }; |
| 250 | 269 |
| 251 | 270 |
| 252 // Ring buffer of Samples that is (usually) shared by many isolates. | 271 // Ring buffer of Samples that is (usually) shared by many isolates. |
| 253 class SampleBuffer { | 272 class SampleBuffer { |
| 254 public: | 273 public: |
| 255 static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz. | 274 static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz. |
| 256 | 275 |
| 257 explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity) { | 276 explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity); |
| 258 samples_ = reinterpret_cast<Sample*>(calloc(capacity, sizeof(*samples_))); | |
| 259 capacity_ = capacity; | |
| 260 cursor_ = 0; | |
| 261 } | |
| 262 | 277 |
| 263 ~SampleBuffer() { | 278 ~SampleBuffer() { |
| 264 if (samples_ != NULL) { | 279 if (samples_ != NULL) { |
| 265 free(samples_); | 280 free(samples_); |
| 266 samples_ = NULL; | 281 samples_ = NULL; |
| 267 cursor_ = 0; | 282 cursor_ = 0; |
| 268 capacity_ = 0; | 283 capacity_ = 0; |
| 269 } | 284 } |
| 270 } | 285 } |
| 271 | 286 |
| 272 intptr_t capacity() const { return capacity_; } | 287 intptr_t capacity() const { return capacity_; } |
| 273 | 288 |
| 289 Sample* At(intptr_t idx) const; |
| 274 Sample* ReserveSample(); | 290 Sample* ReserveSample(); |
| 275 | 291 |
| 276 Sample* At(intptr_t idx) const { | |
| 277 ASSERT(idx >= 0); | |
| 278 ASSERT(idx < capacity_); | |
| 279 return &samples_[idx]; | |
| 280 } | |
| 281 | |
| 282 void VisitSamples(SampleVisitor* visitor) { | 292 void VisitSamples(SampleVisitor* visitor) { |
| 283 ASSERT(visitor != NULL); | 293 ASSERT(visitor != NULL); |
| 284 const intptr_t length = capacity(); | 294 const intptr_t length = capacity(); |
| 285 for (intptr_t i = 0; i < length; i++) { | 295 for (intptr_t i = 0; i < length; i++) { |
| 286 Sample* sample = At(i); | 296 Sample* sample = At(i); |
| 287 if (sample->isolate() != visitor->isolate()) { | 297 if (sample->isolate() != visitor->isolate()) { |
| 288 // Another isolate. | 298 // Another isolate. |
| 289 continue; | 299 continue; |
| 290 } | 300 } |
| 291 if (sample->timestamp() == 0) { | 301 if (sample->timestamp() == 0) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 306 intptr_t capacity_; | 316 intptr_t capacity_; |
| 307 uintptr_t cursor_; | 317 uintptr_t cursor_; |
| 308 | 318 |
| 309 DISALLOW_COPY_AND_ASSIGN(SampleBuffer); | 319 DISALLOW_COPY_AND_ASSIGN(SampleBuffer); |
| 310 }; | 320 }; |
| 311 | 321 |
| 312 | 322 |
| 313 } // namespace dart | 323 } // namespace dart |
| 314 | 324 |
| 315 #endif // VM_PROFILER_H_ | 325 #endif // VM_PROFILER_H_ |
| OLD | NEW |