Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
service_event.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/service_event.h"
6
7#include "vm/debugger.h"
10#include "vm/timeline.h"
11
12namespace dart {
13
14#ifndef PRODUCT
15
17 : ServiceEvent(nullptr, nullptr, event_kind) {}
18
20 : ServiceEvent(isolate_group, nullptr, event_kind) {}
21
23 : ServiceEvent(isolate != nullptr ? isolate->group() : nullptr,
24 isolate,
25 event_kind) {}
26
28 Isolate* isolate,
29 EventKind event_kind)
30 : isolate_(isolate),
31 isolate_group_(isolate_group),
32 kind_(event_kind),
33 flag_name_(nullptr),
34 flag_new_value_(nullptr),
35 previous_tag_(nullptr),
36 updated_tag_(nullptr),
37 embedder_kind_(nullptr),
38 embedder_stream_id_(nullptr),
39 breakpoint_(nullptr),
40 top_frame_(nullptr),
41 timeline_event_block_(nullptr),
42 extension_rpc_(nullptr),
43 exception_(nullptr),
44 reload_error_(nullptr),
45 spawn_token_(nullptr),
46 spawn_error_(nullptr),
47 at_async_jump_(false),
48 inspectee_(nullptr),
49 gc_stats_(nullptr),
50 bytes_(nullptr),
51 bytes_length_(0),
52 timestamp_(OS::GetCurrentTimeMillis()) {
53 // We should never generate events for the vm isolate as it is never reported
54 // over the service.
55 ASSERT(isolate_ != Dart::vm_isolate());
56
57 // VM internal isolates should never post service events. However, the Isolate
58 // service object uses a service event to represent the current running state
59 // of the isolate, so we need to allow for system isolates to create resume
60 // and none events for this purpose. The resume event represents a running
61 // isolate and the none event is returned for an isolate that has not yet
62 // been marked as runnable (see "pauseEvent" in Isolate::PrintJSON).
65 (event_kind == ServiceEvent::kResume ||
66 event_kind == ServiceEvent::kNone ||
67 // VM service can print Observatory information to Stdout or Stderr
68 // which are embedder streams.
69 event_kind == ServiceEvent::kEmbedder ||
70 event_kind == ServiceEvent::kCpuSamples)));
71
72 if ((event_kind == ServiceEvent::kPauseStart) ||
73 (event_kind == ServiceEvent::kPauseExit)) {
74 timestamp_ = isolate_->message_handler()->paused_timestamp();
75 } else if (event_kind == ServiceEvent::kResume) {
76 timestamp_ = isolate_->last_resume_timestamp();
77 }
78 ASSERT(timestamp_ > -1);
79}
80
84
85const char* ServiceEvent::KindAsCString() const {
86 switch (kind()) {
87 case kVMUpdate:
88 return "VMUpdate";
89 case kVMFlagUpdate:
90 return "VMFlagUpdate";
91 case kIsolateStart:
92 return "IsolateStart";
94 return "IsolateRunnable";
95 case kIsolateExit:
96 return "IsolateExit";
97 case kIsolateUpdate:
98 return "IsolateUpdate";
100 return "ServiceExtensionAdded";
101 case kIsolateReload:
102 return "IsolateReload";
103 case kPauseStart:
104 return "PauseStart";
105 case kPauseExit:
106 return "PauseExit";
107 case kPauseBreakpoint:
108 return "PauseBreakpoint";
110 return "PauseInterrupted";
111 case kPauseException:
112 return "PauseException";
114 return "PausePostRequest";
115 case kNone:
116 return "None";
117 case kResume:
118 return "Resume";
119 case kBreakpointAdded:
120 return "BreakpointAdded";
122 return "BreakpointResolved";
124 return "BreakpointRemoved";
126 return "BreakpointUpdated";
127 case kGC:
128 return "GC"; // TODO(koda): Change to GarbageCollected.
129 case kInspect:
130 return "Inspect";
131 case kEmbedder:
132 return embedder_kind();
133 case kLogging:
134 return "Logging";
136 return "_DebuggerSettingsUpdate";
137 case kIllegal:
138 return "Illegal";
139 case kExtension:
140 return "Extension";
141 case kTimelineEvents:
142 return "TimelineEvents";
144 return "TimelineStreamSubscriptionsUpdate";
145 case kUserTagChanged:
146 return "UserTagChanged";
147 case kCpuSamples:
148 return "CpuSamples";
149 default:
150 UNREACHABLE();
151 return "Unknown";
152 }
153}
154
156 switch (kind()) {
157 case kVMUpdate:
158 case kVMFlagUpdate:
159 return &Service::vm_stream;
160
161 case kIsolateStart:
162 case kIsolateRunnable:
163 case kIsolateExit:
164 case kIsolateUpdate:
165 case kIsolateReload:
168
169 case kPauseStart:
170 case kPauseExit:
171 case kPauseBreakpoint:
173 case kPauseException:
175 case kNone:
176 case kResume:
177 case kBreakpointAdded:
181 case kInspect:
183 return &Service::debug_stream;
184
185 case kGC:
186 return &Service::gc_stream;
187
188 case kLogging:
190
191 case kExtension:
193
194 case kTimelineEvents:
197
198 case kEmbedder:
199 return nullptr;
200
201 case kCpuSamples:
202 case kUserTagChanged:
204
205 default:
206 UNREACHABLE();
207 return nullptr;
208 }
209}
210
211const char* ServiceEvent::stream_id() const {
212 const StreamInfo* stream = stream_info();
213 if (stream == nullptr) {
214 ASSERT(kind() == kEmbedder);
215 return embedder_stream_id_;
216 } else {
217 return stream->id();
218 }
219}
220
222 JSONObject jsobj(js);
223 PrintJSONHeader(&jsobj);
224 if (kind() == kVMFlagUpdate) {
225 jsobj.AddProperty("flag", flag_name());
226 // For backwards compatibility, "new_value" is also provided.
227 jsobj.AddProperty("newValue", flag_new_value());
228 }
229 if (kind() == kUserTagChanged) {
230 jsobj.AddProperty("previousTag", previous_tag());
231 jsobj.AddProperty("updatedTag", updated_tag());
232 }
233 if (kind() == kIsolateReload) {
234 if (reload_error_ == nullptr) {
235 jsobj.AddProperty("status", "success");
236 } else {
237 jsobj.AddProperty("status", "failure");
238 jsobj.AddProperty("reloadError", *(reload_error()));
239 }
240 }
241 if (kind() == kServiceExtensionAdded) {
242 ASSERT(extension_rpc_ != nullptr);
243 jsobj.AddProperty("extensionRPC", extension_rpc_->ToCString());
244 }
245 if (kind() == kPauseBreakpoint) {
246 JSONArray jsarr(&jsobj, "pauseBreakpoints");
247 // TODO(rmacnak): If we are paused at more than one breakpoint,
248 // provide it here.
249 if (breakpoint() != nullptr) {
250 jsarr.AddValue(breakpoint());
251 }
252 } else {
253 if (breakpoint() != nullptr) {
254 jsobj.AddProperty("breakpoint", breakpoint());
255 }
256 }
257 if (kind() == kTimelineEvents) {
258 jsobj.AddProperty("timelineEvents", timeline_event_block_);
259 }
261 JSONArray arr(&jsobj, "updatedStreams");
262 Timeline::PrintFlagsToJSONArray(&arr);
263 }
264 if (kind() == kDebuggerSettingsUpdate) {
265 JSONObject jssettings(&jsobj, "_debuggerSettings");
266 isolate()->debugger()->PrintSettingsToJSONObject(&jssettings);
267 }
268#if !defined(DART_PRECOMPILED_RUNTIME)
269 if (top_frame() != nullptr) {
270 JSONObject jsFrame(&jsobj, "topFrame");
271 top_frame()->PrintToJSONObject(&jsFrame);
272 intptr_t index = 0; // Avoid ambiguity in call to AddProperty.
273 jsFrame.AddProperty("index", index);
274 }
275#endif
276 if (exception() != nullptr) {
277 jsobj.AddProperty("exception", *(exception()));
278 }
279 if (at_async_jump()) {
280 jsobj.AddProperty("atAsyncSuspension", true);
281 }
282 if (inspectee() != nullptr) {
283 jsobj.AddProperty("inspectee", *(inspectee()));
284 }
285 if (gc_stats() != nullptr) {
286 jsobj.AddProperty("reason", Heap::GCReasonToString(gc_stats()->reason_));
287 jsobj.AddProperty("gcType", Heap::GCTypeToString(gc_stats()->type_));
290 }
291 if (bytes() != nullptr) {
292 jsobj.AddPropertyBase64("bytes", bytes(), bytes_length());
293 }
294 if (kind() == kLogging) {
295 JSONObject logRecord(&jsobj, "logRecord");
296 logRecord.AddProperty("type", "LogRecord");
297 logRecord.AddProperty64("sequenceNumber", log_record_.sequence_number);
298 logRecord.AddPropertyTimeMillis("time", log_record_.timestamp);
299 logRecord.AddProperty64("level", log_record_.level);
300 logRecord.AddProperty("loggerName", *(log_record_.name));
301 logRecord.AddProperty("message", *(log_record_.message));
302 logRecord.AddProperty("zone", *(log_record_.zone));
303 logRecord.AddProperty("error", *(log_record_.error));
304 logRecord.AddProperty("stackTrace", *(log_record_.stack_trace));
305 }
306 if (kind() == kExtension) {
307 js->AppendSerializedObject("extensionData",
308 extension_event_.event_data->ToCString());
309 }
310
311 if (kind() == kCpuSamples) {
312 JSONObject cpu_profile(&jsobj, "cpuSamples");
313 cpu_profile_->PrintProfileJSON(&cpu_profile, /*include_code_samples=*/false,
314 /*is_event=*/true);
315 }
316}
317
319 ASSERT(jsobj != nullptr);
320 jsobj->AddProperty("type", "Event");
321 jsobj->AddProperty("kind", KindAsCString());
322 if (kind() == kExtension) {
323 ASSERT(extension_event_.event_kind != nullptr);
324 jsobj->AddProperty("extensionKind",
325 extension_event_.event_kind->ToCString());
326 }
327 if (isolate_group() != nullptr) {
328 jsobj->AddProperty("isolateGroup", isolate_group());
329 }
330 if (isolate() != nullptr) {
331 ASSERT(isolate_group() != nullptr);
332 jsobj->AddProperty("isolate", isolate());
333 }
334 if (isolate_group() == nullptr && isolate() == nullptr) {
335 jsobj->AddPropertyVM("vm");
336 }
337 ASSERT(timestamp_ != -1);
338 jsobj->AddPropertyTimeMillis("timestamp", timestamp_);
339}
340
341#endif // !PRODUCT
342
343} // namespace dart
#define UNREACHABLE()
Definition assert.h:248
void PrintToJSONObject(JSONObject *jsobj)
Definition debugger.cc:1221
static Isolate * vm_isolate()
Definition dart.h:68
void PrintSettingsToJSONObject(JSONObject *jsobj) const
Definition debugger.cc:468
static const char * GCReasonToString(GCReason reason)
Definition heap.cc:849
@ kNew
Definition heap.h:38
@ kOld
Definition heap.h:39
void PrintToJSONObject(Space space, JSONObject *object) const
Definition heap.cc:973
static const char * GCTypeToString(GCType type)
Definition heap.cc:831
Heap * heap() const
Definition isolate.h:295
int64_t last_resume_timestamp() const
Definition isolate.h:1112
static bool IsVMInternalIsolate(const Isolate *isolate)
Definition isolate.cc:3563
Debugger * debugger() const
Definition isolate.h:1061
MessageHandler * message_handler() const
Definition isolate.cc:2380
void AddValue(bool b) const
void AddPropertyVM(const char *name, bool ref=true) const
void AddProperty64(const char *name, int64_t i) const
void AddProperty(const char *name, bool b) const
void AddPropertyBase64(const char *name, const uint8_t *bytes, intptr_t length) const
void AddPropertyTimeMillis(const char *name, int64_t millis) const
int64_t paused_timestamp() const
Definition os.h:19
static int64_t GetCurrentTimeMillis()
void PrintProfileJSON(JSONStream *stream, bool include_code_samples)
Profile * cpu_profile() const
const StreamInfo * stream_info() const
Breakpoint * breakpoint() const
const char * KindAsCString() const
const char * previous_tag() const
intptr_t bytes_length() const
const char * stream_id() const
bool at_async_jump() const
const Object * exception() const
const uint8_t * bytes() const
Isolate * isolate() const
IsolateGroup * isolate_group() const
const char * updated_tag() const
ActivationFrame * top_frame() const
const Object * inspectee() const
const char * flag_new_value() const
const char * flag_name() const
void PrintJSONHeader(JSONObject *jsobj) const
void PrintJSON(JSONStream *js) const
const char * embedder_kind() const
ServiceEvent(EventKind event_kind)
EventKind kind() const
const Heap::GCStats * gc_stats() const
const Error * reload_error() const
static StreamInfo isolate_stream
Definition service.h:180
static StreamInfo timeline_stream
Definition service.h:187
static StreamInfo debug_stream
Definition service.h:181
static StreamInfo vm_stream
Definition service.h:179
static StreamInfo logging_stream
Definition service.h:185
static StreamInfo profiler_stream
Definition service.h:188
static StreamInfo gc_stream
Definition service.h:182
static StreamInfo extension_stream
Definition service.h:186
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition object.cc:24205
#define ASSERT(E)