Chromium Code Reviews| 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 #include <cstdlib> | 5 #include <cstdlib> |
| 6 | 6 |
| 7 #include "vm/atomic.h" | 7 #include "vm/atomic.h" |
| 8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
| 9 #include "vm/json_stream.h" | 9 #include "vm/json_stream.h" |
| 10 #include "vm/lockers.h" | 10 #include "vm/lockers.h" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 // synchronizing with other threads in the system. Even though the |Thread| owns | 34 // synchronizing with other threads in the system. Even though the |Thread| owns |
| 35 // the |TimelineEventBlock| the block may need to be reclaimed by the reporting | 35 // the |TimelineEventBlock| the block may need to be reclaimed by the reporting |
| 36 // system. To support that, a |Thread| must hold its |timeline_block_lock_| | 36 // system. To support that, a |Thread| must hold its |timeline_block_lock_| |
| 37 // when operating on the |TimelineEventBlock|. This lock will only ever be | 37 // when operating on the |TimelineEventBlock|. This lock will only ever be |
| 38 // busy if blocks are being reclaimed by the reporting system. | 38 // busy if blocks are being reclaimed by the reporting system. |
| 39 // | 39 // |
| 40 // Reporting: | 40 // Reporting: |
| 41 // When requested, the timeline is serialized in the trace-event format | 41 // When requested, the timeline is serialized in the trace-event format |
| 42 // (https://goo.gl/hDZw5M). The request can be for a VM-wide timeline or an | 42 // (https://goo.gl/hDZw5M). The request can be for a VM-wide timeline or an |
| 43 // isolate specific timeline. In both cases it may be that a thread has | 43 // isolate specific timeline. In both cases it may be that a thread has |
| 44 // a |TimelineEventBlock| cached in TLS. In order to report a complete timeline | 44 // a |TimelineEventBlock| cached in TLS partially filled with events. In order |
|
turnidge
2015/10/16 19:40:20
Is it really cached in TLS? Seems out of date.
Cutch
2015/10/16 19:43:52
Done.
| |
| 45 // the cached |TimelineEventBlock|s need to be reclaimed. | 45 // to report a complete timeline the cached |TimelineEventBlock|s need to be |
| 46 // reclaimed. | |
| 46 // | 47 // |
| 47 // Reclaiming open |TimelineEventBlock|s for an isolate: | 48 // Reclaiming open |TimelineEventBlock|s from threads: |
| 48 // | 49 // |
| 49 // Cached |TimelineEventBlock|s can be in two places: | 50 // Each |Thread| can have one |TimelineEventBlock| cached in it. |
| 50 // 1) In a |Thread| (Thread currently in an |Isolate|) | |
| 51 // 2) In a |Thread::State| (Thread not currently in an |Isolate|). | |
| 52 // | 51 // |
| 53 // As a |Thread| enters and exits an |Isolate|, a |TimelineEventBlock| | 52 // To reclaim blocks, we iterate over all threads and remove the cached |
| 54 // will move between (1) and (2). | 53 // |TimelineEventBlock| from each thread. This is safe because we hold the |
| 55 // | 54 // |Thread|'s |timeline_block_lock_| meaning the block can't be being modified. |
| 56 // The first case occurs for |Thread|s that are currently running inside an | |
| 57 // isolate. The second case occurs for |Thread|s that are not currently | |
| 58 // running inside an isolate. | |
| 59 // | |
| 60 // To reclaim the first case, we take the |Thread|'s |timeline_block_lock_| | |
| 61 // and reclaim the cached block. | |
| 62 // | |
| 63 // To reclaim the second case, we can take the |ThreadRegistry| lock and | |
| 64 // reclaim these blocks. | |
| 65 // | |
| 66 // |Timeline::ReclaimIsolateBlocks| and |Timeline::ReclaimAllBlocks| are | |
| 67 // the two utility methods used to reclaim blocks before reporting. | |
| 68 // | 55 // |
| 69 // Locking notes: | 56 // Locking notes: |
| 70 // The following locks are used by the timeline system: | 57 // The following locks are used by the timeline system: |
| 71 // - |TimelineEventRecorder::lock_| This lock is held whenever a | 58 // - |TimelineEventRecorder::lock_| This lock is held whenever a |
| 72 // |TimelineEventBlock| is being requested or reclaimed. | 59 // |TimelineEventBlock| is being requested or reclaimed. |
| 73 // - |Thread::timeline_block_lock_| This lock is held whenever a |Thread|'s | 60 // - |Thread::timeline_block_lock_| This lock is held whenever a |Thread|'s |
| 74 // cached block is being operated on. | 61 // cached block is being operated on. |
| 75 // - |ThreadRegistry::monitor_| This lock protects the cached block for | 62 // - |Thread::thread_list_lock_| This lock is held when iterating over |
| 76 // unscheduled threads of an isolate. | 63 // |Thread|s. |
| 77 // - |Isolate::isolates_list_monitor_| This lock protects the list of | |
| 78 // isolates in the system. | |
| 79 // | 64 // |
| 80 // Locks must always be taken in the following order: | 65 // Locks must always be taken in the following order: |
| 81 // |Isolate::isolates_list_monitor_| | 66 // |Thread::thread_list_lock_| |
| 82 // |ThreadRegistry::monitor_| | |
| 83 // |Thread::timeline_block_lock_| | 67 // |Thread::timeline_block_lock_| |
| 84 // |TimelineEventRecorder::lock_| | 68 // |TimelineEventRecorder::lock_| |
| 85 // | 69 // |
| 86 | 70 |
| 87 void Timeline::InitOnce() { | 71 void Timeline::InitOnce() { |
| 88 ASSERT(recorder_ == NULL); | 72 ASSERT(recorder_ == NULL); |
| 89 // Default to ring recorder being enabled. | 73 // Default to ring recorder being enabled. |
| 90 const bool use_ring_recorder = true; | 74 const bool use_ring_recorder = true; |
| 91 // Some flags require that we use the endless recorder. | 75 // Some flags require that we use the endless recorder. |
| 92 const bool use_endless_recorder = | 76 const bool use_endless_recorder = |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 128 return (FLAG_timeline_dir != NULL) || FLAG_timing; | 112 return (FLAG_timeline_dir != NULL) || FLAG_timing; |
| 129 } | 113 } |
| 130 | 114 |
| 131 | 115 |
| 132 TimelineStream* Timeline::GetVMStream() { | 116 TimelineStream* Timeline::GetVMStream() { |
| 133 ASSERT(vm_stream_ != NULL); | 117 ASSERT(vm_stream_ != NULL); |
| 134 return vm_stream_; | 118 return vm_stream_; |
| 135 } | 119 } |
| 136 | 120 |
| 137 | 121 |
| 138 void Timeline::ReclaimIsolateBlocks() { | 122 void Timeline::ReclaimCachedBlocksFromThreads() { |
| 139 ReclaimBlocksForIsolate(Isolate::Current()); | 123 TimelineEventRecorder* recorder = Timeline::recorder(); |
| 124 if (recorder == NULL) { | |
| 125 return; | |
| 126 } | |
| 127 | |
| 128 // Iterate over threads. | |
| 129 ThreadIterator it; | |
| 130 while (it.HasNext()) { | |
| 131 Thread* thread = it.Next(); | |
| 132 MutexLocker ml(thread->timeline_block_lock()); | |
| 133 // Grab block and clear it. | |
| 134 TimelineEventBlock* block = thread->timeline_block(); | |
| 135 thread->set_timeline_block(NULL); | |
|
turnidge
2015/10/16 19:40:20
Should we release the timeline_block_lock before w
Cutch
2015/10/16 19:43:52
For now I'm keeping this consistent with the docum
| |
| 136 recorder->FinishBlock(block); | |
| 137 } | |
| 140 } | 138 } |
| 141 | 139 |
| 142 | 140 |
| 143 class ReclaimBlocksIsolateVisitor : public IsolateVisitor { | |
| 144 public: | |
| 145 ReclaimBlocksIsolateVisitor() {} | |
| 146 | |
| 147 virtual void VisitIsolate(Isolate* isolate) { | |
| 148 Timeline::ReclaimBlocksForIsolate(isolate); | |
| 149 } | |
| 150 | |
| 151 private: | |
| 152 }; | |
| 153 | |
| 154 | |
| 155 void Timeline::ReclaimAllBlocks() { | |
| 156 if (recorder() == NULL) { | |
| 157 return; | |
| 158 } | |
| 159 // Reclaim all blocks cached for all isolates. | |
| 160 ReclaimBlocksIsolateVisitor visitor; | |
| 161 Isolate::VisitIsolates(&visitor); | |
| 162 // Reclaim the global VM block. | |
| 163 recorder()->ReclaimGlobalBlock(); | |
| 164 } | |
| 165 | |
| 166 | |
| 167 void Timeline::ReclaimBlocksForIsolate(Isolate* isolate) { | |
| 168 if (recorder() == NULL) { | |
| 169 return; | |
| 170 } | |
| 171 ASSERT(isolate != NULL); | |
| 172 isolate->ReclaimTimelineBlocks(); | |
| 173 } | |
| 174 | |
| 175 | |
| 176 TimelineEventRecorder* Timeline::recorder_ = NULL; | 141 TimelineEventRecorder* Timeline::recorder_ = NULL; |
| 177 TimelineStream* Timeline::vm_stream_ = NULL; | 142 TimelineStream* Timeline::vm_stream_ = NULL; |
| 178 | 143 |
| 179 #define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default) \ | 144 #define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default) \ |
| 180 bool Timeline::stream_##name##_enabled_ = false; | 145 bool Timeline::stream_##name##_enabled_ = false; |
| 181 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DEFINE_FLAG) | 146 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DEFINE_FLAG) |
| 182 #undef ISOLATE_TIMELINE_STREAM_DEFINE_FLAG | 147 #undef ISOLATE_TIMELINE_STREAM_DEFINE_FLAG |
| 183 | 148 |
| 184 TimelineEvent::TimelineEvent() | 149 TimelineEvent::TimelineEvent() |
| 185 : timestamp0_(0), | 150 : timestamp0_(0), |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 649 | 614 |
| 650 void DartTimelineEvent::Init(Isolate* isolate, const char* event) { | 615 void DartTimelineEvent::Init(Isolate* isolate, const char* event) { |
| 651 ASSERT(isolate_ == NULL); | 616 ASSERT(isolate_ == NULL); |
| 652 ASSERT(event != NULL); | 617 ASSERT(event != NULL); |
| 653 isolate_ = isolate; | 618 isolate_ = isolate; |
| 654 event_as_json_ = strdup(event); | 619 event_as_json_ = strdup(event); |
| 655 } | 620 } |
| 656 | 621 |
| 657 | 622 |
| 658 TimelineEventRecorder::TimelineEventRecorder() | 623 TimelineEventRecorder::TimelineEventRecorder() |
| 659 : global_block_(NULL), | 624 : async_id_(0) { |
| 660 async_id_(0) { | |
| 661 } | 625 } |
| 662 | 626 |
| 663 | 627 |
| 664 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { | 628 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { |
| 665 } | 629 } |
| 666 | 630 |
| 667 | 631 |
| 668 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() { | 632 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() { |
| 669 // Grab the current thread. | 633 // Grab the current thread. |
| 670 Thread* thread = Thread::Current(); | 634 Thread* thread = Thread::Current(); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 689 } else if (thread_block == NULL) { | 653 } else if (thread_block == NULL) { |
| 690 MutexLocker ml(&lock_); | 654 MutexLocker ml(&lock_); |
| 691 // Thread has no block. Attempt to allocate one. | 655 // Thread has no block. Attempt to allocate one. |
| 692 thread_block = GetNewBlockLocked(thread->isolate()); | 656 thread_block = GetNewBlockLocked(thread->isolate()); |
| 693 thread->set_timeline_block(thread_block); | 657 thread->set_timeline_block(thread_block); |
| 694 } | 658 } |
| 695 if (thread_block != NULL) { | 659 if (thread_block != NULL) { |
| 696 // NOTE: We are exiting this function with the thread's block lock held. | 660 // NOTE: We are exiting this function with the thread's block lock held. |
| 697 ASSERT(!thread_block->IsFull()); | 661 ASSERT(!thread_block->IsFull()); |
| 698 TimelineEvent* event = thread_block->StartEvent(); | 662 TimelineEvent* event = thread_block->StartEvent(); |
| 699 if (event != NULL) { | |
| 700 event->set_global_block(false); | |
| 701 } | |
| 702 return event; | 663 return event; |
| 703 } | 664 } |
| 704 // Drop lock here as no event is being handed out. | 665 // Drop lock here as no event is being handed out. |
| 705 thread_block_lock->Unlock(); | 666 thread_block_lock->Unlock(); |
| 706 return NULL; | 667 return NULL; |
| 707 } | 668 } |
| 708 | 669 |
| 709 | 670 |
| 710 TimelineEvent* TimelineEventRecorder::GlobalBlockStartEvent() { | |
| 711 // Take recorder lock. This lock will be held until the call to | |
| 712 // |CompleteEvent| is made. | |
| 713 lock_.Lock(); | |
| 714 if (FLAG_trace_timeline) { | |
| 715 OS::Print("GlobalBlockStartEvent in block %p for thread %" Px "\n", | |
| 716 global_block_, OSThread::CurrentCurrentThreadIdAsIntPtr()); | |
| 717 } | |
| 718 if ((global_block_ != NULL) && global_block_->IsFull()) { | |
| 719 // Global block is full. | |
| 720 global_block_->Finish(); | |
| 721 global_block_ = NULL; | |
| 722 } | |
| 723 if (global_block_ == NULL) { | |
| 724 // Allocate a new block. | |
| 725 global_block_ = GetNewBlockLocked(NULL); | |
| 726 ASSERT(global_block_ != NULL); | |
| 727 } | |
| 728 if (global_block_ != NULL) { | |
| 729 // NOTE: We are exiting this function with the recorder's lock held. | |
| 730 ASSERT(!global_block_->IsFull()); | |
| 731 TimelineEvent* event = global_block_->StartEvent(); | |
| 732 if (event != NULL) { | |
| 733 event->set_global_block(true); | |
| 734 } | |
| 735 return event; | |
| 736 } | |
| 737 // Drop lock here as no event is being handed out. | |
| 738 lock_.Unlock(); | |
| 739 return NULL; | |
| 740 } | |
| 741 | |
| 742 | |
| 743 void TimelineEventRecorder::ThreadBlockCompleteEvent(TimelineEvent* event) { | 671 void TimelineEventRecorder::ThreadBlockCompleteEvent(TimelineEvent* event) { |
| 744 if (event == NULL) { | 672 if (event == NULL) { |
| 745 return; | 673 return; |
| 746 } | 674 } |
| 747 ASSERT(!event->global_block()); | |
| 748 // Grab the current thread. | 675 // Grab the current thread. |
| 749 Thread* thread = Thread::Current(); | 676 Thread* thread = Thread::Current(); |
| 750 ASSERT(thread != NULL); | 677 ASSERT(thread != NULL); |
| 751 ASSERT(thread->isolate() != NULL); | 678 // Unlock the thread's block lock. |
| 752 // This event came from the isolate's thread local block. Unlock the | |
| 753 // thread's block lock. | |
| 754 Mutex* thread_block_lock = thread->timeline_block_lock(); | 679 Mutex* thread_block_lock = thread->timeline_block_lock(); |
| 755 ASSERT(thread_block_lock != NULL); | 680 ASSERT(thread_block_lock != NULL); |
| 756 thread_block_lock->Unlock(); | 681 thread_block_lock->Unlock(); |
| 757 } | 682 } |
| 758 | 683 |
| 759 | 684 |
| 760 void TimelineEventRecorder::GlobalBlockCompleteEvent(TimelineEvent* event) { | |
| 761 if (event == NULL) { | |
| 762 return; | |
| 763 } | |
| 764 ASSERT(event->global_block()); | |
| 765 // This event came from the global block, unlock the recorder's lock now | |
| 766 // that the event is filled. | |
| 767 lock_.Unlock(); | |
| 768 } | |
| 769 | |
| 770 | |
| 771 // Trims the ']' character. | 685 // Trims the ']' character. |
| 772 static void TrimOutput(char* output, | 686 static void TrimOutput(char* output, |
| 773 intptr_t* output_length) { | 687 intptr_t* output_length) { |
| 774 ASSERT(output != NULL); | 688 ASSERT(output != NULL); |
| 775 ASSERT(output_length != NULL); | 689 ASSERT(output_length != NULL); |
| 776 ASSERT(*output_length >= 2); | 690 ASSERT(*output_length >= 2); |
| 777 // We expect the first character to be the opening of an array. | 691 // We expect the first character to be the opening of an array. |
| 778 ASSERT(output[0] == '['); | 692 ASSERT(output[0] == '['); |
| 779 // We expect the last character to be the closing of an array. | 693 // We expect the last character to be the closing of an array. |
| 780 ASSERT(output[*output_length - 1] == ']'); | 694 ASSERT(output[*output_length - 1] == ']'); |
| 781 // Skip the ]. | 695 // Skip the ]. |
| 782 *output_length -= 1; | 696 *output_length -= 1; |
| 783 } | 697 } |
| 784 | 698 |
| 785 | 699 |
| 786 void TimelineEventRecorder::WriteTo(const char* directory) { | 700 void TimelineEventRecorder::WriteTo(const char* directory) { |
| 787 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | 701 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
| 788 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | 702 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
| 789 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | 703 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
| 790 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { | 704 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { |
| 791 return; | 705 return; |
| 792 } | 706 } |
| 793 Thread* T = Thread::Current(); | 707 Thread* T = Thread::Current(); |
| 794 StackZone zone(T); | 708 StackZone zone(T); |
| 795 | 709 |
| 796 Timeline::ReclaimAllBlocks(); | 710 Timeline::ReclaimCachedBlocksFromThreads(); |
| 797 | 711 |
| 798 intptr_t pid = OS::ProcessId(); | 712 intptr_t pid = OS::ProcessId(); |
| 799 char* filename = OS::SCreate(NULL, | 713 char* filename = OS::SCreate(NULL, |
| 800 "%s/dart-timeline-%" Pd ".json", directory, pid); | 714 "%s/dart-timeline-%" Pd ".json", directory, pid); |
| 801 void* file = (*file_open)(filename, true); | 715 void* file = (*file_open)(filename, true); |
| 802 if (file == NULL) { | 716 if (file == NULL) { |
| 803 OS::Print("Failed to write timeline file: %s\n", filename); | 717 OS::Print("Failed to write timeline file: %s\n", filename); |
| 804 free(filename); | 718 free(filename); |
| 805 return; | 719 return; |
| 806 } | 720 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 838 | 752 |
| 839 // Write out the ']' character. | 753 // Write out the ']' character. |
| 840 const char* array_close = "]"; | 754 const char* array_close = "]"; |
| 841 (*file_write)(array_close, 1, file); | 755 (*file_write)(array_close, 1, file); |
| 842 (*file_close)(file); | 756 (*file_close)(file); |
| 843 | 757 |
| 844 return; | 758 return; |
| 845 } | 759 } |
| 846 | 760 |
| 847 | 761 |
| 848 void TimelineEventRecorder::ReclaimGlobalBlock() { | |
| 849 MutexLocker ml(&lock_); | |
| 850 if (global_block_ != NULL) { | |
| 851 global_block_->Finish(); | |
| 852 global_block_ = NULL; | |
| 853 } | |
| 854 } | |
| 855 | |
| 856 | |
| 857 int64_t TimelineEventRecorder::GetNextAsyncId() { | 762 int64_t TimelineEventRecorder::GetNextAsyncId() { |
| 858 // TODO(johnmccutchan): Gracefully handle wrap around. | 763 // TODO(johnmccutchan): Gracefully handle wrap around. |
| 859 uint32_t next = static_cast<uint32_t>( | 764 uint32_t next = static_cast<uint32_t>( |
| 860 AtomicOperations::FetchAndIncrement(&async_id_)); | 765 AtomicOperations::FetchAndIncrement(&async_id_)); |
| 861 return static_cast<int64_t>(next); | 766 return static_cast<int64_t>(next); |
| 862 } | 767 } |
| 863 | 768 |
| 864 | 769 |
| 865 void TimelineEventRecorder::FinishBlock(TimelineEventBlock* block) { | 770 void TimelineEventRecorder::FinishBlock(TimelineEventBlock* block) { |
| 866 if (block == NULL) { | 771 if (block == NULL) { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1031 } | 936 } |
| 1032 } | 937 } |
| 1033 return earliest_index; | 938 return earliest_index; |
| 1034 } | 939 } |
| 1035 | 940 |
| 1036 | 941 |
| 1037 TimelineEvent* TimelineEventRingRecorder::StartEvent() { | 942 TimelineEvent* TimelineEventRingRecorder::StartEvent() { |
| 1038 // Grab the current thread. | 943 // Grab the current thread. |
| 1039 Thread* thread = Thread::Current(); | 944 Thread* thread = Thread::Current(); |
| 1040 ASSERT(thread != NULL); | 945 ASSERT(thread != NULL); |
| 1041 if (thread->isolate() == NULL) { | |
| 1042 // Non-isolate thread case. This should be infrequent. | |
| 1043 return GlobalBlockStartEvent(); | |
| 1044 } | |
| 1045 return ThreadBlockStartEvent(); | 946 return ThreadBlockStartEvent(); |
| 1046 } | 947 } |
| 1047 | 948 |
| 1048 | 949 |
| 1049 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) { | 950 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) { |
| 1050 if (event == NULL) { | 951 if (event == NULL) { |
| 1051 return; | 952 return; |
| 1052 } | 953 } |
| 1053 if (event->global_block()) { | 954 ThreadBlockCompleteEvent(event); |
| 1054 GlobalBlockCompleteEvent(event); | |
| 1055 } else { | |
| 1056 ThreadBlockCompleteEvent(event); | |
| 1057 } | |
| 1058 } | 955 } |
| 1059 | 956 |
| 1060 | 957 |
| 1061 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() { | 958 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() { |
| 1062 } | 959 } |
| 1063 | 960 |
| 1064 | 961 |
| 1065 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() { | 962 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() { |
| 1066 } | 963 } |
| 1067 | 964 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1172 | 1069 |
| 1173 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() { | 1070 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() { |
| 1174 return head_; | 1071 return head_; |
| 1175 } | 1072 } |
| 1176 | 1073 |
| 1177 | 1074 |
| 1178 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { | 1075 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { |
| 1179 // Grab the current thread. | 1076 // Grab the current thread. |
| 1180 Thread* thread = Thread::Current(); | 1077 Thread* thread = Thread::Current(); |
| 1181 ASSERT(thread != NULL); | 1078 ASSERT(thread != NULL); |
| 1182 if (thread->isolate() == NULL) { | |
| 1183 // Non-isolate thread case. This should be infrequent. | |
| 1184 return GlobalBlockStartEvent(); | |
| 1185 } | |
| 1186 return ThreadBlockStartEvent(); | 1079 return ThreadBlockStartEvent(); |
| 1187 } | 1080 } |
| 1188 | 1081 |
| 1189 | 1082 |
| 1190 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { | 1083 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { |
| 1191 if (event == NULL) { | 1084 if (event == NULL) { |
| 1192 return; | 1085 return; |
| 1193 } | 1086 } |
| 1194 if (event->global_block()) { | 1087 ThreadBlockCompleteEvent(event); |
| 1195 GlobalBlockCompleteEvent(event); | |
| 1196 } else { | |
| 1197 ThreadBlockCompleteEvent(event); | |
| 1198 } | |
| 1199 } | 1088 } |
| 1200 | 1089 |
| 1201 | 1090 |
| 1202 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked( | 1091 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked( |
| 1203 Isolate* isolate) { | 1092 Isolate* isolate) { |
| 1204 TimelineEventBlock* block = new TimelineEventBlock(block_index_++); | 1093 TimelineEventBlock* block = new TimelineEventBlock(block_index_++); |
| 1205 block->set_next(head_); | 1094 block->set_next(head_); |
| 1206 block->Open(isolate); | 1095 block->Open(isolate); |
| 1207 head_ = block; | 1096 head_ = block; |
| 1208 if (FLAG_trace_timeline) { | 1097 if (FLAG_trace_timeline) { |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1467 // If an isolate was specified, skip events from other isolates. | 1356 // If an isolate was specified, skip events from other isolates. |
| 1468 continue; | 1357 continue; |
| 1469 } | 1358 } |
| 1470 ASSERT(event->event_as_json() != NULL); | 1359 ASSERT(event->event_as_json() != NULL); |
| 1471 result = zone->ConcatStrings(result, event->event_as_json()); | 1360 result = zone->ConcatStrings(result, event->event_as_json()); |
| 1472 } | 1361 } |
| 1473 return result; | 1362 return result; |
| 1474 } | 1363 } |
| 1475 | 1364 |
| 1476 } // namespace dart | 1365 } // namespace dart |
| OLD | NEW |