| 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/bitfield.h" | 9 #include "vm/bitfield.h" |
| 10 #include "vm/code_observers.h" | 10 #include "vm/code_observers.h" |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 timestamp_ = timestamp; | 148 timestamp_ = timestamp; |
| 149 tid_ = tid; | 149 tid_ = tid; |
| 150 isolate_ = isolate; | 150 isolate_ = isolate; |
| 151 } | 151 } |
| 152 | 152 |
| 153 // Isolate sample was taken from. | 153 // Isolate sample was taken from. |
| 154 Isolate* isolate() const { | 154 Isolate* isolate() const { |
| 155 return isolate_; | 155 return isolate_; |
| 156 } | 156 } |
| 157 | 157 |
| 158 // Thread sample was taken on. |
| 159 ThreadId tid() const { |
| 160 return tid_; |
| 161 } |
| 162 |
| 158 void Clear() { | 163 void Clear() { |
| 159 isolate_ = NULL; | 164 isolate_ = NULL; |
| 160 pc_marker_ = 0; | 165 pc_marker_ = 0; |
| 161 for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) { | 166 for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) { |
| 162 stack_buffer_[i] = 0; | 167 stack_buffer_[i] = 0; |
| 163 } | 168 } |
| 164 vm_tag_ = VMTag::kInvalidTagId; | 169 vm_tag_ = VMTag::kInvalidTagId; |
| 165 user_tag_ = UserTags::kDefaultUserTag; | 170 user_tag_ = UserTags::kDefaultUserTag; |
| 166 lr_ = 0; | 171 lr_ = 0; |
| 167 metadata_ = 0; | 172 metadata_ = 0; |
| 168 state_ = 0; | 173 state_ = 0; |
| 174 continuation_index_ = -1; |
| 169 uword* pcs = GetPCArray(); | 175 uword* pcs = GetPCArray(); |
| 170 for (intptr_t i = 0; i < pcs_length_; i++) { | 176 for (intptr_t i = 0; i < pcs_length_; i++) { |
| 171 pcs[i] = 0; | 177 pcs[i] = 0; |
| 172 } | 178 } |
| 179 set_head_sample(true); |
| 173 } | 180 } |
| 174 | 181 |
| 175 // Timestamp sample was taken at. | 182 // Timestamp sample was taken at. |
| 176 int64_t timestamp() const { | 183 int64_t timestamp() const { |
| 177 return timestamp_; | 184 return timestamp_; |
| 178 } | 185 } |
| 179 | 186 |
| 180 // Top most pc. | 187 // Top most pc. |
| 181 uword pc() const { | 188 uword pc() const { |
| 182 return At(0); | 189 return At(0); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 } | 229 } |
| 223 | 230 |
| 224 uword lr() const { | 231 uword lr() const { |
| 225 return lr_; | 232 return lr_; |
| 226 } | 233 } |
| 227 | 234 |
| 228 void set_lr(uword link_register) { | 235 void set_lr(uword link_register) { |
| 229 lr_ = link_register; | 236 lr_ = link_register; |
| 230 } | 237 } |
| 231 | 238 |
| 232 void InsertCallerForTopFrame(uword pc) { | |
| 233 if (pcs_length_ == 1) { | |
| 234 // Only sampling top frame. | |
| 235 return; | |
| 236 } | |
| 237 uword* pcs = GetPCArray(); | |
| 238 // The caller for the top frame is store at index 1. | |
| 239 // Shift all entries down by one. | |
| 240 for (intptr_t i = pcs_length_ - 1; i >= 2; i--) { | |
| 241 pcs[i] = pcs[i - 1]; | |
| 242 } | |
| 243 // Insert caller for top frame. | |
| 244 pcs[1] = pc; | |
| 245 set_missing_frame_inserted(true); | |
| 246 } | |
| 247 | |
| 248 bool processed() const { | |
| 249 return ProcessedBit::decode(state_); | |
| 250 } | |
| 251 | |
| 252 void set_processed(bool processed) { | |
| 253 state_ = ProcessedBit::update(processed, state_); | |
| 254 } | |
| 255 | |
| 256 bool leaf_frame_is_dart() const { | 239 bool leaf_frame_is_dart() const { |
| 257 return LeafFrameIsDart::decode(state_); | 240 return LeafFrameIsDart::decode(state_); |
| 258 } | 241 } |
| 259 | 242 |
| 260 void set_leaf_frame_is_dart(bool leaf_frame_is_dart) { | 243 void set_leaf_frame_is_dart(bool leaf_frame_is_dart) { |
| 261 state_ = LeafFrameIsDart::update(leaf_frame_is_dart, state_); | 244 state_ = LeafFrameIsDart::update(leaf_frame_is_dart, state_); |
| 262 } | 245 } |
| 263 | 246 |
| 264 bool ignore_sample() const { | 247 bool ignore_sample() const { |
| 265 return IgnoreBit::decode(state_); | 248 return IgnoreBit::decode(state_); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 294 } | 277 } |
| 295 | 278 |
| 296 bool is_allocation_sample() const { | 279 bool is_allocation_sample() const { |
| 297 return ClassAllocationSampleBit::decode(state_); | 280 return ClassAllocationSampleBit::decode(state_); |
| 298 } | 281 } |
| 299 | 282 |
| 300 void set_is_allocation_sample(bool allocation_sample) { | 283 void set_is_allocation_sample(bool allocation_sample) { |
| 301 state_ = ClassAllocationSampleBit::update(allocation_sample, state_); | 284 state_ = ClassAllocationSampleBit::update(allocation_sample, state_); |
| 302 } | 285 } |
| 303 | 286 |
| 287 bool is_continuation_sample() const { |
| 288 return ContinuationSampleBit::decode(state_); |
| 289 } |
| 290 |
| 291 void SetContinuationIndex(intptr_t index) { |
| 292 ASSERT(!is_continuation_sample()); |
| 293 ASSERT(continuation_index_ == -1); |
| 294 state_ = ContinuationSampleBit::update(true, state_); |
| 295 continuation_index_ = index; |
| 296 ASSERT(is_continuation_sample()); |
| 297 } |
| 298 |
| 299 intptr_t continuation_index() const { |
| 300 ASSERT(is_continuation_sample()); |
| 301 return continuation_index_; |
| 302 } |
| 303 |
| 304 intptr_t allocation_cid() const { | 304 intptr_t allocation_cid() const { |
| 305 ASSERT(is_allocation_sample()); | 305 ASSERT(is_allocation_sample()); |
| 306 return metadata_; | 306 return metadata_; |
| 307 } | 307 } |
| 308 | 308 |
| 309 void set_head_sample(bool head_sample) { |
| 310 state_ = HeadSampleBit::update(head_sample, state_); |
| 311 } |
| 312 |
| 313 bool head_sample() const { |
| 314 return HeadSampleBit::decode(state_); |
| 315 } |
| 316 |
| 309 void set_metadata(intptr_t metadata) { | 317 void set_metadata(intptr_t metadata) { |
| 310 metadata_ = metadata; | 318 metadata_ = metadata; |
| 311 } | 319 } |
| 312 | 320 |
| 313 void SetAllocationCid(intptr_t cid) { | 321 void SetAllocationCid(intptr_t cid) { |
| 314 set_is_allocation_sample(true); | 322 set_is_allocation_sample(true); |
| 315 set_metadata(cid); | 323 set_metadata(cid); |
| 316 } | 324 } |
| 317 | 325 |
| 318 static void InitOnce(); | 326 static void InitOnce(); |
| 319 | 327 |
| 320 static intptr_t instance_size() { | 328 static intptr_t instance_size() { |
| 321 return instance_size_; | 329 return instance_size_; |
| 322 } | 330 } |
| 323 | 331 |
| 324 uword* GetPCArray() const; | 332 uword* GetPCArray() const; |
| 325 | 333 |
| 326 static const int kStackBufferSizeInWords = 2; | 334 static const int kStackBufferSizeInWords = 2; |
| 327 uword* GetStackBuffer() { | 335 uword* GetStackBuffer() { |
| 328 return &stack_buffer_[0]; | 336 return &stack_buffer_[0]; |
| 329 } | 337 } |
| 330 | 338 |
| 331 private: | 339 private: |
| 332 static intptr_t instance_size_; | 340 static intptr_t instance_size_; |
| 333 static intptr_t pcs_length_; | 341 static intptr_t pcs_length_; |
| 334 enum StateBits { | 342 enum StateBits { |
| 335 kProcessedBit = 0, | 343 kHeadSampleBit = 0, |
| 336 kLeafFrameIsDartBit = 1, | 344 kLeafFrameIsDartBit = 1, |
| 337 kIgnoreBit = 2, | 345 kIgnoreBit = 2, |
| 338 kExitFrameBit = 3, | 346 kExitFrameBit = 3, |
| 339 kMissingFrameInsertedBit = 4, | 347 kMissingFrameInsertedBit = 4, |
| 340 kTruncatedTrace = 5, | 348 kTruncatedTraceBit = 5, |
| 341 kClassAllocationSample = 6, | 349 kClassAllocationSampleBit = 6, |
| 350 kContinuationSampleBit = 7, |
| 342 }; | 351 }; |
| 343 class ProcessedBit : public BitField<bool, kProcessedBit, 1> {}; | 352 class HeadSampleBit : public BitField<bool, kHeadSampleBit, 1> {}; |
| 344 class LeafFrameIsDart : public BitField<bool, kLeafFrameIsDartBit, 1> {}; | 353 class LeafFrameIsDart : public BitField<bool, kLeafFrameIsDartBit, 1> {}; |
| 345 class IgnoreBit : public BitField<bool, kIgnoreBit, 1> {}; | 354 class IgnoreBit : public BitField<bool, kIgnoreBit, 1> {}; |
| 346 class ExitFrameBit : public BitField<bool, kExitFrameBit, 1> {}; | 355 class ExitFrameBit : public BitField<bool, kExitFrameBit, 1> {}; |
| 347 class MissingFrameInsertedBit | 356 class MissingFrameInsertedBit |
| 348 : public BitField<bool, kMissingFrameInsertedBit, 1> {}; | 357 : public BitField<bool, kMissingFrameInsertedBit, 1> {}; |
| 349 class TruncatedTraceBit : public BitField<bool, kTruncatedTrace, 1> {}; | 358 class TruncatedTraceBit : public BitField<bool, kTruncatedTraceBit, 1> {}; |
| 350 class ClassAllocationSampleBit | 359 class ClassAllocationSampleBit |
| 351 : public BitField<bool, kClassAllocationSample, 1> {}; | 360 : public BitField<bool, kClassAllocationSampleBit, 1> {}; |
| 361 class ContinuationSampleBit |
| 362 : public BitField<bool, kContinuationSampleBit, 1> {}; |
| 352 | 363 |
| 353 int64_t timestamp_; | 364 int64_t timestamp_; |
| 354 ThreadId tid_; | 365 ThreadId tid_; |
| 355 Isolate* isolate_; | 366 Isolate* isolate_; |
| 356 uword pc_marker_; | 367 uword pc_marker_; |
| 357 uword stack_buffer_[kStackBufferSizeInWords]; | 368 uword stack_buffer_[kStackBufferSizeInWords]; |
| 358 uword vm_tag_; | 369 uword vm_tag_; |
| 359 uword user_tag_; | 370 uword user_tag_; |
| 360 uword metadata_; | 371 uword metadata_; |
| 361 uword lr_; | 372 uword lr_; |
| 362 uword state_; | 373 uword state_; |
| 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 |
| 365 * sampled pc values. Access via GetPCArray() */ | 377 * sampled pc values. Access via GetPCArray() */ |
| 366 | 378 |
| 367 DISALLOW_COPY_AND_ASSIGN(Sample); | 379 DISALLOW_COPY_AND_ASSIGN(Sample); |
| 368 }; | 380 }; |
| 369 | 381 |
| 370 | 382 |
| 371 // Ring buffer of Samples that is (usually) shared by many isolates. | 383 // Ring buffer of Samples that is (usually) shared by many isolates. |
| 372 class SampleBuffer { | 384 class SampleBuffer { |
| 373 public: | 385 public: |
| 374 static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz. | 386 static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz. |
| 375 | 387 |
| 376 explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity); | 388 explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity); |
| 377 | 389 |
| 378 ~SampleBuffer() { | 390 ~SampleBuffer() { |
| 379 if (samples_ != NULL) { | 391 if (samples_ != NULL) { |
| 380 free(samples_); | 392 free(samples_); |
| 381 samples_ = NULL; | 393 samples_ = NULL; |
| 382 cursor_ = 0; | 394 cursor_ = 0; |
| 383 capacity_ = 0; | 395 capacity_ = 0; |
| 384 } | 396 } |
| 385 } | 397 } |
| 386 | 398 |
| 387 intptr_t capacity() const { return capacity_; } | 399 intptr_t capacity() const { return capacity_; } |
| 388 | 400 |
| 389 Sample* At(intptr_t idx) const; | 401 Sample* At(intptr_t idx) const; |
| 402 intptr_t ReserveSampleSlot(); |
| 390 Sample* ReserveSample(); | 403 Sample* ReserveSample(); |
| 404 Sample* ReserveSampleAndLink(Sample* previous); |
| 391 | 405 |
| 392 void VisitSamples(SampleVisitor* visitor) { | 406 void VisitSamples(SampleVisitor* visitor) { |
| 393 ASSERT(visitor != NULL); | 407 ASSERT(visitor != NULL); |
| 394 const intptr_t length = capacity(); | 408 const intptr_t length = capacity(); |
| 395 for (intptr_t i = 0; i < length; i++) { | 409 for (intptr_t i = 0; i < length; i++) { |
| 396 Sample* sample = At(i); | 410 Sample* sample = At(i); |
| 411 if (!sample->head_sample()) { |
| 412 // An inner sample in a chain of samples. |
| 413 continue; |
| 414 } |
| 397 if (sample->ignore_sample()) { | 415 if (sample->ignore_sample()) { |
| 398 // Bad sample. | 416 // Bad sample. |
| 399 continue; | 417 continue; |
| 400 } | 418 } |
| 401 if (sample->isolate() != visitor->isolate()) { | 419 if (sample->isolate() != visitor->isolate()) { |
| 402 // Another isolate. | 420 // Another isolate. |
| 403 continue; | 421 continue; |
| 404 } | 422 } |
| 405 if (sample->timestamp() == 0) { | 423 if (sample->timestamp() == 0) { |
| 406 // Empty. | 424 // Empty. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 | 556 |
| 539 private: | 557 private: |
| 540 ZoneGrowableArray<ProcessedSample*> samples_; | 558 ZoneGrowableArray<ProcessedSample*> samples_; |
| 541 | 559 |
| 542 DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer); | 560 DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer); |
| 543 }; | 561 }; |
| 544 | 562 |
| 545 } // namespace dart | 563 } // namespace dart |
| 546 | 564 |
| 547 #endif // VM_PROFILER_H_ | 565 #endif // VM_PROFILER_H_ |
| OLD | NEW |