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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 #undef ISOLATE_TIMELINE_STREAM_DEFINE_FLAG | 150 #undef ISOLATE_TIMELINE_STREAM_DEFINE_FLAG |
151 | 151 |
152 TimelineEvent::TimelineEvent() | 152 TimelineEvent::TimelineEvent() |
153 : timestamp0_(0), | 153 : timestamp0_(0), |
154 timestamp1_(0), | 154 timestamp1_(0), |
155 arguments_(NULL), | 155 arguments_(NULL), |
156 arguments_length_(0), | 156 arguments_length_(0), |
157 state_(0), | 157 state_(0), |
158 label_(NULL), | 158 label_(NULL), |
159 category_(""), | 159 category_(""), |
160 thread_(OSThread::kInvalidThreadId) { | 160 thread_(OSThread::kInvalidThreadId), |
| 161 isolate_id_(ILLEGAL_PORT) { |
161 } | 162 } |
162 | 163 |
163 | 164 |
164 TimelineEvent::~TimelineEvent() { | 165 TimelineEvent::~TimelineEvent() { |
165 Reset(); | 166 Reset(); |
166 } | 167 } |
167 | 168 |
168 | 169 |
169 void TimelineEvent::Reset() { | 170 void TimelineEvent::Reset() { |
170 set_event_type(kNone); | 171 set_event_type(kNone); |
171 thread_ = OSThread::kInvalidThreadId; | 172 thread_ = OSThread::kInvalidThreadId; |
172 isolate_ = NULL; | 173 isolate_id_ = ILLEGAL_PORT; |
173 category_ = ""; | 174 category_ = ""; |
174 label_ = NULL; | 175 label_ = NULL; |
175 FreeArguments(); | 176 FreeArguments(); |
176 } | 177 } |
177 | 178 |
178 | 179 |
179 void TimelineEvent::AsyncBegin(const char* label, int64_t async_id) { | 180 void TimelineEvent::AsyncBegin(const char* label, int64_t async_id) { |
180 Init(kAsyncBegin, label); | 181 Init(kAsyncBegin, label); |
181 timestamp0_ = OS::GetCurrentTraceMicros(); | 182 timestamp0_ = OS::GetCurrentTraceMicros(); |
182 // Overload timestamp1_ with the async_id. | 183 // Overload timestamp1_ with the async_id. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 } | 236 } |
236 | 237 |
237 | 238 |
238 void TimelineEvent::End(const char* label, | 239 void TimelineEvent::End(const char* label, |
239 int64_t micros) { | 240 int64_t micros) { |
240 Init(kEnd, label); | 241 Init(kEnd, label); |
241 timestamp0_ = micros; | 242 timestamp0_ = micros; |
242 } | 243 } |
243 | 244 |
244 | 245 |
| 246 void TimelineEvent::SerializedJSON(const char* json) { |
| 247 Init(kSerializedJSON, "Dart"); |
| 248 SetNumArguments(1); |
| 249 CopyArgument(0, "Dart", json); |
| 250 } |
| 251 |
| 252 |
245 void TimelineEvent::SetNumArguments(intptr_t length) { | 253 void TimelineEvent::SetNumArguments(intptr_t length) { |
246 // Cannot call this twice. | 254 // Cannot call this twice. |
247 ASSERT(arguments_ == NULL); | 255 ASSERT(arguments_ == NULL); |
248 ASSERT(arguments_length_ == 0); | 256 ASSERT(arguments_length_ == 0); |
249 if (length == 0) { | 257 if (length == 0) { |
250 return; | 258 return; |
251 } | 259 } |
252 arguments_length_ = length; | 260 arguments_length_ = length; |
253 arguments_ = reinterpret_cast<TimelineEventArgument*>( | 261 arguments_ = reinterpret_cast<TimelineEventArgument*>( |
254 calloc(sizeof(TimelineEventArgument), length)); | 262 calloc(sizeof(TimelineEventArgument), length)); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 } | 334 } |
327 | 335 |
328 | 336 |
329 void TimelineEvent::Init(EventType event_type, | 337 void TimelineEvent::Init(EventType event_type, |
330 const char* label) { | 338 const char* label) { |
331 ASSERT(label != NULL); | 339 ASSERT(label != NULL); |
332 set_event_type(event_type); | 340 set_event_type(event_type); |
333 timestamp0_ = 0; | 341 timestamp0_ = 0; |
334 timestamp1_ = 0; | 342 timestamp1_ = 0; |
335 thread_ = OSThread::GetCurrentThreadTraceId(); | 343 thread_ = OSThread::GetCurrentThreadTraceId(); |
336 isolate_ = Isolate::Current(); | 344 Isolate* isolate = Isolate::Current(); |
| 345 if (isolate != NULL) { |
| 346 isolate_id_ = isolate->main_port(); |
| 347 } else { |
| 348 isolate_id_ = ILLEGAL_PORT; |
| 349 } |
337 label_ = label; | 350 label_ = label; |
338 FreeArguments(); | 351 FreeArguments(); |
339 } | 352 } |
340 | 353 |
341 | 354 |
| 355 const char* TimelineEvent::GetSerializedJSON() const { |
| 356 ASSERT(event_type() == kSerializedJSON); |
| 357 ASSERT(arguments_length_ == 1); |
| 358 ASSERT(arguments_ != NULL); |
| 359 return arguments_[0].value; |
| 360 } |
| 361 |
| 362 |
342 void TimelineEvent::PrintJSON(JSONStream* stream) const { | 363 void TimelineEvent::PrintJSON(JSONStream* stream) const { |
| 364 if (event_type() == kSerializedJSON) { |
| 365 // Event has already been serialized into JSON- just append the |
| 366 // raw data. |
| 367 stream->AppendSerializedObject(GetSerializedJSON()); |
| 368 return; |
| 369 } |
343 JSONObject obj(stream); | 370 JSONObject obj(stream); |
344 int64_t pid = OS::ProcessId(); | 371 int64_t pid = OS::ProcessId(); |
345 int64_t tid = OSThread::ThreadIdToIntPtr(thread_); | 372 int64_t tid = OSThread::ThreadIdToIntPtr(thread_); |
346 obj.AddProperty("name", label_); | 373 obj.AddProperty("name", label_); |
347 obj.AddProperty("cat", category_); | 374 obj.AddProperty("cat", category_); |
348 obj.AddProperty64("tid", tid); | 375 obj.AddProperty64("tid", tid); |
349 obj.AddProperty64("pid", pid); | 376 obj.AddProperty64("pid", pid); |
350 obj.AddPropertyTimeMicros("ts", TimeOrigin()); | 377 obj.AddPropertyTimeMicros("ts", TimeOrigin()); |
351 | 378 |
352 switch (event_type()) { | 379 switch (event_type()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 break; | 412 break; |
386 default: | 413 default: |
387 UNIMPLEMENTED(); | 414 UNIMPLEMENTED(); |
388 } | 415 } |
389 { | 416 { |
390 JSONObject args(&obj, "args"); | 417 JSONObject args(&obj, "args"); |
391 for (intptr_t i = 0; i < arguments_length_; i++) { | 418 for (intptr_t i = 0; i < arguments_length_; i++) { |
392 const TimelineEventArgument& arg = arguments_[i]; | 419 const TimelineEventArgument& arg = arguments_[i]; |
393 args.AddProperty(arg.name, arg.value); | 420 args.AddProperty(arg.name, arg.value); |
394 } | 421 } |
| 422 if (isolate_id_ != ILLEGAL_PORT) { |
| 423 // If we have one, append the isolate id. |
| 424 args.AddProperty("isolateNumber", isolate_id_); |
| 425 } |
395 } | 426 } |
396 } | 427 } |
397 | 428 |
398 | 429 |
399 int64_t TimelineEvent::TimeOrigin() const { | 430 int64_t TimelineEvent::TimeOrigin() const { |
400 return timestamp0_; | 431 return timestamp0_; |
401 } | 432 } |
402 | 433 |
403 | 434 |
404 int64_t TimelineEvent::AsyncId() const { | 435 int64_t TimelineEvent::AsyncId() const { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 | 612 |
582 | 613 |
583 TimelineEventFilter::TimelineEventFilter() { | 614 TimelineEventFilter::TimelineEventFilter() { |
584 } | 615 } |
585 | 616 |
586 | 617 |
587 TimelineEventFilter::~TimelineEventFilter() { | 618 TimelineEventFilter::~TimelineEventFilter() { |
588 } | 619 } |
589 | 620 |
590 | 621 |
591 IsolateTimelineEventFilter::IsolateTimelineEventFilter(Isolate* isolate) | 622 IsolateTimelineEventFilter::IsolateTimelineEventFilter(Dart_Port isolate_id) |
592 : isolate_(isolate) { | 623 : isolate_id_(isolate_id) { |
593 } | 624 } |
594 | 625 |
595 | 626 |
596 DartTimelineEvent::DartTimelineEvent() | |
597 : isolate_(NULL), | |
598 event_as_json_(NULL) { | |
599 } | |
600 | |
601 | |
602 DartTimelineEvent::~DartTimelineEvent() { | |
603 Clear(); | |
604 } | |
605 | |
606 | |
607 void DartTimelineEvent::Clear() { | |
608 if (isolate_ != NULL) { | |
609 isolate_ = NULL; | |
610 } | |
611 if (event_as_json_ != NULL) { | |
612 free(event_as_json_); | |
613 event_as_json_ = NULL; | |
614 } | |
615 } | |
616 | |
617 | |
618 void DartTimelineEvent::Init(Isolate* isolate, const char* event) { | |
619 ASSERT(isolate_ == NULL); | |
620 ASSERT(event != NULL); | |
621 isolate_ = isolate; | |
622 event_as_json_ = strdup(event); | |
623 } | |
624 | |
625 | |
626 TimelineEventRecorder::TimelineEventRecorder() | 627 TimelineEventRecorder::TimelineEventRecorder() |
627 : async_id_(0) { | 628 : async_id_(0) { |
628 } | 629 } |
629 | 630 |
630 | 631 |
631 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { | 632 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { |
632 } | 633 } |
633 | 634 |
634 | 635 |
635 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() { | 636 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() { |
636 // Grab the current thread. | 637 // Grab the current thread. |
637 Thread* thread = Thread::Current(); | 638 Thread* thread = Thread::Current(); |
638 ASSERT(thread != NULL); | 639 ASSERT(thread != NULL); |
639 ASSERT(thread->isolate() != NULL); | |
640 Mutex* thread_block_lock = thread->timeline_block_lock(); | 640 Mutex* thread_block_lock = thread->timeline_block_lock(); |
641 ASSERT(thread_block_lock != NULL); | 641 ASSERT(thread_block_lock != NULL); |
642 // We are accessing the thread's timeline block- so take the lock here. | 642 // We are accessing the thread's timeline block- so take the lock here. |
643 // This lock will be held until the call to |CompleteEvent| is made. | 643 // This lock will be held until the call to |CompleteEvent| is made. |
644 thread_block_lock->Lock(); | 644 thread_block_lock->Lock(); |
645 | 645 |
646 TimelineEventBlock* thread_block = thread->timeline_block(); | 646 TimelineEventBlock* thread_block = thread->timeline_block(); |
647 | 647 |
648 if ((thread_block != NULL) && thread_block->IsFull()) { | 648 if ((thread_block != NULL) && thread_block->IsFull()) { |
649 MutexLocker ml(&lock_); | 649 MutexLocker ml(&lock_); |
650 // Thread has a block and it is full: | 650 // Thread has a block and it is full: |
651 // 1) Mark it as finished. | 651 // 1) Mark it as finished. |
652 thread_block->Finish(); | 652 thread_block->Finish(); |
653 // 2) Allocate a new block. | 653 // 2) Allocate a new block. |
654 thread_block = GetNewBlockLocked(thread->isolate()); | 654 thread_block = GetNewBlockLocked(); |
655 thread->set_timeline_block(thread_block); | 655 thread->set_timeline_block(thread_block); |
656 } else if (thread_block == NULL) { | 656 } else if (thread_block == NULL) { |
657 MutexLocker ml(&lock_); | 657 MutexLocker ml(&lock_); |
658 // Thread has no block. Attempt to allocate one. | 658 // Thread has no block. Attempt to allocate one. |
659 thread_block = GetNewBlockLocked(thread->isolate()); | 659 thread_block = GetNewBlockLocked(); |
660 thread->set_timeline_block(thread_block); | 660 thread->set_timeline_block(thread_block); |
661 } | 661 } |
662 if (thread_block != NULL) { | 662 if (thread_block != NULL) { |
663 // NOTE: We are exiting this function with the thread's block lock held. | 663 // NOTE: We are exiting this function with the thread's block lock held. |
664 ASSERT(!thread_block->IsFull()); | 664 ASSERT(!thread_block->IsFull()); |
665 TimelineEvent* event = thread_block->StartEvent(); | 665 TimelineEvent* event = thread_block->StartEvent(); |
666 return event; | 666 return event; |
667 } | 667 } |
668 // Drop lock here as no event is being handed out. | 668 // Drop lock here as no event is being handed out. |
669 thread_block_lock->Unlock(); | 669 thread_block_lock->Unlock(); |
670 return NULL; | 670 return NULL; |
671 } | 671 } |
672 | 672 |
673 | 673 |
674 void TimelineEventRecorder::ThreadBlockCompleteEvent(TimelineEvent* event) { | 674 void TimelineEventRecorder::ThreadBlockCompleteEvent(TimelineEvent* event) { |
675 if (event == NULL) { | 675 if (event == NULL) { |
676 return; | 676 return; |
677 } | 677 } |
678 // Grab the current thread. | 678 // Grab the current thread. |
679 Thread* thread = Thread::Current(); | 679 Thread* thread = Thread::Current(); |
680 ASSERT(thread != NULL); | 680 ASSERT(thread != NULL); |
681 // Unlock the thread's block lock. | 681 // Unlock the thread's block lock. |
682 Mutex* thread_block_lock = thread->timeline_block_lock(); | 682 Mutex* thread_block_lock = thread->timeline_block_lock(); |
683 ASSERT(thread_block_lock != NULL); | 683 ASSERT(thread_block_lock != NULL); |
684 thread_block_lock->Unlock(); | 684 thread_block_lock->Unlock(); |
685 } | 685 } |
686 | 686 |
687 | 687 |
688 // Trims the ']' character. | |
689 static void TrimOutput(char* output, | |
690 intptr_t* output_length) { | |
691 ASSERT(output != NULL); | |
692 ASSERT(output_length != NULL); | |
693 ASSERT(*output_length >= 2); | |
694 // We expect the first character to be the opening of an array. | |
695 ASSERT(output[0] == '['); | |
696 // We expect the last character to be the closing of an array. | |
697 ASSERT(output[*output_length - 1] == ']'); | |
698 // Skip the ]. | |
699 *output_length -= 1; | |
700 } | |
701 | |
702 | |
703 void TimelineEventRecorder::WriteTo(const char* directory) { | 688 void TimelineEventRecorder::WriteTo(const char* directory) { |
704 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | 689 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
705 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | 690 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
706 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | 691 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
707 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { | 692 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { |
708 return; | 693 return; |
709 } | 694 } |
710 Thread* T = Thread::Current(); | 695 Thread* T = Thread::Current(); |
711 StackZone zone(T); | 696 StackZone zone(T); |
712 | 697 |
(...skipping 10 matching lines...) Expand all Loading... |
723 } | 708 } |
724 free(filename); | 709 free(filename); |
725 | 710 |
726 JSONStream js; | 711 JSONStream js; |
727 TimelineEventFilter filter; | 712 TimelineEventFilter filter; |
728 PrintTraceEvent(&js, &filter); | 713 PrintTraceEvent(&js, &filter); |
729 // Steal output from JSONStream. | 714 // Steal output from JSONStream. |
730 char* output = NULL; | 715 char* output = NULL; |
731 intptr_t output_length = 0; | 716 intptr_t output_length = 0; |
732 js.Steal(const_cast<const char**>(&output), &output_length); | 717 js.Steal(const_cast<const char**>(&output), &output_length); |
733 TrimOutput(output, &output_length); | |
734 ASSERT(output_length >= 1); | |
735 (*file_write)(output, output_length, file); | 718 (*file_write)(output, output_length, file); |
736 // Free the stolen output. | 719 // Free the stolen output. |
737 free(output); | 720 free(output); |
738 | |
739 const char* dart_events = | |
740 DartTimelineEventIterator::PrintTraceEvents(this, | |
741 zone.GetZone(), | |
742 NULL); | |
743 | |
744 // If we wrote out vm events and have dart events, write out the comma. | |
745 if ((output_length > 1) && (dart_events != NULL)) { | |
746 // Write out the ',' character. | |
747 const char* comma = ","; | |
748 (*file_write)(comma, 1, file); | |
749 } | |
750 | |
751 // Write out the Dart events. | |
752 if (dart_events != NULL) { | |
753 (*file_write)(dart_events, strlen(dart_events), file); | |
754 } | |
755 | |
756 // Write out the ']' character. | |
757 const char* array_close = "]"; | |
758 (*file_write)(array_close, 1, file); | |
759 (*file_close)(file); | 721 (*file_close)(file); |
760 | 722 |
761 return; | 723 return; |
762 } | 724 } |
763 | 725 |
764 | 726 |
765 int64_t TimelineEventRecorder::GetNextAsyncId() { | 727 int64_t TimelineEventRecorder::GetNextAsyncId() { |
766 // TODO(johnmccutchan): Gracefully handle wrap around. | 728 // TODO(johnmccutchan): Gracefully handle wrap around. |
767 uint32_t next = static_cast<uint32_t>( | 729 uint32_t next = static_cast<uint32_t>( |
768 AtomicOperations::FetchAndIncrement(&async_id_)); | 730 AtomicOperations::FetchAndIncrement(&async_id_)); |
769 return static_cast<int64_t>(next); | 731 return static_cast<int64_t>(next); |
770 } | 732 } |
771 | 733 |
772 | 734 |
773 void TimelineEventRecorder::FinishBlock(TimelineEventBlock* block) { | 735 void TimelineEventRecorder::FinishBlock(TimelineEventBlock* block) { |
774 if (block == NULL) { | 736 if (block == NULL) { |
775 return; | 737 return; |
776 } | 738 } |
777 MutexLocker ml(&lock_); | 739 MutexLocker ml(&lock_); |
778 block->Finish(); | 740 block->Finish(); |
779 } | 741 } |
780 | 742 |
781 | 743 |
782 TimelineEventBlock* TimelineEventRecorder::GetNewBlock() { | 744 TimelineEventBlock* TimelineEventRecorder::GetNewBlock() { |
783 MutexLocker ml(&lock_); | 745 MutexLocker ml(&lock_); |
784 return GetNewBlockLocked(Isolate::Current()); | 746 return GetNewBlockLocked(); |
785 } | 747 } |
786 | 748 |
787 | 749 |
788 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) | 750 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) |
789 : blocks_(NULL), | 751 : blocks_(NULL), |
790 capacity_(capacity), | 752 capacity_(capacity), |
791 num_blocks_(0), | 753 num_blocks_(0), |
792 block_cursor_(0), | 754 block_cursor_(0) { |
793 dart_events_(NULL), | |
794 dart_events_capacity_(capacity), | |
795 dart_events_cursor_(0) { | |
796 // Capacity must be a multiple of TimelineEventBlock::kBlockSize | 755 // Capacity must be a multiple of TimelineEventBlock::kBlockSize |
797 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0); | 756 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0); |
798 // Allocate blocks array. | 757 // Allocate blocks array. |
799 num_blocks_ = capacity / TimelineEventBlock::kBlockSize; | 758 num_blocks_ = capacity / TimelineEventBlock::kBlockSize; |
800 blocks_ = | 759 blocks_ = |
801 reinterpret_cast<TimelineEventBlock**>( | 760 reinterpret_cast<TimelineEventBlock**>( |
802 calloc(num_blocks_, sizeof(TimelineEventBlock*))); | 761 calloc(num_blocks_, sizeof(TimelineEventBlock*))); |
803 // Allocate each block. | 762 // Allocate each block. |
804 for (intptr_t i = 0; i < num_blocks_; i++) { | 763 for (intptr_t i = 0; i < num_blocks_; i++) { |
805 blocks_[i] = new TimelineEventBlock(i); | 764 blocks_[i] = new TimelineEventBlock(i); |
806 } | 765 } |
807 // Chain blocks together. | 766 // Chain blocks together. |
808 for (intptr_t i = 0; i < num_blocks_ - 1; i++) { | 767 for (intptr_t i = 0; i < num_blocks_ - 1; i++) { |
809 blocks_[i]->set_next(blocks_[i + 1]); | 768 blocks_[i]->set_next(blocks_[i + 1]); |
810 } | 769 } |
811 // Pre-allocate DartTimelineEvents. | |
812 dart_events_ = | |
813 reinterpret_cast<DartTimelineEvent**>( | |
814 calloc(dart_events_capacity_, sizeof(DartTimelineEvent*))); | |
815 for (intptr_t i = 0; i < dart_events_capacity_; i++) { | |
816 dart_events_[i] = new DartTimelineEvent(); | |
817 } | |
818 } | 770 } |
819 | 771 |
820 | 772 |
821 TimelineEventRingRecorder::~TimelineEventRingRecorder() { | 773 TimelineEventRingRecorder::~TimelineEventRingRecorder() { |
822 // Delete all blocks. | 774 // Delete all blocks. |
823 for (intptr_t i = 0; i < num_blocks_; i++) { | 775 for (intptr_t i = 0; i < num_blocks_; i++) { |
824 TimelineEventBlock* block = blocks_[i]; | 776 TimelineEventBlock* block = blocks_[i]; |
825 delete block; | 777 delete block; |
826 } | 778 } |
827 free(blocks_); | 779 free(blocks_); |
828 // Delete all DartTimelineEvents. | |
829 for (intptr_t i = 0; i < dart_events_capacity_; i++) { | |
830 DartTimelineEvent* event = dart_events_[i]; | |
831 delete event; | |
832 } | |
833 free(dart_events_); | |
834 } | 780 } |
835 | 781 |
836 | 782 |
837 void TimelineEventRingRecorder::PrintJSONEvents( | 783 void TimelineEventRingRecorder::PrintJSONEvents( |
838 JSONArray* events, | 784 JSONArray* events, |
839 TimelineEventFilter* filter) const { | 785 TimelineEventFilter* filter) const { |
840 intptr_t block_offset = FindOldestBlockIndex(); | 786 intptr_t block_offset = FindOldestBlockIndex(); |
841 if (block_offset == -1) { | 787 if (block_offset == -1) { |
842 // All blocks are empty. | 788 // All blocks are empty. |
843 return; | 789 return; |
(...skipping 20 matching lines...) Expand all Loading... |
864 JSONObject topLevel(js); | 810 JSONObject topLevel(js); |
865 topLevel.AddProperty("type", "_Timeline"); | 811 topLevel.AddProperty("type", "_Timeline"); |
866 { | 812 { |
867 JSONArray events(&topLevel, "traceEvents"); | 813 JSONArray events(&topLevel, "traceEvents"); |
868 PrintJSONMeta(&events); | 814 PrintJSONMeta(&events); |
869 PrintJSONEvents(&events, filter); | 815 PrintJSONEvents(&events, filter); |
870 } | 816 } |
871 } | 817 } |
872 | 818 |
873 | 819 |
874 void TimelineEventRingRecorder::AppendDartEvent(Isolate* isolate, | |
875 const char* event) { | |
876 MutexLocker ml(&lock_); | |
877 // TODO(johnmccutchan): If locking becomes an issue, use the Isolate to store | |
878 // the events. | |
879 if (dart_events_cursor_ == dart_events_capacity_) { | |
880 dart_events_cursor_ = 0; | |
881 } | |
882 ASSERT(dart_events_[dart_events_cursor_] != NULL); | |
883 dart_events_[dart_events_cursor_]->Clear(); | |
884 dart_events_[dart_events_cursor_]->Init(isolate, event); | |
885 dart_events_cursor_++; | |
886 } | |
887 | |
888 | |
889 intptr_t TimelineEventRingRecorder::NumDartEventsLocked() { | |
890 return dart_events_capacity_; | |
891 } | |
892 | |
893 | |
894 DartTimelineEvent* TimelineEventRingRecorder::DartEventAtLocked(intptr_t i) { | |
895 ASSERT(i >= 0); | |
896 ASSERT(i < dart_events_capacity_); | |
897 return dart_events_[i]; | |
898 } | |
899 | |
900 | |
901 void TimelineEventRingRecorder::PrintTraceEvent(JSONStream* js, | 820 void TimelineEventRingRecorder::PrintTraceEvent(JSONStream* js, |
902 TimelineEventFilter* filter) { | 821 TimelineEventFilter* filter) { |
903 JSONArray events(js); | 822 JSONArray events(js); |
904 PrintJSONEvents(&events, filter); | 823 PrintJSONEvents(&events, filter); |
905 } | 824 } |
906 | 825 |
907 | 826 |
908 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlockLocked() { | 827 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlockLocked() { |
909 return blocks_[0]; | 828 return blocks_[0]; |
910 } | 829 } |
911 | 830 |
912 | 831 |
913 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked( | 832 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() { |
914 Isolate* isolate) { | |
915 // TODO(johnmccutchan): This function should only hand out blocks | 833 // TODO(johnmccutchan): This function should only hand out blocks |
916 // which have been marked as finished. | 834 // which have been marked as finished. |
917 if (block_cursor_ == num_blocks_) { | 835 if (block_cursor_ == num_blocks_) { |
918 block_cursor_ = 0; | 836 block_cursor_ = 0; |
919 } | 837 } |
920 TimelineEventBlock* block = blocks_[block_cursor_++]; | 838 TimelineEventBlock* block = blocks_[block_cursor_++]; |
921 block->Reset(); | 839 block->Reset(); |
922 block->Open(isolate); | 840 block->Open(); |
923 return block; | 841 return block; |
924 } | 842 } |
925 | 843 |
926 | 844 |
927 intptr_t TimelineEventRingRecorder::FindOldestBlockIndex() const { | 845 intptr_t TimelineEventRingRecorder::FindOldestBlockIndex() const { |
928 int64_t earliest_time = kMaxInt64; | 846 int64_t earliest_time = kMaxInt64; |
929 intptr_t earliest_index = -1; | 847 intptr_t earliest_index = -1; |
930 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) { | 848 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) { |
931 TimelineEventBlock* block = blocks_[block_idx]; | 849 TimelineEventBlock* block = blocks_[block_idx]; |
932 if (block->IsEmpty()) { | 850 if (block->IsEmpty()) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
977 } | 895 } |
978 | 896 |
979 | 897 |
980 void TimelineEventStreamingRecorder::PrintTraceEvent( | 898 void TimelineEventStreamingRecorder::PrintTraceEvent( |
981 JSONStream* js, | 899 JSONStream* js, |
982 TimelineEventFilter* filter) { | 900 TimelineEventFilter* filter) { |
983 JSONArray events(js); | 901 JSONArray events(js); |
984 } | 902 } |
985 | 903 |
986 | 904 |
987 void TimelineEventStreamingRecorder::AppendDartEvent(Isolate* isolate, | |
988 const char* event) { | |
989 if (event != NULL) { | |
990 StreamDartEvent(event); | |
991 } | |
992 } | |
993 | |
994 | |
995 intptr_t TimelineEventStreamingRecorder::NumDartEventsLocked() { | |
996 return 0; | |
997 } | |
998 | |
999 | |
1000 DartTimelineEvent* TimelineEventStreamingRecorder::DartEventAtLocked( | |
1001 intptr_t i) { | |
1002 return NULL; | |
1003 } | |
1004 | |
1005 | |
1006 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() { | 905 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() { |
1007 TimelineEvent* event = new TimelineEvent(); | 906 TimelineEvent* event = new TimelineEvent(); |
1008 return event; | 907 return event; |
1009 } | 908 } |
1010 | 909 |
1011 | 910 |
1012 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) { | 911 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) { |
1013 StreamEvent(event); | 912 StreamEvent(event); |
1014 delete event; | 913 delete event; |
1015 } | 914 } |
1016 | 915 |
1017 | 916 |
1018 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder() | 917 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder() |
1019 : head_(NULL), | 918 : head_(NULL), |
1020 block_index_(0), | 919 block_index_(0) { |
1021 dart_events_(NULL), | |
1022 dart_events_capacity_(0), | |
1023 dart_events_cursor_(0) { | |
1024 } | 920 } |
1025 | 921 |
1026 | 922 |
1027 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js, | 923 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js, |
1028 TimelineEventFilter* filter) { | 924 TimelineEventFilter* filter) { |
1029 MutexLocker ml(&lock_); | 925 MutexLocker ml(&lock_); |
1030 JSONObject topLevel(js); | 926 JSONObject topLevel(js); |
1031 topLevel.AddProperty("type", "_Timeline"); | 927 topLevel.AddProperty("type", "_Timeline"); |
1032 { | 928 { |
1033 JSONArray events(&topLevel, "traceEvents"); | 929 JSONArray events(&topLevel, "traceEvents"); |
1034 PrintJSONMeta(&events); | 930 PrintJSONMeta(&events); |
1035 PrintJSONEvents(&events, filter); | 931 PrintJSONEvents(&events, filter); |
1036 } | 932 } |
1037 } | 933 } |
1038 | 934 |
1039 | 935 |
1040 void TimelineEventEndlessRecorder::PrintTraceEvent( | 936 void TimelineEventEndlessRecorder::PrintTraceEvent( |
1041 JSONStream* js, | 937 JSONStream* js, |
1042 TimelineEventFilter* filter) { | 938 TimelineEventFilter* filter) { |
1043 JSONArray events(js); | 939 JSONArray events(js); |
1044 PrintJSONEvents(&events, filter); | 940 PrintJSONEvents(&events, filter); |
1045 } | 941 } |
1046 | 942 |
1047 | 943 |
1048 void TimelineEventEndlessRecorder::AppendDartEvent(Isolate* isolate, | |
1049 const char* event) { | |
1050 MutexLocker ml(&lock_); | |
1051 // TODO(johnmccutchan): If locking becomes an issue, use the Isolate to store | |
1052 // the events. | |
1053 if (dart_events_cursor_ == dart_events_capacity_) { | |
1054 // Grow. | |
1055 intptr_t new_capacity = | |
1056 (dart_events_capacity_ == 0) ? 16 : dart_events_capacity_ * 2; | |
1057 dart_events_ = reinterpret_cast<DartTimelineEvent**>( | |
1058 realloc(dart_events_, new_capacity * sizeof(DartTimelineEvent*))); | |
1059 for (intptr_t i = dart_events_capacity_; i < new_capacity; i++) { | |
1060 // Fill with NULLs. | |
1061 dart_events_[i] = NULL; | |
1062 } | |
1063 dart_events_capacity_ = new_capacity; | |
1064 } | |
1065 ASSERT(dart_events_cursor_ < dart_events_capacity_); | |
1066 DartTimelineEvent* dart_event = new DartTimelineEvent(); | |
1067 dart_event->Init(isolate, event); | |
1068 ASSERT(dart_events_[dart_events_cursor_] == NULL); | |
1069 dart_events_[dart_events_cursor_++] = dart_event; | |
1070 } | |
1071 | |
1072 | |
1073 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() { | 944 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() { |
1074 return head_; | 945 return head_; |
1075 } | 946 } |
1076 | 947 |
1077 | 948 |
1078 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { | 949 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { |
1079 // Grab the current thread. | 950 // Grab the current thread. |
1080 Thread* thread = Thread::Current(); | 951 Thread* thread = Thread::Current(); |
1081 ASSERT(thread != NULL); | 952 ASSERT(thread != NULL); |
1082 return ThreadBlockStartEvent(); | 953 return ThreadBlockStartEvent(); |
1083 } | 954 } |
1084 | 955 |
1085 | 956 |
1086 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { | 957 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { |
1087 if (event == NULL) { | 958 if (event == NULL) { |
1088 return; | 959 return; |
1089 } | 960 } |
1090 ThreadBlockCompleteEvent(event); | 961 ThreadBlockCompleteEvent(event); |
1091 } | 962 } |
1092 | 963 |
1093 | 964 |
1094 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked( | 965 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked() { |
1095 Isolate* isolate) { | |
1096 TimelineEventBlock* block = new TimelineEventBlock(block_index_++); | 966 TimelineEventBlock* block = new TimelineEventBlock(block_index_++); |
1097 block->set_next(head_); | 967 block->set_next(head_); |
1098 block->Open(isolate); | 968 block->Open(); |
1099 head_ = block; | 969 head_ = block; |
1100 if (FLAG_trace_timeline) { | 970 if (FLAG_trace_timeline) { |
1101 if (isolate != NULL) { | 971 OS::Print("Created new block %p\n", block); |
1102 OS::Print("Created new isolate block %p for %s\n", | |
1103 block, isolate->name()); | |
1104 } else { | |
1105 OS::Print("Created new global block %p\n", block); | |
1106 } | |
1107 } | 972 } |
1108 return head_; | 973 return head_; |
1109 } | 974 } |
1110 | 975 |
1111 | 976 |
1112 intptr_t TimelineEventEndlessRecorder::NumDartEventsLocked() { | |
1113 return dart_events_cursor_; | |
1114 } | |
1115 | |
1116 | |
1117 DartTimelineEvent* TimelineEventEndlessRecorder::DartEventAtLocked( | |
1118 intptr_t i) { | |
1119 ASSERT(i >= 0); | |
1120 ASSERT(i < dart_events_cursor_); | |
1121 return dart_events_[i]; | |
1122 } | |
1123 | |
1124 | |
1125 void TimelineEventEndlessRecorder::PrintJSONEvents( | 977 void TimelineEventEndlessRecorder::PrintJSONEvents( |
1126 JSONArray* events, | 978 JSONArray* events, |
1127 TimelineEventFilter* filter) const { | 979 TimelineEventFilter* filter) const { |
1128 TimelineEventBlock* current = head_; | 980 TimelineEventBlock* current = head_; |
1129 | 981 |
1130 while (current != NULL) { | 982 while (current != NULL) { |
1131 if (!filter->IncludeBlock(current)) { | 983 if (!filter->IncludeBlock(current)) { |
1132 current = current->next(); | 984 current = current->next(); |
1133 continue; | 985 continue; |
1134 } | 986 } |
(...skipping 21 matching lines...) Expand all Loading... |
1156 block_index_ = 0; | 1008 block_index_ = 0; |
1157 Thread* thread = Thread::Current(); | 1009 Thread* thread = Thread::Current(); |
1158 thread->set_timeline_block(NULL); | 1010 thread->set_timeline_block(NULL); |
1159 } | 1011 } |
1160 | 1012 |
1161 | 1013 |
1162 TimelineEventBlock::TimelineEventBlock(intptr_t block_index) | 1014 TimelineEventBlock::TimelineEventBlock(intptr_t block_index) |
1163 : next_(NULL), | 1015 : next_(NULL), |
1164 length_(0), | 1016 length_(0), |
1165 block_index_(block_index), | 1017 block_index_(block_index), |
1166 isolate_(NULL), | 1018 thread_id_(OSThread::kInvalidThreadId), |
1167 in_use_(false) { | 1019 in_use_(false) { |
1168 } | 1020 } |
1169 | 1021 |
1170 | 1022 |
1171 TimelineEventBlock::~TimelineEventBlock() { | 1023 TimelineEventBlock::~TimelineEventBlock() { |
1172 Reset(); | 1024 Reset(); |
1173 } | 1025 } |
1174 | 1026 |
1175 | 1027 |
1176 TimelineEvent* TimelineEventBlock::StartEvent() { | 1028 TimelineEvent* TimelineEventBlock::StartEvent() { |
1177 ASSERT(!IsFull()); | 1029 ASSERT(!IsFull()); |
1178 if (FLAG_trace_timeline) { | 1030 if (FLAG_trace_timeline) { |
1179 OS::Print("StartEvent in block %p for thread %" Px "\n", | 1031 OS::Print("StartEvent in block %p for thread %" Px "\n", |
1180 this, OSThread::CurrentCurrentThreadIdAsIntPtr()); | 1032 this, OSThread::CurrentCurrentThreadIdAsIntPtr()); |
1181 } | 1033 } |
1182 return &events_[length_++]; | 1034 return &events_[length_++]; |
1183 } | 1035 } |
1184 | 1036 |
1185 | 1037 |
1186 ThreadId TimelineEventBlock::thread() const { | |
1187 ASSERT(length_ > 0); | |
1188 return events_[0].thread(); | |
1189 } | |
1190 | |
1191 | |
1192 int64_t TimelineEventBlock::LowerTimeBound() const { | 1038 int64_t TimelineEventBlock::LowerTimeBound() const { |
| 1039 if (length_ == 0) { |
| 1040 return kMaxInt64; |
| 1041 } |
1193 ASSERT(length_ > 0); | 1042 ASSERT(length_ > 0); |
1194 return events_[0].TimeOrigin(); | 1043 return events_[0].TimeOrigin(); |
1195 } | 1044 } |
1196 | 1045 |
1197 | 1046 |
1198 bool TimelineEventBlock::CheckBlock() { | 1047 bool TimelineEventBlock::CheckBlock() { |
1199 if (length() == 0) { | 1048 if (length() == 0) { |
1200 return true; | 1049 return true; |
1201 } | 1050 } |
1202 | 1051 |
1203 // - events in the block come from one thread. | |
1204 ThreadId tid = thread(); | |
1205 for (intptr_t i = 0; i < length(); i++) { | 1052 for (intptr_t i = 0; i < length(); i++) { |
1206 if (At(i)->thread() != tid) { | 1053 if (At(i)->thread() != thread_id()) { |
1207 return false; | 1054 return false; |
1208 } | 1055 } |
1209 } | 1056 } |
1210 | 1057 |
1211 // - events have monotonically increasing timestamps. | 1058 // - events have monotonically increasing timestamps. |
1212 int64_t last_time = LowerTimeBound(); | 1059 int64_t last_time = LowerTimeBound(); |
1213 for (intptr_t i = 0; i < length(); i++) { | 1060 for (intptr_t i = 0; i < length(); i++) { |
1214 if (last_time > At(i)->TimeOrigin()) { | 1061 if (last_time > At(i)->TimeOrigin()) { |
1215 return false; | 1062 return false; |
1216 } | 1063 } |
1217 last_time = At(i)->TimeOrigin(); | 1064 last_time = At(i)->TimeOrigin(); |
1218 } | 1065 } |
1219 | 1066 |
1220 return true; | 1067 return true; |
1221 } | 1068 } |
1222 | 1069 |
1223 | 1070 |
1224 void TimelineEventBlock::Reset() { | 1071 void TimelineEventBlock::Reset() { |
1225 for (intptr_t i = 0; i < kBlockSize; i++) { | 1072 for (intptr_t i = 0; i < kBlockSize; i++) { |
1226 // Clear any extra data. | 1073 // Clear any extra data. |
1227 events_[i].Reset(); | 1074 events_[i].Reset(); |
1228 } | 1075 } |
1229 length_ = 0; | 1076 length_ = 0; |
1230 isolate_ = NULL; | 1077 thread_id_ = OSThread::kInvalidThreadId; |
1231 in_use_ = false; | 1078 in_use_ = false; |
1232 } | 1079 } |
1233 | 1080 |
1234 | 1081 |
1235 void TimelineEventBlock::Open(Isolate* isolate) { | 1082 void TimelineEventBlock::Open() { |
1236 isolate_ = isolate; | 1083 thread_id_ = OSThread::GetCurrentThreadTraceId(); |
1237 in_use_ = true; | 1084 in_use_ = true; |
1238 } | 1085 } |
1239 | 1086 |
1240 | 1087 |
1241 void TimelineEventBlock::Finish() { | 1088 void TimelineEventBlock::Finish() { |
1242 if (FLAG_trace_timeline) { | 1089 if (FLAG_trace_timeline) { |
1243 OS::Print("Finish block %p\n", this); | 1090 OS::Print("Finish block %p\n", this); |
1244 } | 1091 } |
1245 in_use_ = false; | 1092 in_use_ = false; |
1246 } | 1093 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1282 } | 1129 } |
1283 | 1130 |
1284 | 1131 |
1285 TimelineEventBlock* TimelineEventBlockIterator::Next() { | 1132 TimelineEventBlock* TimelineEventBlockIterator::Next() { |
1286 ASSERT(current_ != NULL); | 1133 ASSERT(current_ != NULL); |
1287 TimelineEventBlock* r = current_; | 1134 TimelineEventBlock* r = current_; |
1288 current_ = current_->next(); | 1135 current_ = current_->next(); |
1289 return r; | 1136 return r; |
1290 } | 1137 } |
1291 | 1138 |
1292 | |
1293 DartTimelineEventIterator::DartTimelineEventIterator( | |
1294 TimelineEventRecorder* recorder) | |
1295 : cursor_(0), | |
1296 num_events_(0), | |
1297 recorder_(NULL) { | |
1298 Reset(recorder); | |
1299 } | |
1300 | |
1301 | |
1302 DartTimelineEventIterator::~DartTimelineEventIterator() { | |
1303 Reset(NULL); | |
1304 } | |
1305 | |
1306 | |
1307 void DartTimelineEventIterator::Reset(TimelineEventRecorder* recorder) { | |
1308 // Clear state. | |
1309 cursor_ = 0; | |
1310 num_events_ = 0; | |
1311 if (recorder_ != NULL) { | |
1312 // Unlock old recorder. | |
1313 recorder_->lock_.Unlock(); | |
1314 } | |
1315 recorder_ = recorder; | |
1316 if (recorder_ == NULL) { | |
1317 return; | |
1318 } | |
1319 // Lock new recorder. | |
1320 recorder_->lock_.Lock(); | |
1321 cursor_ = 0; | |
1322 num_events_ = recorder_->NumDartEventsLocked(); | |
1323 } | |
1324 | |
1325 | |
1326 bool DartTimelineEventIterator::HasNext() const { | |
1327 return cursor_ < num_events_; | |
1328 } | |
1329 | |
1330 | |
1331 DartTimelineEvent* DartTimelineEventIterator::Next() { | |
1332 ASSERT(cursor_ < num_events_); | |
1333 DartTimelineEvent* r = recorder_->DartEventAtLocked(cursor_); | |
1334 cursor_++; | |
1335 return r; | |
1336 } | |
1337 | |
1338 const char* DartTimelineEventIterator::PrintTraceEvents( | |
1339 TimelineEventRecorder* recorder, | |
1340 Zone* zone, | |
1341 Isolate* isolate) { | |
1342 if (recorder == NULL) { | |
1343 return NULL; | |
1344 } | |
1345 | |
1346 if (zone == NULL) { | |
1347 return NULL; | |
1348 } | |
1349 | |
1350 char* result = NULL; | |
1351 DartTimelineEventIterator iterator(recorder); | |
1352 while (iterator.HasNext()) { | |
1353 DartTimelineEvent* event = iterator.Next(); | |
1354 if (!event->IsValid()) { | |
1355 // Skip invalid | |
1356 continue; | |
1357 } | |
1358 if ((isolate != NULL) && (isolate != event->isolate())) { | |
1359 // If an isolate was specified, skip events from other isolates. | |
1360 continue; | |
1361 } | |
1362 ASSERT(event->event_as_json() != NULL); | |
1363 result = zone->ConcatStrings(result, event->event_as_json()); | |
1364 } | |
1365 return result; | |
1366 } | |
1367 | |
1368 } // namespace dart | 1139 } // namespace dart |
OLD | NEW |