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 |