| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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_TIMELINE_H_ | 5 #ifndef VM_TIMELINE_H_ |
| 6 #define VM_TIMELINE_H_ | 6 #define VM_TIMELINE_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/bitfield.h" | 9 #include "vm/bitfield.h" |
| 10 | 10 |
| 11 namespace dart { | 11 namespace dart { |
| 12 | 12 |
| 13 class JSONArray; | 13 class JSONArray; |
| 14 class JSONObject; | 14 class JSONObject; |
| 15 class JSONStream; | 15 class JSONStream; |
| 16 class Object; | 16 class Object; |
| 17 class ObjectPointerVisitor; | 17 class ObjectPointerVisitor; |
| 18 class Isolate; |
| 18 class RawArray; | 19 class RawArray; |
| 19 class Thread; | 20 class Thread; |
| 20 class TimelineEvent; | 21 class TimelineEvent; |
| 21 class TimelineEventBlock; | 22 class TimelineEventBlock; |
| 22 class TimelineEventRecorder; | 23 class TimelineEventRecorder; |
| 23 class TimelineStream; | 24 class TimelineStream; |
| 25 class Zone; |
| 24 | 26 |
| 25 // (name, enabled by default for isolate). | 27 // (name, enabled by default for isolate). |
| 26 #define ISOLATE_TIMELINE_STREAM_LIST(V) \ | 28 #define ISOLATE_TIMELINE_STREAM_LIST(V) \ |
| 27 V(API, false) \ | 29 V(API, false) \ |
| 28 V(Compiler, false) \ | 30 V(Compiler, false) \ |
| 31 V(Dart, false) \ |
| 29 V(Embedder, false) \ | 32 V(Embedder, false) \ |
| 30 V(GC, false) \ | 33 V(GC, false) \ |
| 31 V(Isolate, false) \ | 34 V(Isolate, false) \ |
| 32 | 35 |
| 33 class Timeline : public AllStatic { | 36 class Timeline : public AllStatic { |
| 34 public: | 37 public: |
| 35 // Initialize timeline system. Not thread safe. | 38 // Initialize timeline system. Not thread safe. |
| 36 static void InitOnce(); | 39 static void InitOnce(); |
| 37 | 40 |
| 38 // Shutdown timeline system. Not thread safe. | 41 // Shutdown timeline system. Not thread safe. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 const char* category_; | 200 const char* category_; |
| 198 ThreadId thread_; | 201 ThreadId thread_; |
| 199 Isolate* isolate_; | 202 Isolate* isolate_; |
| 200 | 203 |
| 201 void FreeArguments(); | 204 void FreeArguments(); |
| 202 | 205 |
| 203 void StreamInit(TimelineStream* stream); | 206 void StreamInit(TimelineStream* stream); |
| 204 void Init(EventType event_type, const char* label); | 207 void Init(EventType event_type, const char* label); |
| 205 | 208 |
| 206 void set_event_type(EventType event_type) { | 209 void set_event_type(EventType event_type) { |
| 210 // We only reserve 4 bits to hold the event type. |
| 211 COMPILE_ASSERT(kNumEventTypes < 16); |
| 207 state_ = EventTypeField::update(event_type, state_); | 212 state_ = EventTypeField::update(event_type, state_); |
| 208 } | 213 } |
| 209 | 214 |
| 210 enum StateBits { | 215 enum StateBits { |
| 211 kEventTypeBit = 0, | 216 kEventTypeBit = 0, |
| 212 // reserve 4 bits for type. | 217 // reserve 4 bits for type. |
| 213 kNextBit = 4, | 218 kNextBit = 4, |
| 214 }; | 219 }; |
| 215 | 220 |
| 216 class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {}; | 221 class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {}; |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 // Not empty, not in use, and isolate match. | 478 // Not empty, not in use, and isolate match. |
| 474 return !block->IsEmpty() && !block->in_use() && | 479 return !block->IsEmpty() && !block->in_use() && |
| 475 (block->isolate() == isolate_); | 480 (block->isolate() == isolate_); |
| 476 } | 481 } |
| 477 | 482 |
| 478 private: | 483 private: |
| 479 Isolate* isolate_; | 484 Isolate* isolate_; |
| 480 }; | 485 }; |
| 481 | 486 |
| 482 | 487 |
| 488 // Timeline events from Dart code are eagerly converted to JSON and stored |
| 489 // as a C string. |
| 490 class DartTimelineEvent { |
| 491 public: |
| 492 DartTimelineEvent(); |
| 493 ~DartTimelineEvent(); |
| 494 |
| 495 void Clear(); |
| 496 |
| 497 // This function makes a copy of |event|. |
| 498 void Init(Isolate* isolate, const char* event); |
| 499 |
| 500 bool IsValid() const { |
| 501 return (isolate_ != NULL) && |
| 502 (event_as_json_ != NULL); |
| 503 } |
| 504 |
| 505 Isolate* isolate() const { |
| 506 return isolate_; |
| 507 } |
| 508 |
| 509 char* event_as_json() const { |
| 510 return event_as_json_; |
| 511 } |
| 512 |
| 513 private: |
| 514 Isolate* isolate_; |
| 515 char* event_as_json_; |
| 516 |
| 517 DISALLOW_COPY_AND_ASSIGN(DartTimelineEvent); |
| 518 }; |
| 519 |
| 520 |
| 483 // Recorder of |TimelineEvent|s. | 521 // Recorder of |TimelineEvent|s. |
| 484 class TimelineEventRecorder { | 522 class TimelineEventRecorder { |
| 485 public: | 523 public: |
| 486 TimelineEventRecorder(); | 524 TimelineEventRecorder(); |
| 487 virtual ~TimelineEventRecorder() {} | 525 virtual ~TimelineEventRecorder() {} |
| 488 | 526 |
| 489 TimelineEventBlock* GetNewBlock(); | 527 TimelineEventBlock* GetNewBlock(); |
| 490 | 528 |
| 491 // Interface method(s) which must be implemented. | 529 // Interface method(s) which must be implemented. |
| 492 virtual void PrintJSON(JSONStream* js, TimelineEventFilter* filter) = 0; | 530 virtual void PrintJSON(JSONStream* js, TimelineEventFilter* filter) = 0; |
| 493 virtual void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) = 0; | 531 virtual void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) = 0; |
| 494 | 532 |
| 495 int64_t GetNextAsyncId(); | 533 int64_t GetNextAsyncId(); |
| 496 | 534 |
| 497 void FinishBlock(TimelineEventBlock* block); | 535 void FinishBlock(TimelineEventBlock* block); |
| 498 | 536 |
| 537 // Interface method(s) which must be implemented. |
| 538 virtual void AppendDartEvent(Isolate* isolate, const char* event) = 0; |
| 539 |
| 499 protected: | 540 protected: |
| 500 void WriteTo(const char* directory); | 541 void WriteTo(const char* directory); |
| 501 | 542 |
| 502 // Interface method(s) which must be implemented. | 543 // Interface method(s) which must be implemented. |
| 503 virtual TimelineEvent* StartEvent() = 0; | 544 virtual TimelineEvent* StartEvent() = 0; |
| 504 virtual void CompleteEvent(TimelineEvent* event) = 0; | 545 virtual void CompleteEvent(TimelineEvent* event) = 0; |
| 505 virtual TimelineEventBlock* GetHeadBlockLocked() = 0; | 546 virtual TimelineEventBlock* GetHeadBlockLocked() = 0; |
| 506 virtual TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) = 0; | 547 virtual TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) = 0; |
| 548 virtual intptr_t NumDartEventsLocked() = 0; |
| 549 virtual DartTimelineEvent* DartEventAtLocked(intptr_t i) = 0; |
| 507 | 550 |
| 508 // Utility method(s). | 551 // Utility method(s). |
| 509 void PrintJSONMeta(JSONArray* array) const; | 552 void PrintJSONMeta(JSONArray* array) const; |
| 510 TimelineEvent* ThreadBlockStartEvent(); | 553 TimelineEvent* ThreadBlockStartEvent(); |
| 511 TimelineEvent* GlobalBlockStartEvent(); | 554 TimelineEvent* GlobalBlockStartEvent(); |
| 512 | 555 |
| 513 Mutex lock_; | 556 Mutex lock_; |
| 514 // Only accessed under |lock_|. | 557 // Only accessed under |lock_|. |
| 515 TimelineEventBlock* global_block_; | 558 TimelineEventBlock* global_block_; |
| 516 void ReclaimGlobalBlock(); | 559 void ReclaimGlobalBlock(); |
| 517 | 560 |
| 518 uintptr_t async_id_; | 561 uintptr_t async_id_; |
| 519 | 562 |
| 563 friend class DartTimelineEventIterator; |
| 520 friend class TimelineEvent; | 564 friend class TimelineEvent; |
| 521 friend class TimelineEventBlockIterator; | 565 friend class TimelineEventBlockIterator; |
| 522 friend class TimelineStream; | 566 friend class TimelineStream; |
| 523 friend class TimelineTestHelper; | 567 friend class TimelineTestHelper; |
| 524 friend class Timeline; | 568 friend class Timeline; |
| 525 | 569 |
| 526 private: | 570 private: |
| 527 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder); | 571 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder); |
| 528 }; | 572 }; |
| 529 | 573 |
| 530 | 574 |
| 531 // A recorder that stores events in a ring buffer of fixed capacity. | 575 // A recorder that stores events in a ring buffer of fixed capacity. |
| 532 class TimelineEventRingRecorder : public TimelineEventRecorder { | 576 class TimelineEventRingRecorder : public TimelineEventRecorder { |
| 533 public: | 577 public: |
| 534 static const intptr_t kDefaultCapacity = 8192; | 578 static const intptr_t kDefaultCapacity = 8192; |
| 535 | 579 |
| 536 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity); | 580 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity); |
| 537 ~TimelineEventRingRecorder(); | 581 ~TimelineEventRingRecorder(); |
| 538 | 582 |
| 539 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); | 583 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); |
| 540 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); | 584 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); |
| 541 | 585 |
| 586 void AppendDartEvent(Isolate* isolate, const char* event); |
| 587 |
| 542 protected: | 588 protected: |
| 543 TimelineEvent* StartEvent(); | 589 TimelineEvent* StartEvent(); |
| 544 void CompleteEvent(TimelineEvent* event); | 590 void CompleteEvent(TimelineEvent* event); |
| 545 TimelineEventBlock* GetHeadBlockLocked(); | 591 TimelineEventBlock* GetHeadBlockLocked(); |
| 546 intptr_t FindOldestBlockIndex() const; | 592 intptr_t FindOldestBlockIndex() const; |
| 547 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate); | 593 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate); |
| 594 intptr_t NumDartEventsLocked(); |
| 595 DartTimelineEvent* DartEventAtLocked(intptr_t i); |
| 548 | 596 |
| 549 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter) const; | 597 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter) const; |
| 550 | 598 |
| 551 TimelineEventBlock** blocks_; | 599 TimelineEventBlock** blocks_; |
| 552 intptr_t capacity_; | 600 intptr_t capacity_; |
| 553 intptr_t num_blocks_; | 601 intptr_t num_blocks_; |
| 554 intptr_t block_cursor_; | 602 intptr_t block_cursor_; |
| 603 |
| 604 DartTimelineEvent** dart_events_; |
| 605 intptr_t dart_events_capacity_; |
| 606 intptr_t dart_events_cursor_; |
| 555 }; | 607 }; |
| 556 | 608 |
| 557 | 609 |
| 558 // An abstract recorder that calls |StreamEvent| whenever an event is complete. | 610 // An abstract recorder that calls |StreamEvent| whenever an event is complete. |
| 559 class TimelineEventStreamingRecorder : public TimelineEventRecorder { | 611 class TimelineEventStreamingRecorder : public TimelineEventRecorder { |
| 560 public: | 612 public: |
| 561 TimelineEventStreamingRecorder(); | 613 TimelineEventStreamingRecorder(); |
| 562 ~TimelineEventStreamingRecorder(); | 614 ~TimelineEventStreamingRecorder(); |
| 563 | 615 |
| 564 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); | 616 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); |
| 565 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); | 617 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); |
| 566 | 618 |
| 619 void AppendDartEvent(Isolate* isolate, const char* event); |
| 620 |
| 567 // Called when |event| is ready to be streamed. It is unsafe to keep a | 621 // Called when |event| is ready to be streamed. It is unsafe to keep a |
| 568 // reference to |event| as it may be freed as soon as this function returns. | 622 // reference to |event| as it may be freed as soon as this function returns. |
| 569 virtual void StreamEvent(TimelineEvent* event) = 0; | 623 virtual void StreamEvent(TimelineEvent* event) = 0; |
| 624 virtual void StreamDartEvent(const char* event) = 0; |
| 570 | 625 |
| 571 protected: | 626 protected: |
| 572 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) { | 627 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate) { |
| 573 return NULL; | 628 return NULL; |
| 574 } | 629 } |
| 575 TimelineEventBlock* GetHeadBlockLocked() { | 630 TimelineEventBlock* GetHeadBlockLocked() { |
| 576 return NULL; | 631 return NULL; |
| 577 } | 632 } |
| 633 intptr_t NumDartEventsLocked(); |
| 634 DartTimelineEvent* DartEventAtLocked(intptr_t i); |
| 578 TimelineEvent* StartEvent(); | 635 TimelineEvent* StartEvent(); |
| 579 void CompleteEvent(TimelineEvent* event); | 636 void CompleteEvent(TimelineEvent* event); |
| 580 }; | 637 }; |
| 581 | 638 |
| 582 | 639 |
| 583 // A recorder that stores events in chains of blocks of events. | 640 // A recorder that stores events in chains of blocks of events. |
| 584 // NOTE: This recorder will continue to allocate blocks until it exhausts | 641 // NOTE: This recorder will continue to allocate blocks until it exhausts |
| 585 // memory. | 642 // memory. |
| 586 class TimelineEventEndlessRecorder : public TimelineEventRecorder { | 643 class TimelineEventEndlessRecorder : public TimelineEventRecorder { |
| 587 public: | 644 public: |
| 588 TimelineEventEndlessRecorder(); | 645 TimelineEventEndlessRecorder(); |
| 589 | 646 |
| 590 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); | 647 void PrintJSON(JSONStream* js, TimelineEventFilter* filter); |
| 591 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); | 648 void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter); |
| 592 | 649 |
| 650 void AppendDartEvent(Isolate* isolate, const char* event); |
| 651 |
| 593 protected: | 652 protected: |
| 594 TimelineEvent* StartEvent(); | 653 TimelineEvent* StartEvent(); |
| 595 void CompleteEvent(TimelineEvent* event); | 654 void CompleteEvent(TimelineEvent* event); |
| 596 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate); | 655 TimelineEventBlock* GetNewBlockLocked(Isolate* isolate); |
| 597 TimelineEventBlock* GetHeadBlockLocked(); | 656 TimelineEventBlock* GetHeadBlockLocked(); |
| 657 intptr_t NumDartEventsLocked(); |
| 658 DartTimelineEvent* DartEventAtLocked(intptr_t i); |
| 598 | 659 |
| 599 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter) const; | 660 void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter) const; |
| 600 | 661 |
| 601 // Useful only for testing. Only works for one thread. | 662 // Useful only for testing. Only works for one thread. |
| 602 void Clear(); | 663 void Clear(); |
| 603 | 664 |
| 604 TimelineEventBlock* head_; | 665 TimelineEventBlock* head_; |
| 605 intptr_t block_index_; | 666 intptr_t block_index_; |
| 606 | 667 |
| 668 DartTimelineEvent** dart_events_; |
| 669 intptr_t dart_events_capacity_; |
| 670 intptr_t dart_events_cursor_; |
| 671 |
| 607 friend class TimelineTestHelper; | 672 friend class TimelineTestHelper; |
| 608 }; | 673 }; |
| 609 | 674 |
| 610 | 675 |
| 611 // An iterator for blocks. | 676 // An iterator for blocks. |
| 612 class TimelineEventBlockIterator { | 677 class TimelineEventBlockIterator { |
| 613 public: | 678 public: |
| 614 explicit TimelineEventBlockIterator(TimelineEventRecorder* recorder); | 679 explicit TimelineEventBlockIterator(TimelineEventRecorder* recorder); |
| 615 ~TimelineEventBlockIterator(); | 680 ~TimelineEventBlockIterator(); |
| 616 | 681 |
| 617 void Reset(TimelineEventRecorder* recorder); | 682 void Reset(TimelineEventRecorder* recorder); |
| 618 | 683 |
| 619 // Returns false when there are no more blocks. | 684 // Returns false when there are no more blocks. |
| 620 bool HasNext() const; | 685 bool HasNext() const; |
| 621 | 686 |
| 622 // Returns the next block and moves forward. | 687 // Returns the next block and moves forward. |
| 623 TimelineEventBlock* Next(); | 688 TimelineEventBlock* Next(); |
| 624 | 689 |
| 625 private: | 690 private: |
| 626 TimelineEventBlock* current_; | 691 TimelineEventBlock* current_; |
| 627 TimelineEventRecorder* recorder_; | 692 TimelineEventRecorder* recorder_; |
| 628 }; | 693 }; |
| 629 | 694 |
| 695 |
| 696 // An iterator for timeline events. |
| 697 class DartTimelineEventIterator { |
| 698 public: |
| 699 explicit DartTimelineEventIterator(TimelineEventRecorder* recorder); |
| 700 ~DartTimelineEventIterator(); |
| 701 |
| 702 void Reset(TimelineEventRecorder* recorder); |
| 703 |
| 704 // Returns true if there is another event. |
| 705 bool HasNext() const; |
| 706 |
| 707 // Returns the next event and moves forward. |
| 708 DartTimelineEvent* Next(); |
| 709 |
| 710 // Returns a zone allocated string of all trace events for isolate. |
| 711 // If isolate is NULL, all isolates' events will be included. |
| 712 static const char* PrintTraceEvents(TimelineEventRecorder* recorder, |
| 713 Zone* zone, |
| 714 Isolate* isolate); |
| 715 |
| 716 private: |
| 717 intptr_t cursor_; |
| 718 intptr_t num_events_; |
| 719 TimelineEventRecorder* recorder_; |
| 720 }; |
| 721 |
| 630 } // namespace dart | 722 } // namespace dart |
| 631 | 723 |
| 632 #endif // VM_TIMELINE_H_ | 724 #endif // VM_TIMELINE_H_ |
| OLD | NEW |