Index: runtime/vm/isolate.cc |
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc |
index 588cd2d7f7acf40f7eb6276a3c5fdd67ad54582d..4ad066786a7fd183f37a53a51cab0cb8813290c3 100644 |
--- a/runtime/vm/isolate.cc |
+++ b/runtime/vm/isolate.cc |
@@ -35,6 +35,7 @@ |
#include "vm/symbols.h" |
#include "vm/tags.h" |
#include "vm/thread_interrupter.h" |
+#include "vm/timeline.h" |
#include "vm/timer.h" |
#include "vm/visitor.h" |
@@ -54,6 +55,10 @@ DEFINE_FLAG(charp, isolate_log_filter, NULL, |
"Log isolates whose name include the filter. " |
"Default: service isolate log messages are suppressed."); |
+DEFINE_FLAG(charp, timeline_trace_dir, NULL, |
+ "Enable all timeline trace streams and output traces " |
+ "into specified directory."); |
+ |
// TODO(iposva): Make these isolate specific flags inaccessible using the |
// regular FLAG_xyz pattern. |
// These flags are per-isolate and only influence the defaults. |
@@ -368,6 +373,8 @@ void IsolateMessageHandler::MessageNotify(Message::Priority priority) { |
bool IsolateMessageHandler::HandleMessage(Message* message) { |
StackZone zone(I); |
HandleScope handle_scope(I); |
+ TimelineDurationScope tds(I, I->GetIsolateStream(), "HandleMessage"); |
+ |
// TODO(turnidge): Rework collection total dart execution. This can |
// overcount when other things (gc, compilation) are active. |
TIMERSCOPE(isolate_, time_dart_execution); |
@@ -662,6 +669,7 @@ Isolate::Isolate(const Dart_IsolateFlags& api_flags) |
last_allocationprofile_gc_timestamp_(0), |
object_id_ring_(NULL), |
trace_buffer_(NULL), |
+ timeline_event_buffer_(NULL), |
profiler_data_(NULL), |
thread_state_(NULL), |
tag_table_(GrowableObjectArray::null()), |
@@ -710,6 +718,7 @@ Isolate::~Isolate() { |
delete compiler_stats_; |
compiler_stats_ = NULL; |
} |
+ RemoveTimelineEventBuffer(); |
} |
@@ -739,6 +748,15 @@ Isolate* Isolate::Init(const char* name_prefix, |
ISOLATE_METRIC_LIST(ISOLATE_METRIC_INIT); |
#undef ISOLATE_METRIC_INIT |
+ const bool force_streams = FLAG_timeline_trace_dir != NULL; |
+ |
+ // Initialize Timeline streams. |
+#define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default) \ |
+ result->stream_##name##_.Init(#name, force_streams || enabled_by_default); |
+ ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT); |
+#undef ISOLATE_TIMELINE_STREAM_INIT |
+ |
+ |
// TODO(5411455): For now just set the recently created isolate as |
// the current isolate. |
Thread::EnterIsolate(result); |
@@ -963,6 +981,12 @@ bool Isolate::MakeRunnable() { |
ASSERT(this == state->isolate()); |
Run(); |
} |
+ TimelineStream* stream = GetIsolateStream(); |
+ ASSERT(stream != NULL); |
+ TimelineEvent* event = stream->RecordEvent(); |
+ if (event != NULL) { |
+ event->Instant(stream, "Runnable"); |
+ } |
return true; |
} |
@@ -1452,6 +1476,10 @@ void Isolate::Shutdown() { |
OS::Print("[-] Stopping isolate:\n" |
"\tisolate: %s\n", name()); |
} |
+ |
+ if ((timeline_event_buffer_ != NULL) && (FLAG_timeline_trace_dir != NULL)) { |
+ timeline_event_buffer_->WriteTo(FLAG_timeline_trace_dir); |
+ } |
} |
// TODO(5411455): For now just make sure there are no current isolates |
@@ -1550,6 +1578,21 @@ void Isolate::VisitPrologueWeakPersistentHandles(HandleVisitor* visitor) { |
} |
+void Isolate::SetTimelineEventBuffer( |
+ TimelineEventBuffer* timeline_event_buffer) { |
+#define ISOLATE_TIMELINE_STREAM_SET_BUFFER(name, enabled_by_default) \ |
+ stream_##name##_.set_buffer(timeline_event_buffer); |
+ ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_SET_BUFFER) |
+#undef ISOLATE_TIMELINE_STREAM_SET_BUFFER |
+ timeline_event_buffer_ = timeline_event_buffer; |
+} |
+ |
+void Isolate::RemoveTimelineEventBuffer() { |
+ SetTimelineEventBuffer(NULL); |
+ delete timeline_event_buffer_; |
+} |
+ |
+ |
void Isolate::PrintJSON(JSONStream* stream, bool ref) { |
JSONObject jsobj(stream); |
jsobj.AddProperty("type", (ref ? "@Isolate" : "Isolate")); |