Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: runtime/vm/service.cc

Issue 131973007: Allow root level requests in the vm service. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 "vm/service.h" 5 #include "vm/service.h"
6 6
7 #include "vm/cpu.h" 7 #include "vm/cpu.h"
8 #include "vm/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/debugger.h" 9 #include "vm/debugger.h"
10 #include "vm/heap_histogram.h" 10 #include "vm/heap_histogram.h"
11 #include "vm/isolate.h" 11 #include "vm/isolate.h"
12 #include "vm/message.h" 12 #include "vm/message.h"
13 #include "vm/object.h" 13 #include "vm/object.h"
14 #include "vm/object_id_ring.h" 14 #include "vm/object_id_ring.h"
15 #include "vm/object_store.h" 15 #include "vm/object_store.h"
16 #include "vm/port.h" 16 #include "vm/port.h"
17 #include "vm/profiler.h" 17 #include "vm/profiler.h"
18 18
19 namespace dart { 19 namespace dart {
20 20
21 typedef void (*ServiceMessageHandler)(Isolate* isolate, JSONStream* stream); 21 // A handler for a per-isolate request. These handlers must call
22 // PostReply in order to respond to the request.
23 typedef void (*IsolateMessageHandler)(Isolate* isolate, JSONStream* stream);
Cutch 2014/01/09 23:03:23 Why not have the handler functions return true to
turnidge 2014/01/15 20:21:04 Done.
22 24
23 struct ServiceMessageHandlerEntry { 25 struct IsolateMessageHandlerEntry {
24 const char* command; 26 const char* command;
25 ServiceMessageHandler handler; 27 IsolateMessageHandler handler;
26 }; 28 };
27 29
28 static ServiceMessageHandler FindServiceMessageHandler(const char* command); 30 static IsolateMessageHandler FindIsolateMessageHandler(const char* command);
29 31
32 // A handler for a root (vm-global) request. These handlers do not
33 // call PostReply.
34 typedef void (*RootMessageHandler)(JSONStream* stream);
35
36 struct RootMessageHandlerEntry {
37 const char* command;
38 RootMessageHandler handler;
39 };
40
41 static RootMessageHandler FindRootMessageHandler(const char* command);
30 42
31 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { 43 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
32 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); 44 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
33 return reinterpret_cast<uint8_t*>(new_ptr); 45 return reinterpret_cast<uint8_t*>(new_ptr);
34 } 46 }
35 47
36 48
37 static void PostReply(const String& reply, const Instance& reply_port) { 49 static void PostReply(JSONStream* js) {
50 Dart_Port reply_port = js->reply_port();
51 ASSERT(reply_port != ILLEGAL_PORT);
52 js->SetReplyPort(ILLEGAL_PORT); // Prevent double replies.
53
54 const String& reply = String::Handle(String::New(js->ToCString()));
55 ASSERT(!reply.IsNull());
56
57 uint8_t* data = NULL;
58 MessageWriter writer(&data, &allocator);
59 writer.WriteMessage(reply);
60 PortMap::PostMessage(new Message(reply_port, data,
61 writer.BytesWritten(),
62 Message::kNormalPriority));
63 }
64
65
66 static void SetupJSONStream(JSONStream* js, Zone* zone,
67 const Instance& reply_port,
68 const GrowableObjectArray& path,
69 const GrowableObjectArray& option_keys,
70 const GrowableObjectArray& option_values) {
71 // Setup the reply port.
38 const Object& id_obj = Object::Handle( 72 const Object& id_obj = Object::Handle(
39 DartLibraryCalls::PortGetId(reply_port)); 73 DartLibraryCalls::PortGetId(reply_port));
40 if (id_obj.IsError()) { 74 if (id_obj.IsError()) {
41 Exceptions::PropagateError(Error::Cast(id_obj)); 75 Exceptions::PropagateError(Error::Cast(id_obj));
42 } 76 }
43 const Integer& id = Integer::Cast(id_obj); 77 const Integer& id = Integer::Cast(id_obj);
44 Dart_Port port = static_cast<Dart_Port>(id.AsInt64Value()); 78 Dart_Port port = static_cast<Dart_Port>(id.AsInt64Value());
45 ASSERT(port != ILLEGAL_PORT); 79 ASSERT(port != ILLEGAL_PORT);
80 js->SetReplyPort(port);
46 81
47 uint8_t* data = NULL; 82 // Setup JSONStream arguments and options. The arguments and options
48 MessageWriter writer(&data, &allocator); 83 // are zone allocated and will be freed immediately after handling the
49 writer.WriteMessage(reply); 84 // message.
50 PortMap::PostMessage(new Message(port, data, 85 const char** arguments = zone->Alloc<const char*>(path.Length());
51 writer.BytesWritten(), 86 String& string_iterator = String::Handle();
52 Message::kNormalPriority)); 87 for (intptr_t i = 0; i < path.Length(); i++) {
53 } 88 string_iterator ^= path.At(i);
54 89 arguments[i] = zone->MakeCopyOfString(string_iterator.ToCString());
55 90 }
56 void Service::HandleServiceMessage(Isolate* isolate, const Instance& msg) { 91 js->SetArguments(arguments, path.Length());
57 ASSERT(isolate != NULL); 92 if (option_keys.Length() > 0) {
58 ASSERT(!msg.IsNull()); 93 const char** option_keys_native =
59 ASSERT(msg.IsGrowableObjectArray()); 94 zone->Alloc<const char*>(option_keys.Length());
60 95 const char** option_values_native =
61 { 96 zone->Alloc<const char*>(option_keys.Length());
62 StackZone zone(isolate); 97 for (intptr_t i = 0; i < option_keys.Length(); i++) {
63 HANDLESCOPE(isolate); 98 string_iterator ^= option_keys.At(i);
64 99 option_keys_native[i] =
65 const GrowableObjectArray& message = GrowableObjectArray::Cast(msg); 100 zone->MakeCopyOfString(string_iterator.ToCString());
66 // Message is a list with three entries. 101 string_iterator ^= option_values.At(i);
67 ASSERT(message.Length() == 4); 102 option_values_native[i] =
68 103 zone->MakeCopyOfString(string_iterator.ToCString());
69 Instance& reply_port = Instance::Handle(isolate);
70 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
71 GrowableObjectArray& option_keys = GrowableObjectArray::Handle(isolate);
72 GrowableObjectArray& option_values = GrowableObjectArray::Handle(isolate);
73 reply_port ^= message.At(0);
74 path ^= message.At(1);
75 option_keys ^= message.At(2);
76 option_values ^= message.At(3);
77
78 ASSERT(!path.IsNull());
79 ASSERT(!option_keys.IsNull());
80 ASSERT(!option_values.IsNull());
81 // Path always has at least one entry in it.
82 ASSERT(path.Length() > 0);
83 // Same number of option keys as values.
84 ASSERT(option_keys.Length() == option_values.Length());
85
86 String& pathSegment = String::Handle();
87 pathSegment ^= path.At(0);
88 ASSERT(!pathSegment.IsNull());
89
90 ServiceMessageHandler handler =
91 FindServiceMessageHandler(pathSegment.ToCString());
92 ASSERT(handler != NULL);
93 {
94 JSONStream js;
95
96 // Setup JSONStream arguments and options. The arguments and options
97 // are zone allocated and will be freed immediately after handling the
98 // message.
99 Zone* zoneAllocator = zone.GetZone();
100 const char** arguments = zoneAllocator->Alloc<const char*>(path.Length());
101 String& string_iterator = String::Handle();
102 for (intptr_t i = 0; i < path.Length(); i++) {
103 string_iterator ^= path.At(i);
104 arguments[i] =
105 zoneAllocator->MakeCopyOfString(string_iterator.ToCString());
106 }
107 js.SetArguments(arguments, path.Length());
108 if (option_keys.Length() > 0) {
109 const char** option_keys_native =
110 zoneAllocator->Alloc<const char*>(option_keys.Length());
111 const char** option_values_native =
112 zoneAllocator->Alloc<const char*>(option_keys.Length());
113 for (intptr_t i = 0; i < option_keys.Length(); i++) {
114 string_iterator ^= option_keys.At(i);
115 option_keys_native[i] =
116 zoneAllocator->MakeCopyOfString(string_iterator.ToCString());
117 string_iterator ^= option_values.At(i);
118 option_values_native[i] =
119 zoneAllocator->MakeCopyOfString(string_iterator.ToCString());
120 }
121 js.SetOptions(option_keys_native, option_values_native,
122 option_keys.Length());
123 }
124
125 handler(isolate, &js);
126 const String& reply = String::Handle(String::New(js.ToCString()));
127 ASSERT(!reply.IsNull());
128 PostReply(reply, reply_port);
129 } 104 }
105 js->SetOptions(option_keys_native, option_values_native,
106 option_keys.Length());
130 } 107 }
131 } 108 }
132 109
133 110
134 static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) { 111 static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) {
135 JSONObject jsobj(&obj, "message"); 112 JSONObject jsobj(&obj, "message");
136 { 113 {
137 JSONArray jsarr(&jsobj, "arguments"); 114 JSONArray jsarr(&jsobj, "arguments");
138 for (intptr_t i = 0; i < js->num_arguments(); i++) { 115 for (intptr_t i = 0; i < js->num_arguments(); i++) {
139 jsarr.AddValue(js->GetArgument(i)); 116 jsarr.AddValue(js->GetArgument(i));
140 } 117 }
141 } 118 }
142 { 119 {
143 JSONArray jsarr(&jsobj, "option_keys"); 120 JSONArray jsarr(&jsobj, "option_keys");
144 for (intptr_t i = 0; i < js->num_options(); i++) { 121 for (intptr_t i = 0; i < js->num_options(); i++) {
145 jsarr.AddValue(js->GetOptionKey(i)); 122 jsarr.AddValue(js->GetOptionKey(i));
146 } 123 }
147 } 124 }
148 { 125 {
149 JSONArray jsarr(&jsobj, "option_values"); 126 JSONArray jsarr(&jsobj, "option_values");
150 for (intptr_t i = 0; i < js->num_options(); i++) { 127 for (intptr_t i = 0; i < js->num_options(); i++) {
151 jsarr.AddValue(js->GetOptionValue(i)); 128 jsarr.AddValue(js->GetOptionValue(i));
152 } 129 }
153 } 130 }
154 } 131 }
155 132
156 133
157 static void PrintGenericError(JSONStream* js) {
158 JSONObject jsobj(js);
159 jsobj.AddProperty("type", "Error");
160 jsobj.AddProperty("text", "Invalid request.");
161 PrintArgumentsAndOptions(jsobj, js);
162 }
163
164
165 static void PrintError(JSONStream* js, const char* format, ...) { 134 static void PrintError(JSONStream* js, const char* format, ...) {
166 Isolate* isolate = Isolate::Current(); 135 Isolate* isolate = Isolate::Current();
167 136
168 va_list args; 137 va_list args;
169 va_start(args, format); 138 va_start(args, format);
170 intptr_t len = OS::VSNPrint(NULL, 0, format, args); 139 intptr_t len = OS::VSNPrint(NULL, 0, format, args);
171 va_end(args); 140 va_end(args);
172 141
173 char* buffer = isolate->current_zone()->Alloc<char>(len + 1); 142 char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
174 va_list args2; 143 va_list args2;
175 va_start(args2, format); 144 va_start(args2, format);
176 OS::VSNPrint(buffer, (len + 1), format, args2); 145 OS::VSNPrint(buffer, (len + 1), format, args2);
177 va_end(args2); 146 va_end(args2);
178 147
179 JSONObject jsobj(js); 148 JSONObject jsobj(js);
180 jsobj.AddProperty("type", "Error"); 149 jsobj.AddProperty("type", "Error");
181 jsobj.AddProperty("text", buffer); 150 jsobj.AddProperty("text", buffer);
182 PrintArgumentsAndOptions(jsobj, js); 151 PrintArgumentsAndOptions(jsobj, js);
183 } 152 }
184 153
185 154
155 void Service::HandleIsolateMessage(Isolate* isolate, const Instance& msg) {
156 ASSERT(isolate != NULL);
157 ASSERT(!msg.IsNull());
158 ASSERT(msg.IsGrowableObjectArray());
159
160 {
161 StackZone zone(isolate);
162 HANDLESCOPE(isolate);
163
164 const GrowableObjectArray& message = GrowableObjectArray::Cast(msg);
165 // Message is a list with four entries.
166 ASSERT(message.Length() == 4);
167
168 Instance& reply_port = Instance::Handle(isolate);
169 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
170 GrowableObjectArray& option_keys = GrowableObjectArray::Handle(isolate);
171 GrowableObjectArray& option_values = GrowableObjectArray::Handle(isolate);
172 reply_port ^= message.At(0);
173 path ^= message.At(1);
174 option_keys ^= message.At(2);
175 option_values ^= message.At(3);
176
177 ASSERT(!path.IsNull());
178 ASSERT(!option_keys.IsNull());
179 ASSERT(!option_values.IsNull());
180 // Path always has at least one entry in it.
181 ASSERT(path.Length() > 0);
182 // Same number of option keys as values.
183 ASSERT(option_keys.Length() == option_values.Length());
184
185 String& pathSegment = String::Handle();
186 pathSegment ^= path.At(0);
187 ASSERT(!pathSegment.IsNull());
188
189 IsolateMessageHandler handler =
190 FindIsolateMessageHandler(pathSegment.ToCString());
191 {
192 JSONStream js;
193 SetupJSONStream(&js, zone.GetZone(),
194 reply_port, path, option_keys, option_values);
195 if (handler == NULL) {
196 PrintError(&js, "Unrecognized path");
197 PostReply(&js);
198 } else {
199 handler(isolate, &js);
200 }
201 }
202 }
203 }
204
205
186 static void HandleName(Isolate* isolate, JSONStream* js) { 206 static void HandleName(Isolate* isolate, JSONStream* js) {
187 JSONObject jsobj(js); 207 {
188 jsobj.AddProperty("type", "IsolateName"); 208 JSONObject jsobj(js);
189 jsobj.AddProperty("id", static_cast<intptr_t>(isolate->main_port())); 209 jsobj.AddProperty("type", "IsolateName");
190 jsobj.AddProperty("name", isolate->name()); 210 jsobj.AddProperty("id", static_cast<intptr_t>(isolate->main_port()));
211 jsobj.AddProperty("name", isolate->name());
212 }
213 PostReply(js);
191 } 214 }
192 215
193 216
194 static void HandleStackTrace(Isolate* isolate, JSONStream* js) { 217 static void HandleStackTrace(Isolate* isolate, JSONStream* js) {
195 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); 218 {
196 JSONObject jsobj(js); 219 DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
197 jsobj.AddProperty("type", "StackTrace"); 220 JSONObject jsobj(js);
198 JSONArray jsarr(&jsobj, "members"); 221 jsobj.AddProperty("type", "StackTrace");
199 intptr_t n_frames = stack->Length(); 222 JSONArray jsarr(&jsobj, "members");
200 String& function = String::Handle(); 223 intptr_t n_frames = stack->Length();
201 Script& script = Script::Handle(); 224 String& function = String::Handle();
202 for (int i = 0; i < n_frames; i++) { 225 Script& script = Script::Handle();
203 ActivationFrame* frame = stack->FrameAt(i); 226 for (int i = 0; i < n_frames; i++) {
204 script ^= frame->SourceScript(); 227 ActivationFrame* frame = stack->FrameAt(i);
205 function ^= frame->function().UserVisibleName(); 228 script ^= frame->SourceScript();
206 JSONObject jsobj(&jsarr); 229 function ^= frame->function().UserVisibleName();
207 jsobj.AddProperty("name", function.ToCString()); 230 JSONObject jsobj(&jsarr);
208 jsobj.AddProperty("script", script); 231 jsobj.AddProperty("name", function.ToCString());
209 jsobj.AddProperty("line", frame->LineNumber()); 232 jsobj.AddProperty("script", script);
210 jsobj.AddProperty("function", frame->function()); 233 jsobj.AddProperty("line", frame->LineNumber());
211 jsobj.AddProperty("code", frame->code()); 234 jsobj.AddProperty("function", frame->function());
235 jsobj.AddProperty("code", frame->code());
236 }
212 } 237 }
238 PostReply(js);
213 } 239 }
214 240
215 241
216 static void HandleObjectHistogram(Isolate* isolate, JSONStream* js) { 242 static void HandleObjectHistogram(Isolate* isolate, JSONStream* js) {
217 ObjectHistogram* histogram = Isolate::Current()->object_histogram(); 243 ObjectHistogram* histogram = Isolate::Current()->object_histogram();
218 if (histogram == NULL) { 244 if (histogram == NULL) {
219 JSONObject jsobj(js); 245 {
220 jsobj.AddProperty("type", "Error"); 246 JSONObject jsobj(js);
221 jsobj.AddProperty("text", "Run with --print_object_histogram"); 247 jsobj.AddProperty("type", "Error");
248 jsobj.AddProperty("text", "Run with --print_object_histogram");
249 }
250 PostReply(js);
222 return; 251 return;
223 } 252 }
224 histogram->PrintToJSONStream(js); 253 histogram->PrintToJSONStream(js);
254 PostReply(js);
225 } 255 }
226 256
227 257
228 static void HandleEcho(Isolate* isolate, JSONStream* js) { 258 static void HandleIsolateEcho(Isolate* isolate, JSONStream* js) {
229 JSONObject jsobj(js); 259 {
230 jsobj.AddProperty("type", "message"); 260 JSONObject jsobj(js);
231 PrintArgumentsAndOptions(jsobj, js); 261 jsobj.AddProperty("type", "message");
262 PrintArgumentsAndOptions(jsobj, js);
263 }
264 PostReply(js);
232 } 265 }
233 266
234 267
235 // Print an error message if there is no ID argument. 268 // Print an error message if there is no ID argument.
236 #define REQUIRE_COLLECTION_ID(collection) \ 269 #define REQUIRE_COLLECTION_ID(collection) \
237 if (js->num_arguments() == 1) { \ 270 if (js->num_arguments() == 1) { \
238 PrintError(js, "Must specify collection object id: /%s/id", collection); \ 271 PrintError(js, "Must specify collection object id: /%s/id", collection); \
239 return; \ 272 return; \
240 } 273 }
241 274
242 275
243 #define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \ 276 #define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \
244 if (!GetIntegerId(arg, &id)) { \ 277 if (!GetIntegerId(arg, &id)) { \
245 PrintError(js, "Must specify collection object id: %s/id", collection); \ 278 PrintError(js, "Must specify collection object id: %s/id", collection); \
246 return; \ 279 return; \
247 } \ 280 } \
248 if ((id < 0) || (id >= length)) { \ 281 if ((id < 0) || (id >= length)) { \
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 *id = r; 325 *id = r;
293 return true; 326 return true;
294 } 327 }
295 328
296 329
297 static void HandleClassesClosures(Isolate* isolate, const Class& cls, 330 static void HandleClassesClosures(Isolate* isolate, const Class& cls,
298 JSONStream* js) { 331 JSONStream* js) {
299 intptr_t id; 332 intptr_t id;
300 if (js->num_arguments() > 4) { 333 if (js->num_arguments() > 4) {
301 PrintError(js, "Command too long"); 334 PrintError(js, "Command too long");
335 PostReply(js);
302 return; 336 return;
303 } 337 }
304 if (!GetIntegerId(js->GetArgument(3), &id)) { 338 if (!GetIntegerId(js->GetArgument(3), &id)) {
305 PrintError(js, "Must specify collection object id: closures/id"); 339 PrintError(js, "Must specify collection object id: closures/id");
340 PostReply(js);
306 return; 341 return;
307 } 342 }
308 Function& func = Function::Handle(); 343 Function& func = Function::Handle();
309 func ^= cls.ClosureFunctionFromIndex(id); 344 func ^= cls.ClosureFunctionFromIndex(id);
310 if (func.IsNull()) { 345 if (func.IsNull()) {
311 PrintError(js, "Closure function %" Pd " not found", id); 346 PrintError(js, "Closure function %" Pd " not found", id);
347 PostReply(js);
312 return; 348 return;
313 } 349 }
314 func.PrintToJSONStream(js, false); 350 func.PrintToJSONStream(js, false);
351 PostReply(js);
315 } 352 }
316 353
317 354
318 static void HandleClassesDispatchers(Isolate* isolate, const Class& cls, 355 static void HandleClassesDispatchers(Isolate* isolate, const Class& cls,
319 JSONStream* js) { 356 JSONStream* js) {
320 intptr_t id; 357 intptr_t id;
321 if (js->num_arguments() > 4) { 358 if (js->num_arguments() > 4) {
322 PrintError(js, "Command too long"); 359 PrintError(js, "Command too long");
360 PostReply(js);
323 return; 361 return;
324 } 362 }
325 if (!GetIntegerId(js->GetArgument(3), &id)) { 363 if (!GetIntegerId(js->GetArgument(3), &id)) {
326 PrintError(js, "Must specify collection object id: dispatchers/id"); 364 PrintError(js, "Must specify collection object id: dispatchers/id");
365 PostReply(js);
327 return; 366 return;
328 } 367 }
329 Function& func = Function::Handle(); 368 Function& func = Function::Handle();
330 func ^= cls.InvocationDispatcherFunctionFromIndex(id); 369 func ^= cls.InvocationDispatcherFunctionFromIndex(id);
331 if (func.IsNull()) { 370 if (func.IsNull()) {
332 PrintError(js, "Dispatcher %" Pd " not found", id); 371 PrintError(js, "Dispatcher %" Pd " not found", id);
372 PostReply(js);
333 return; 373 return;
334 } 374 }
335 func.PrintToJSONStream(js, false); 375 func.PrintToJSONStream(js, false);
376 PostReply(js);
336 } 377 }
337 378
338 379
339 static void HandleClassesFunctions(Isolate* isolate, const Class& cls, 380 static void HandleClassesFunctions(Isolate* isolate, const Class& cls,
340 JSONStream* js) { 381 JSONStream* js) {
341 intptr_t id; 382 intptr_t id;
342 if (js->num_arguments() > 4) { 383 if (js->num_arguments() > 4) {
343 PrintError(js, "Command too long"); 384 PrintError(js, "Command too long");
385 PostReply(js);
344 return; 386 return;
345 } 387 }
346 if (!GetIntegerId(js->GetArgument(3), &id)) { 388 if (!GetIntegerId(js->GetArgument(3), &id)) {
347 PrintError(js, "Must specify collection object id: functions/id"); 389 PrintError(js, "Must specify collection object id: functions/id");
390 PostReply(js);
348 return; 391 return;
349 } 392 }
350 Function& func = Function::Handle(); 393 Function& func = Function::Handle();
351 func ^= cls.FunctionFromIndex(id); 394 func ^= cls.FunctionFromIndex(id);
352 if (func.IsNull()) { 395 if (func.IsNull()) {
353 PrintError(js, "Function %" Pd " not found", id); 396 PrintError(js, "Function %" Pd " not found", id);
397 PostReply(js);
354 return; 398 return;
355 } 399 }
356 func.PrintToJSONStream(js, false); 400 func.PrintToJSONStream(js, false);
401 PostReply(js);
357 } 402 }
358 403
359 404
360 static void HandleClassesImplicitClosures(Isolate* isolate, const Class& cls, 405 static void HandleClassesImplicitClosures(Isolate* isolate, const Class& cls,
361 JSONStream* js) { 406 JSONStream* js) {
362 intptr_t id; 407 intptr_t id;
363 if (js->num_arguments() > 4) { 408 if (js->num_arguments() > 4) {
364 PrintError(js, "Command too long"); 409 PrintError(js, "Command too long");
410 PostReply(js);
365 return; 411 return;
366 } 412 }
367 if (!GetIntegerId(js->GetArgument(3), &id)) { 413 if (!GetIntegerId(js->GetArgument(3), &id)) {
368 PrintError(js, "Must specify collection object id: implicit_closures/id"); 414 PrintError(js, "Must specify collection object id: implicit_closures/id");
415 PostReply(js);
369 return; 416 return;
370 } 417 }
371 Function& func = Function::Handle(); 418 Function& func = Function::Handle();
372 func ^= cls.ImplicitClosureFunctionFromIndex(id); 419 func ^= cls.ImplicitClosureFunctionFromIndex(id);
373 if (func.IsNull()) { 420 if (func.IsNull()) {
374 PrintError(js, "Implicit closure function %" Pd " not found", id); 421 PrintError(js, "Implicit closure function %" Pd " not found", id);
422 PostReply(js);
375 return; 423 return;
376 } 424 }
377 func.PrintToJSONStream(js, false); 425 func.PrintToJSONStream(js, false);
426 PostReply(js);
378 } 427 }
379 428
380 429
381 static void HandleClassesFields(Isolate* isolate, const Class& cls, 430 static void HandleClassesFields(Isolate* isolate, const Class& cls,
382 JSONStream* js) { 431 JSONStream* js) {
383 intptr_t id; 432 intptr_t id;
384 if (js->num_arguments() > 4) { 433 if (js->num_arguments() > 4) {
385 PrintError(js, "Command too long"); 434 PrintError(js, "Command too long");
435 PostReply(js);
386 return; 436 return;
387 } 437 }
388 if (!GetIntegerId(js->GetArgument(3), &id)) { 438 if (!GetIntegerId(js->GetArgument(3), &id)) {
389 PrintError(js, "Must specify collection object id: fields/id"); 439 PrintError(js, "Must specify collection object id: fields/id");
440 PostReply(js);
390 return; 441 return;
391 } 442 }
392 Field& field = Field::Handle(cls.FieldFromIndex(id)); 443 Field& field = Field::Handle(cls.FieldFromIndex(id));
393 if (field.IsNull()) { 444 if (field.IsNull()) {
394 PrintError(js, "Field %" Pd " not found", id); 445 PrintError(js, "Field %" Pd " not found", id);
446 PostReply(js);
395 return; 447 return;
396 } 448 }
397 field.PrintToJSONStream(js, false); 449 field.PrintToJSONStream(js, false);
450 PostReply(js);
398 } 451 }
399 452
400 453
401 static void HandleClasses(Isolate* isolate, JSONStream* js) { 454 static void HandleClasses(Isolate* isolate, JSONStream* js) {
402 if (js->num_arguments() == 1) { 455 if (js->num_arguments() == 1) {
403 ClassTable* table = isolate->class_table(); 456 ClassTable* table = isolate->class_table();
404 table->PrintToJSONStream(js); 457 table->PrintToJSONStream(js);
458 PostReply(js);
405 return; 459 return;
406 } 460 }
407 ASSERT(js->num_arguments() >= 2); 461 ASSERT(js->num_arguments() >= 2);
408 intptr_t id; 462 intptr_t id;
409 if (!GetIntegerId(js->GetArgument(1), &id)) { 463 if (!GetIntegerId(js->GetArgument(1), &id)) {
410 PrintError(js, "Must specify collection object id: /classes/id"); 464 PrintError(js, "Must specify collection object id: /classes/id");
465 PostReply(js);
411 return; 466 return;
412 } 467 }
413 ClassTable* table = isolate->class_table(); 468 ClassTable* table = isolate->class_table();
414 if (!table->IsValidIndex(id)) { 469 if (!table->IsValidIndex(id)) {
415 PrintError(js, "%" Pd " is not a valid class id.", id);; 470 PrintError(js, "%" Pd " is not a valid class id.", id);;
471 PostReply(js);
416 return; 472 return;
417 } 473 }
418 Class& cls = Class::Handle(table->At(id)); 474 Class& cls = Class::Handle(table->At(id));
419 if (js->num_arguments() == 2) { 475 if (js->num_arguments() == 2) {
420 cls.PrintToJSONStream(js, false); 476 cls.PrintToJSONStream(js, false);
477 PostReply(js);
421 return; 478 return;
422 } else if (js->num_arguments() >= 3) { 479 } else if (js->num_arguments() >= 3) {
423 const char* second = js->GetArgument(2); 480 const char* second = js->GetArgument(2);
424 if (!strcmp(second, "closures")) { 481 if (!strcmp(second, "closures")) {
425 HandleClassesClosures(isolate, cls, js); 482 HandleClassesClosures(isolate, cls, js);
426 } else if (!strcmp(second, "fields")) { 483 } else if (!strcmp(second, "fields")) {
427 HandleClassesFields(isolate, cls, js); 484 HandleClassesFields(isolate, cls, js);
428 } else if (!strcmp(second, "functions")) { 485 } else if (!strcmp(second, "functions")) {
429 HandleClassesFunctions(isolate, cls, js); 486 HandleClassesFunctions(isolate, cls, js);
430 } else if (!strcmp(second, "implicit_closures")) { 487 } else if (!strcmp(second, "implicit_closures")) {
431 HandleClassesImplicitClosures(isolate, cls, js); 488 HandleClassesImplicitClosures(isolate, cls, js);
432 } else if (!strcmp(second, "dispatchers")) { 489 } else if (!strcmp(second, "dispatchers")) {
433 HandleClassesDispatchers(isolate, cls, js); 490 HandleClassesDispatchers(isolate, cls, js);
434 } else { 491 } else {
435 PrintError(js, "Invalid sub collection %s", second); 492 PrintError(js, "Invalid sub collection %s", second);
493 PostReply(js);
436 } 494 }
437 return; 495 return;
438 } 496 }
439 UNREACHABLE(); 497 UNREACHABLE();
440 } 498 }
441 499
442 500
443 static void HandleLibrary(Isolate* isolate, JSONStream* js) { 501 static void HandleLibrary(Isolate* isolate, JSONStream* js) {
444 if (js->num_arguments() == 1) { 502 if (js->num_arguments() == 1) {
445 const Library& lib = 503 const Library& lib =
446 Library::Handle(isolate->object_store()->root_library()); 504 Library::Handle(isolate->object_store()->root_library());
447 lib.PrintToJSONStream(js, false); 505 lib.PrintToJSONStream(js, false);
506 PostReply(js);
448 return; 507 return;
449 } 508 }
450 PrintGenericError(js); 509 PrintError(js, "Command too long");
510 PostReply(js);
451 } 511 }
452 512
453 513
454 static void HandleLibraries(Isolate* isolate, JSONStream* js) { 514 static void HandleLibraries(Isolate* isolate, JSONStream* js) {
455 // TODO(johnmccutchan): Support fields and functions on libraries. 515 // TODO(johnmccutchan): Support fields and functions on libraries.
456 REQUIRE_COLLECTION_ID("libraries"); 516 REQUIRE_COLLECTION_ID("libraries");
457 const GrowableObjectArray& libs = 517 const GrowableObjectArray& libs =
458 GrowableObjectArray::Handle(isolate->object_store()->libraries()); 518 GrowableObjectArray::Handle(isolate->object_store()->libraries());
459 ASSERT(!libs.IsNull()); 519 ASSERT(!libs.IsNull());
460 intptr_t id = 0; 520 intptr_t id = 0;
461 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1), 521 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1),
462 id, js); 522 id, js);
463 Library& lib = Library::Handle(); 523 Library& lib = Library::Handle();
464 lib ^= libs.At(id); 524 lib ^= libs.At(id);
465 ASSERT(!lib.IsNull()); 525 ASSERT(!lib.IsNull());
466 lib.PrintToJSONStream(js, false); 526 lib.PrintToJSONStream(js, false);
527 PostReply(js);
467 } 528 }
468 529
469 530
470 static void HandleObjects(Isolate* isolate, JSONStream* js) { 531 static void HandleObjects(Isolate* isolate, JSONStream* js) {
471 REQUIRE_COLLECTION_ID("objects"); 532 REQUIRE_COLLECTION_ID("objects");
472 ASSERT(js->num_arguments() >= 2); 533 ASSERT(js->num_arguments() >= 2);
473 ObjectIdRing* ring = isolate->object_id_ring(); 534 ObjectIdRing* ring = isolate->object_id_ring();
474 ASSERT(ring != NULL); 535 ASSERT(ring != NULL);
475 intptr_t id = -1; 536 intptr_t id = -1;
476 if (!GetIntegerId(js->GetArgument(1), &id)) { 537 if (!GetIntegerId(js->GetArgument(1), &id)) {
477 Object::null_object().PrintToJSONStream(js, false); 538 Object::null_object().PrintToJSONStream(js, false);
539 PostReply(js);
478 return; 540 return;
479 } 541 }
480 Object& obj = Object::Handle(ring->GetObjectForId(id)); 542 Object& obj = Object::Handle(ring->GetObjectForId(id));
481 obj.PrintToJSONStream(js, false); 543 obj.PrintToJSONStream(js, false);
544 PostReply(js);
482 } 545 }
483 546
484 547
485 548
486 static void HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) { 549 static void HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) {
487 JSONObject jsobj(js);
488 jsobj.AddProperty("type", "ScriptList");
489 { 550 {
551 JSONObject jsobj(js);
552 jsobj.AddProperty("type", "ScriptList");
490 JSONArray members(&jsobj, "members"); 553 JSONArray members(&jsobj, "members");
491 const GrowableObjectArray& libs = 554 const GrowableObjectArray& libs =
492 GrowableObjectArray::Handle(isolate->object_store()->libraries()); 555 GrowableObjectArray::Handle(isolate->object_store()->libraries());
493 int num_libs = libs.Length(); 556 int num_libs = libs.Length();
494 Library &lib = Library::Handle(); 557 Library &lib = Library::Handle();
495 Script& script = Script::Handle(); 558 Script& script = Script::Handle();
496 for (intptr_t i = 0; i < num_libs; i++) { 559 for (intptr_t i = 0; i < num_libs; i++) {
497 lib ^= libs.At(i); 560 lib ^= libs.At(i);
498 ASSERT(!lib.IsNull()); 561 ASSERT(!lib.IsNull());
499 ASSERT(Smi::IsValid(lib.index())); 562 ASSERT(Smi::IsValid(lib.index()));
500 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts()); 563 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
501 ASSERT(!loaded_scripts.IsNull()); 564 ASSERT(!loaded_scripts.IsNull());
502 intptr_t num_scripts = loaded_scripts.Length(); 565 intptr_t num_scripts = loaded_scripts.Length();
503 for (intptr_t i = 0; i < num_scripts; i++) { 566 for (intptr_t i = 0; i < num_scripts; i++) {
504 script ^= loaded_scripts.At(i); 567 script ^= loaded_scripts.At(i);
505 members.AddValue(script); 568 members.AddValue(script);
506 } 569 }
507 } 570 }
508 } 571 }
572 PostReply(js);
509 } 573 }
510 574
511 575
512 static void HandleScriptsFetch(Isolate* isolate, JSONStream* js) { 576 static void HandleScriptsFetch(Isolate* isolate, JSONStream* js) {
513 const GrowableObjectArray& libs = 577 const GrowableObjectArray& libs =
514 GrowableObjectArray::Handle(isolate->object_store()->libraries()); 578 GrowableObjectArray::Handle(isolate->object_store()->libraries());
515 int num_libs = libs.Length(); 579 int num_libs = libs.Length();
516 Library &lib = Library::Handle(); 580 Library &lib = Library::Handle();
517 Script& script = Script::Handle(); 581 Script& script = Script::Handle();
518 String& url = String::Handle(); 582 String& url = String::Handle();
519 const String& id = String::Handle(String::New(js->GetArgument(1))); 583 const String& id = String::Handle(String::New(js->GetArgument(1)));
520 ASSERT(!id.IsNull()); 584 ASSERT(!id.IsNull());
521 // The id is the url of the script % encoded, decode it. 585 // The id is the url of the script % encoded, decode it.
522 String& requested_url = String::Handle(String::DecodeURI(id)); 586 String& requested_url = String::Handle(String::DecodeURI(id));
523 for (intptr_t i = 0; i < num_libs; i++) { 587 for (intptr_t i = 0; i < num_libs; i++) {
524 lib ^= libs.At(i); 588 lib ^= libs.At(i);
525 ASSERT(!lib.IsNull()); 589 ASSERT(!lib.IsNull());
526 ASSERT(Smi::IsValid(lib.index())); 590 ASSERT(Smi::IsValid(lib.index()));
527 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts()); 591 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
528 ASSERT(!loaded_scripts.IsNull()); 592 ASSERT(!loaded_scripts.IsNull());
529 intptr_t num_scripts = loaded_scripts.Length(); 593 intptr_t num_scripts = loaded_scripts.Length();
530 for (intptr_t i = 0; i < num_scripts; i++) { 594 for (intptr_t i = 0; i < num_scripts; i++) {
531 script ^= loaded_scripts.At(i); 595 script ^= loaded_scripts.At(i);
532 ASSERT(!script.IsNull()); 596 ASSERT(!script.IsNull());
533 url ^= script.url(); 597 url ^= script.url();
534 if (url.Equals(requested_url)) { 598 if (url.Equals(requested_url)) {
535 script.PrintToJSONStream(js, false); 599 script.PrintToJSONStream(js, false);
600 PostReply(js);
536 return; 601 return;
537 } 602 }
538 } 603 }
539 } 604 }
540 PrintError(js, "Cannot find script %s\n", requested_url.ToCString()); 605 PrintError(js, "Cannot find script %s\n", requested_url.ToCString());
606 PostReply(js);
541 } 607 }
542 608
543 609
544 static void HandleScripts(Isolate* isolate, JSONStream* js) { 610 static void HandleScripts(Isolate* isolate, JSONStream* js) {
545 if (js->num_arguments() == 1) { 611 if (js->num_arguments() == 1) {
546 // Enumerate all scripts. 612 // Enumerate all scripts.
547 HandleScriptsEnumerate(isolate, js); 613 HandleScriptsEnumerate(isolate, js);
548 } else if (js->num_arguments() == 2) { 614 } else if (js->num_arguments() == 2) {
549 // Fetch specific script. 615 // Fetch specific script.
550 HandleScriptsFetch(isolate, js); 616 HandleScriptsFetch(isolate, js);
551 } else { 617 } else {
552 PrintError(js, "Command too long"); 618 PrintError(js, "Command too long");
619 PostReply(js);
553 } 620 }
554 } 621 }
555 622
556 623
557 static void HandleDebug(Isolate* isolate, JSONStream* js) { 624 static void HandleDebug(Isolate* isolate, JSONStream* js) {
558 if (js->num_arguments() == 1) { 625 if (js->num_arguments() == 1) {
559 PrintError(js, "Must specify a subcommand"); 626 PrintError(js, "Must specify a subcommand");
627 PostReply(js);
560 return; 628 return;
561 } 629 }
562 const char* command = js->GetArgument(1); 630 const char* command = js->GetArgument(1);
563 if (!strcmp(command, "breakpoints")) { 631 if (!strcmp(command, "breakpoints")) {
564 if (js->num_arguments() == 2) { 632 if (js->num_arguments() == 2) {
565 // Print breakpoint list. 633 // Print breakpoint list.
566 JSONObject jsobj(js); 634 {
567 jsobj.AddProperty("type", "BreakpointList"); 635 JSONObject jsobj(js);
568 JSONArray jsarr(&jsobj, "breakpoints"); 636 jsobj.AddProperty("type", "BreakpointList");
569 isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr); 637 JSONArray jsarr(&jsobj, "breakpoints");
570 638 isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr);
639 }
640 PostReply(js);
641 return;
571 } else if (js->num_arguments() == 3) { 642 } else if (js->num_arguments() == 3) {
572 // Print individual breakpoint. 643 // Print individual breakpoint.
573 intptr_t id = 0; 644 intptr_t id = 0;
574 SourceBreakpoint* bpt = NULL; 645 SourceBreakpoint* bpt = NULL;
575 if (GetIntegerId(js->GetArgument(2), &id)) { 646 if (GetIntegerId(js->GetArgument(2), &id)) {
576 bpt = isolate->debugger()->GetBreakpointById(id); 647 bpt = isolate->debugger()->GetBreakpointById(id);
577 } 648 }
578 if (bpt != NULL) { 649 if (bpt != NULL) {
579 bpt->PrintToJSONStream(js); 650 bpt->PrintToJSONStream(js);
651 PostReply(js);
652 return;
580 } else { 653 } else {
581 PrintError(js, "Unrecognized breakpoint id %s", js->GetArgument(2)); 654 PrintError(js, "Unrecognized breakpoint id %s", js->GetArgument(2));
655 PostReply(js);
656 return;
582 } 657 }
583
584 } else { 658 } else {
585 PrintError(js, "Command too long"); 659 PrintError(js, "Command too long");
660 PostReply(js);
661 return;
586 } 662 }
587 } else { 663 } else {
588 PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1)); 664 PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1));
665 PostReply(js);
666 return;
589 } 667 }
590 } 668 }
591 669
592 670
593 static void HandleCpu(Isolate* isolate, JSONStream* js) {
594 JSONObject jsobj(js);
595 jsobj.AddProperty("type", "CPU");
596 jsobj.AddProperty("architecture", CPU::Id());
597 }
598
599
600 static void HandleCode(Isolate* isolate, JSONStream* js) { 671 static void HandleCode(Isolate* isolate, JSONStream* js) {
601 REQUIRE_COLLECTION_ID("code"); 672 REQUIRE_COLLECTION_ID("code");
602 uintptr_t pc; 673 uintptr_t pc;
603 if (!GetUnsignedIntegerId(js->GetArgument(1), &pc, 16)) { 674 if (!GetUnsignedIntegerId(js->GetArgument(1), &pc, 16)) {
604 PrintError(js, "Must specify code address: code/c0deadd0."); 675 PrintError(js, "Must specify code address: code/c0deadd0.");
676 PostReply(js);
605 return; 677 return;
606 } 678 }
607 Code& code = Code::Handle(Code::LookupCode(pc)); 679 Code& code = Code::Handle(Code::LookupCode(pc));
608 if (code.IsNull()) { 680 if (code.IsNull()) {
609 PrintError(js, "Could not find code at %" Px "", pc); 681 PrintError(js, "Could not find code at %" Px "", pc);
682 PostReply(js);
610 return; 683 return;
611 } 684 }
612 code.PrintToJSONStream(js, false); 685 code.PrintToJSONStream(js, false);
686 PostReply(js);
613 } 687 }
614 688
615 689
616 static void HandleProfile(Isolate* isolate, JSONStream* js) { 690 static void HandleProfile(Isolate* isolate, JSONStream* js) {
617 Profiler::PrintToJSONStream(isolate, js, true); 691 Profiler::PrintToJSONStream(isolate, js, true);
692 PostReply(js);
618 } 693 }
619 694
620 695
621 static ServiceMessageHandlerEntry __message_handlers[] = { 696 static IsolateMessageHandlerEntry isolate_handlers[] = {
622 { "_echo", HandleEcho }, 697 { "_echo", HandleIsolateEcho },
623 { "classes", HandleClasses }, 698 { "classes", HandleClasses },
624 { "code", HandleCode }, 699 { "code", HandleCode },
625 { "cpu", HandleCpu },
626 { "debug", HandleDebug }, 700 { "debug", HandleDebug },
627 { "libraries", HandleLibraries }, 701 { "libraries", HandleLibraries },
628 { "library", HandleLibrary }, 702 { "library", HandleLibrary },
629 { "name", HandleName }, 703 { "name", HandleName },
630 { "objecthistogram", HandleObjectHistogram}, 704 { "objecthistogram", HandleObjectHistogram},
631 { "objects", HandleObjects }, 705 { "objects", HandleObjects },
632 { "profile", HandleProfile }, 706 { "profile", HandleProfile },
633 { "scripts", HandleScripts }, 707 { "scripts", HandleScripts },
634 { "stacktrace", HandleStackTrace }, 708 { "stacktrace", HandleStackTrace },
635 }; 709 };
636 710
637 711
638 static void HandleFallthrough(Isolate* isolate, JSONStream* js) { 712 static IsolateMessageHandler FindIsolateMessageHandler(const char* command) {
639 JSONObject jsobj(js); 713 intptr_t num_message_handlers = sizeof(isolate_handlers) /
640 jsobj.AddProperty("type", "Error"); 714 sizeof(isolate_handlers[0]);
641 jsobj.AddProperty("text", "request not understood.");
642 PrintArgumentsAndOptions(jsobj, js);
643 }
644
645
646 static ServiceMessageHandler FindServiceMessageHandler(const char* command) {
647 intptr_t num_message_handlers = sizeof(__message_handlers) /
648 sizeof(__message_handlers[0]);
649 for (intptr_t i = 0; i < num_message_handlers; i++) { 715 for (intptr_t i = 0; i < num_message_handlers; i++) {
650 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; 716 const IsolateMessageHandlerEntry& entry = isolate_handlers[i];
651 if (!strcmp(command, entry.command)) { 717 if (!strcmp(command, entry.command)) {
652 return entry.handler; 718 return entry.handler;
653 } 719 }
654 } 720 }
655 return HandleFallthrough; 721 return NULL;
722 }
723
724
725 void Service::HandleRootMessage(const Instance& msg) {
726 Isolate* isolate = Isolate::Current();
727 ASSERT(!msg.IsNull());
728 ASSERT(msg.IsGrowableObjectArray());
729
730 {
731 StackZone zone(isolate);
732 HANDLESCOPE(isolate);
733
734 const GrowableObjectArray& message = GrowableObjectArray::Cast(msg);
735 // Message is a list with four entries.
736 ASSERT(message.Length() == 4);
737
738 Instance& reply_port = Instance::Handle(isolate);
739 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
740 GrowableObjectArray& option_keys = GrowableObjectArray::Handle(isolate);
741 GrowableObjectArray& option_values = GrowableObjectArray::Handle(isolate);
742 reply_port ^= message.At(0);
743 path ^= message.At(1);
744 option_keys ^= message.At(2);
745 option_values ^= message.At(3);
746
747 ASSERT(!path.IsNull());
748 ASSERT(!option_keys.IsNull());
749 ASSERT(!option_values.IsNull());
750 // Path always has at least one entry in it.
751 ASSERT(path.Length() > 0);
752 // Same number of option keys as values.
753 ASSERT(option_keys.Length() == option_values.Length());
754
755 String& pathSegment = String::Handle();
756 pathSegment ^= path.At(0);
757 ASSERT(!pathSegment.IsNull());
758
759 RootMessageHandler handler =
760 FindRootMessageHandler(pathSegment.ToCString());
761 {
762 JSONStream js;
763 SetupJSONStream(&js, zone.GetZone(),
764 reply_port, path, option_keys, option_values);
765 if (handler == NULL) {
766 PrintError(&js, "Unrecognized path");
767 PostReply(&js);
768 } else {
769 handler(&js);
770 }
771 }
772 }
773 }
774
775
776 static void HandleRootEcho(JSONStream* js) {
777 {
778 JSONObject jsobj(js);
779 jsobj.AddProperty("type", "message");
780 PrintArgumentsAndOptions(jsobj, js);
781 }
782 PostReply(js);
783 }
784
785
786 static void HandleCpu(JSONStream* js) {
787 {
788 JSONObject jsobj(js);
789 jsobj.AddProperty("type", "CPU");
790 jsobj.AddProperty("architecture", CPU::Id());
791 }
792 PostReply(js);
793 }
794
795
796 static RootMessageHandlerEntry root_handlers[] = {
797 { "_echo", HandleRootEcho },
798 { "cpu", HandleCpu },
799 };
800
801
802 static RootMessageHandler FindRootMessageHandler(const char* command) {
803 intptr_t num_message_handlers = sizeof(root_handlers) /
804 sizeof(root_handlers[0]);
805 for (intptr_t i = 0; i < num_message_handlers; i++) {
806 const RootMessageHandlerEntry& entry = root_handlers[i];
807 if (!strcmp(command, entry.command)) {
808 return entry.handler;
809 }
810 }
811 return NULL;
656 } 812 }
657 813
658 } // namespace dart 814 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698