Index: runtime/vm/timeline_analysis.cc |
diff --git a/runtime/vm/timeline_analysis.cc b/runtime/vm/timeline_analysis.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1e7480fa4c69a1094ac29c90616204f24e427138 |
--- /dev/null |
+++ b/runtime/vm/timeline_analysis.cc |
@@ -0,0 +1,139 @@ |
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+#include "vm/timeline_analysis.h" |
+ |
+#include "vm/flags.h" |
+ |
+namespace dart { |
+ |
+DECLARE_FLAG(bool, trace_timeline); |
+ |
+ |
+TimelineAnalysisThread::TimelineAnalysisThread(ThreadId id) |
+ : id_(id) { |
+} |
+ |
+ |
+TimelineAnalysisThread::~TimelineAnalysisThread() { |
+} |
+ |
+ |
+void TimelineAnalysisThread::AddBlock(TimelineEventBlock* block) { |
+ blocks_.Add(block); |
+} |
+ |
+ |
+static int CompareBlocksLowerTimeBound(TimelineEventBlock* const* a, |
+ TimelineEventBlock* const* b) { |
+ ASSERT(a != NULL); |
+ ASSERT(*a != NULL); |
+ ASSERT(b != NULL); |
+ ASSERT(*b != NULL); |
+ return (*a)->LowerTimeBound() - (*b)->LowerTimeBound(); |
+} |
+ |
+ |
+void TimelineAnalysisThread::Finalize() { |
+ blocks_.Sort(CompareBlocksLowerTimeBound); |
+} |
+ |
+ |
+TimelineAnalysis::TimelineAnalysis(Zone* zone, |
+ Isolate* isolate, |
+ TimelineEventEndlessRecorder* recorder) |
+ : zone_(zone), |
+ isolate_(isolate), |
+ recorder_(recorder), |
+ has_error_(false), |
+ error_msg_(NULL) { |
+ ASSERT(zone_ != NULL); |
+ ASSERT(isolate_ != NULL); |
+ ASSERT(recorder_ != NULL); |
+} |
+ |
+ |
+TimelineAnalysis::~TimelineAnalysis() { |
+} |
+ |
+ |
+void TimelineAnalysis::BuildThreads() { |
+ DiscoverThreads(); |
+ FinalizeThreads(); |
+} |
+ |
+ |
+TimelineAnalysisThread* TimelineAnalysis::GetThread(ThreadId tid) { |
+ // Linear lookup because we expect N (# of threads in an isolate) to be small. |
+ for (intptr_t i = 0; i < threads_.length(); i++) { |
+ TimelineAnalysisThread* thread = threads_.At(i); |
+ ASSERT(thread != NULL); |
+ if (thread->id() == tid) { |
+ return thread; |
+ } |
+ } |
+ return NULL; |
+} |
+ |
+ |
+TimelineAnalysisThread* TimelineAnalysis::GetOrAddThread(ThreadId tid) { |
+ TimelineAnalysisThread* thread = GetThread(tid); |
+ if (thread != NULL) { |
+ return thread; |
+ } |
+ // New thread. |
+ thread = new TimelineAnalysisThread(tid); |
+ threads_.Add(thread); |
+ return thread; |
+} |
+ |
+ |
+void TimelineAnalysis::DiscoverThreads() { |
+ TimelineEventBlockIterator it(recorder_); |
+ while (it.Next()) { |
+ TimelineEventBlock* block = it.current(); |
+ ASSERT(block != NULL); |
+ if (block->IsEmpty()) { |
+ // Skip empty blocks. |
+ continue; |
+ } |
+ if (!block->CheckBlock()) { |
+ // Skip bad blocks. |
+ // TODO(johnmccutchan): Make this into an error? |
+ continue; |
+ } |
+ TimelineAnalysisThread* thread = GetOrAddThread(block->thread()); |
+ ASSERT(thread != NULL); |
+ thread->AddBlock(block); |
+ } |
+} |
+ |
+ |
+void TimelineAnalysis::FinalizeThreads() { |
+ for (intptr_t i = 0; i < threads_.length(); i++) { |
+ TimelineAnalysisThread* thread = threads_.At(i); |
+ ASSERT(thread != NULL); |
+ thread->Finalize(); |
+ } |
+} |
+ |
+ |
+void TimelineAnalysis::SetError(const char* format, ...) { |
+ ASSERT(!has_error_); |
+ ASSERT(error_msg_ == NULL); |
+ has_error_ = true; |
+ va_list args; |
+ va_start(args, format); |
+ error_msg_ = zone_->VPrint(format, args); |
+ ASSERT(error_msg_ != NULL); |
+} |
+ |
+ |
+TimelinePauses::TimelinePauses(Zone* zone, |
+ Isolate* isolate, |
+ TimelineEventEndlessRecorder* recorder) |
+ : TimelineAnalysis(zone, isolate, recorder) { |
+} |
+ |
+} // namespace dart |