OLD | NEW |
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 | 18 |
18 namespace dart { | 19 namespace dart { |
19 | 20 |
20 typedef void (*ServiceMessageHandler)(Isolate* isolate, JSONStream* stream); | 21 typedef void (*ServiceMessageHandler)(Isolate* isolate, JSONStream* stream); |
21 | 22 |
22 struct ServiceMessageHandlerEntry { | 23 struct ServiceMessageHandlerEntry { |
23 const char* command; | 24 const char* command; |
24 ServiceMessageHandler handler; | 25 ServiceMessageHandler handler; |
25 }; | 26 }; |
26 | 27 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 jsobj.AddProperty("name", isolate->name()); | 190 jsobj.AddProperty("name", isolate->name()); |
190 } | 191 } |
191 | 192 |
192 | 193 |
193 static void HandleStackTrace(Isolate* isolate, JSONStream* js) { | 194 static void HandleStackTrace(Isolate* isolate, JSONStream* js) { |
194 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); | 195 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); |
195 JSONObject jsobj(js); | 196 JSONObject jsobj(js); |
196 jsobj.AddProperty("type", "StackTrace"); | 197 jsobj.AddProperty("type", "StackTrace"); |
197 JSONArray jsarr(&jsobj, "members"); | 198 JSONArray jsarr(&jsobj, "members"); |
198 intptr_t n_frames = stack->Length(); | 199 intptr_t n_frames = stack->Length(); |
199 String& url = String::Handle(); | |
200 String& function = String::Handle(); | 200 String& function = String::Handle(); |
| 201 Script& script = Script::Handle(); |
201 for (int i = 0; i < n_frames; i++) { | 202 for (int i = 0; i < n_frames; i++) { |
202 ActivationFrame* frame = stack->FrameAt(i); | 203 ActivationFrame* frame = stack->FrameAt(i); |
203 url ^= frame->SourceUrl(); | 204 script ^= frame->SourceScript(); |
204 function ^= frame->function().UserVisibleName(); | 205 function ^= frame->function().UserVisibleName(); |
205 JSONObject jsobj(&jsarr); | 206 JSONObject jsobj(&jsarr); |
206 jsobj.AddProperty("name", function.ToCString()); | 207 jsobj.AddProperty("name", function.ToCString()); |
207 jsobj.AddProperty("url", url.ToCString()); | 208 jsobj.AddProperty("script", script); |
208 jsobj.AddProperty("line", frame->LineNumber()); | 209 jsobj.AddProperty("line", frame->LineNumber()); |
209 jsobj.AddProperty("function", frame->function()); | 210 jsobj.AddProperty("function", frame->function()); |
210 jsobj.AddProperty("code", frame->code()); | 211 jsobj.AddProperty("code", frame->code()); |
211 } | 212 } |
212 } | 213 } |
213 | 214 |
214 | 215 |
215 static void HandleObjectHistogram(Isolate* isolate, JSONStream* js) { | 216 static void HandleObjectHistogram(Isolate* isolate, JSONStream* js) { |
216 ObjectHistogram* histogram = Isolate::Current()->object_histogram(); | 217 ObjectHistogram* histogram = Isolate::Current()->object_histogram(); |
217 if (histogram == NULL) { | 218 if (histogram == NULL) { |
(...skipping 14 matching lines...) Expand all Loading... |
232 | 233 |
233 | 234 |
234 // Print an error message if there is no ID argument. | 235 // Print an error message if there is no ID argument. |
235 #define REQUIRE_COLLECTION_ID(collection) \ | 236 #define REQUIRE_COLLECTION_ID(collection) \ |
236 if (js->num_arguments() == 1) { \ | 237 if (js->num_arguments() == 1) { \ |
237 PrintError(js, "Must specify collection object id: /%s/id", collection); \ | 238 PrintError(js, "Must specify collection object id: /%s/id", collection); \ |
238 return; \ | 239 return; \ |
239 } | 240 } |
240 | 241 |
241 | 242 |
| 243 #define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \ |
| 244 if (!GetIntegerId(arg, &id)) { \ |
| 245 PrintError(js, "Must specify collection object id: %s/id", collection); \ |
| 246 return; \ |
| 247 } \ |
| 248 if ((id < 0) || (id >= length)) { \ |
| 249 PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \ |
| 250 length); \ |
| 251 return; \ |
| 252 } |
| 253 |
| 254 |
| 255 static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) { |
| 256 if ((s == NULL) || (*s == '\0')) { |
| 257 // Empty string. |
| 258 return false; |
| 259 } |
| 260 if (id == NULL) { |
| 261 // No id pointer. |
| 262 return false; |
| 263 } |
| 264 intptr_t r = 0; |
| 265 char* end_ptr = NULL; |
| 266 r = strtol(s, &end_ptr, base); |
| 267 if (end_ptr == s) { |
| 268 // String was not advanced at all, cannot be valid. |
| 269 return false; |
| 270 } |
| 271 *id = r; |
| 272 return true; |
| 273 } |
| 274 |
| 275 |
| 276 static bool GetUnsignedIntegerId(const char* s, uintptr_t* id, int base = 10) { |
| 277 if ((s == NULL) || (*s == '\0')) { |
| 278 // Empty string. |
| 279 return false; |
| 280 } |
| 281 if (id == NULL) { |
| 282 // No id pointer. |
| 283 return false; |
| 284 } |
| 285 uintptr_t r = 0; |
| 286 char* end_ptr = NULL; |
| 287 r = strtoul(s, &end_ptr, base); |
| 288 if (end_ptr == s) { |
| 289 // String was not advanced at all, cannot be valid. |
| 290 return false; |
| 291 } |
| 292 *id = r; |
| 293 return true; |
| 294 } |
| 295 |
| 296 |
| 297 static void HandleClassesClosures(Isolate* isolate, const Class& cls, |
| 298 JSONStream* js) { |
| 299 intptr_t id; |
| 300 if (js->num_arguments() > 4) { |
| 301 PrintError(js, "Command too long"); |
| 302 return; |
| 303 } |
| 304 if (!GetIntegerId(js->GetArgument(3), &id)) { |
| 305 PrintError(js, "Must specify collection object id: closures/id"); |
| 306 return; |
| 307 } |
| 308 Function& func = Function::Handle(); |
| 309 func ^= cls.ClosureFunctionFromIndex(id); |
| 310 if (func.IsNull()) { |
| 311 PrintError(js, "Closure function %" Pd " not found", id); |
| 312 return; |
| 313 } |
| 314 func.PrintToJSONStream(js, false); |
| 315 } |
| 316 |
| 317 |
| 318 static void HandleClassesDispatchers(Isolate* isolate, const Class& cls, |
| 319 JSONStream* js) { |
| 320 intptr_t id; |
| 321 if (js->num_arguments() > 4) { |
| 322 PrintError(js, "Command too long"); |
| 323 return; |
| 324 } |
| 325 if (!GetIntegerId(js->GetArgument(3), &id)) { |
| 326 PrintError(js, "Must specify collection object id: dispatchers/id"); |
| 327 return; |
| 328 } |
| 329 Function& func = Function::Handle(); |
| 330 func ^= cls.InvocationDispatcherFunctionFromIndex(id); |
| 331 if (func.IsNull()) { |
| 332 PrintError(js, "Dispatcher %" Pd " not found", id); |
| 333 return; |
| 334 } |
| 335 func.PrintToJSONStream(js, false); |
| 336 } |
| 337 |
| 338 |
| 339 static void HandleClassesFunctions(Isolate* isolate, const Class& cls, |
| 340 JSONStream* js) { |
| 341 intptr_t id; |
| 342 if (js->num_arguments() > 4) { |
| 343 PrintError(js, "Command too long"); |
| 344 return; |
| 345 } |
| 346 if (!GetIntegerId(js->GetArgument(3), &id)) { |
| 347 PrintError(js, "Must specify collection object id: functions/id"); |
| 348 return; |
| 349 } |
| 350 Function& func = Function::Handle(); |
| 351 func ^= cls.FunctionFromIndex(id); |
| 352 if (func.IsNull()) { |
| 353 PrintError(js, "Function %" Pd " not found", id); |
| 354 return; |
| 355 } |
| 356 func.PrintToJSONStream(js, false); |
| 357 } |
| 358 |
| 359 |
| 360 static void HandleClassesImplicitClosures(Isolate* isolate, const Class& cls, |
| 361 JSONStream* js) { |
| 362 intptr_t id; |
| 363 if (js->num_arguments() > 4) { |
| 364 PrintError(js, "Command too long"); |
| 365 return; |
| 366 } |
| 367 if (!GetIntegerId(js->GetArgument(3), &id)) { |
| 368 PrintError(js, "Must specify collection object id: implicit_closures/id"); |
| 369 return; |
| 370 } |
| 371 Function& func = Function::Handle(); |
| 372 func ^= cls.ImplicitClosureFunctionFromIndex(id); |
| 373 if (func.IsNull()) { |
| 374 PrintError(js, "Implicit closure function %" Pd " not found", id); |
| 375 return; |
| 376 } |
| 377 func.PrintToJSONStream(js, false); |
| 378 } |
| 379 |
| 380 |
| 381 static void HandleClassesFields(Isolate* isolate, const Class& cls, |
| 382 JSONStream* js) { |
| 383 intptr_t id; |
| 384 if (js->num_arguments() > 4) { |
| 385 PrintError(js, "Command too long"); |
| 386 return; |
| 387 } |
| 388 if (!GetIntegerId(js->GetArgument(3), &id)) { |
| 389 PrintError(js, "Must specify collection object id: fields/id"); |
| 390 return; |
| 391 } |
| 392 Field& field = Field::Handle(cls.FieldFromIndex(id)); |
| 393 if (field.IsNull()) { |
| 394 PrintError(js, "Field %" Pd " not found", id); |
| 395 return; |
| 396 } |
| 397 field.PrintToJSONStream(js, false); |
| 398 } |
| 399 |
| 400 |
242 static void HandleClasses(Isolate* isolate, JSONStream* js) { | 401 static void HandleClasses(Isolate* isolate, JSONStream* js) { |
243 if (js->num_arguments() == 1) { | 402 if (js->num_arguments() == 1) { |
244 ClassTable* table = isolate->class_table(); | 403 ClassTable* table = isolate->class_table(); |
245 table->PrintToJSONStream(js); | 404 table->PrintToJSONStream(js); |
246 return; | 405 return; |
247 } | 406 } |
248 ASSERT(js->num_arguments() >= 2); | 407 ASSERT(js->num_arguments() >= 2); |
249 intptr_t id = atoi(js->GetArgument(1)); | 408 intptr_t id; |
| 409 if (!GetIntegerId(js->GetArgument(1), &id)) { |
| 410 PrintError(js, "Must specify collection object id: /classes/id"); |
| 411 return; |
| 412 } |
250 ClassTable* table = isolate->class_table(); | 413 ClassTable* table = isolate->class_table(); |
251 if (!table->IsValidIndex(id)) { | 414 if (!table->IsValidIndex(id)) { |
252 Object::null_object().PrintToJSONStream(js, false); | 415 PrintError(js, "%" Pd " is not a valid class id.", id);; |
253 } else { | 416 return; |
254 Class& cls = Class::Handle(table->At(id)); | 417 } |
| 418 Class& cls = Class::Handle(table->At(id)); |
| 419 if (js->num_arguments() == 2) { |
255 cls.PrintToJSONStream(js, false); | 420 cls.PrintToJSONStream(js, false); |
| 421 return; |
| 422 } else if (js->num_arguments() >= 3) { |
| 423 const char* second = js->GetArgument(2); |
| 424 if (!strcmp(second, "closures")) { |
| 425 HandleClassesClosures(isolate, cls, js); |
| 426 } else if (!strcmp(second, "fields")) { |
| 427 HandleClassesFields(isolate, cls, js); |
| 428 } else if (!strcmp(second, "functions")) { |
| 429 HandleClassesFunctions(isolate, cls, js); |
| 430 } else if (!strcmp(second, "implicit_closures")) { |
| 431 HandleClassesImplicitClosures(isolate, cls, js); |
| 432 } else if (!strcmp(second, "dispatchers")) { |
| 433 HandleClassesDispatchers(isolate, cls, js); |
| 434 } else { |
| 435 PrintError(js, "Invalid sub collection %s", second); |
| 436 } |
| 437 return; |
256 } | 438 } |
| 439 UNREACHABLE(); |
257 } | 440 } |
258 | 441 |
259 | 442 |
260 static void HandleLibrary(Isolate* isolate, JSONStream* js) { | 443 static void HandleLibrary(Isolate* isolate, JSONStream* js) { |
261 if (js->num_arguments() == 1) { | 444 if (js->num_arguments() == 1) { |
262 const Library& lib = | 445 const Library& lib = |
263 Library::Handle(isolate->object_store()->root_library()); | 446 Library::Handle(isolate->object_store()->root_library()); |
264 lib.PrintToJSONStream(js, false); | 447 lib.PrintToJSONStream(js, false); |
265 return; | 448 return; |
266 } | 449 } |
267 PrintGenericError(js); | 450 PrintGenericError(js); |
268 } | 451 } |
269 | 452 |
270 | 453 |
| 454 static void HandleLibraries(Isolate* isolate, JSONStream* js) { |
| 455 // TODO(johnmccutchan): Support fields and functions on libraries. |
| 456 REQUIRE_COLLECTION_ID("libraries"); |
| 457 const GrowableObjectArray& libs = |
| 458 GrowableObjectArray::Handle(isolate->object_store()->libraries()); |
| 459 ASSERT(!libs.IsNull()); |
| 460 intptr_t id = 0; |
| 461 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1), |
| 462 id, js); |
| 463 Library& lib = Library::Handle(); |
| 464 lib ^= libs.At(id); |
| 465 ASSERT(!lib.IsNull()); |
| 466 lib.PrintToJSONStream(js, false); |
| 467 } |
| 468 |
| 469 |
271 static void HandleObjects(Isolate* isolate, JSONStream* js) { | 470 static void HandleObjects(Isolate* isolate, JSONStream* js) { |
272 REQUIRE_COLLECTION_ID("objects"); | 471 REQUIRE_COLLECTION_ID("objects"); |
273 ASSERT(js->num_arguments() >= 2); | 472 ASSERT(js->num_arguments() >= 2); |
274 ObjectIdRing* ring = isolate->object_id_ring(); | 473 ObjectIdRing* ring = isolate->object_id_ring(); |
275 ASSERT(ring != NULL); | 474 ASSERT(ring != NULL); |
276 intptr_t id = atoi(js->GetArgument(1)); | 475 intptr_t id = -1; |
| 476 if (!GetIntegerId(js->GetArgument(1), &id)) { |
| 477 Object::null_object().PrintToJSONStream(js, false); |
| 478 return; |
| 479 } |
277 Object& obj = Object::Handle(ring->GetObjectForId(id)); | 480 Object& obj = Object::Handle(ring->GetObjectForId(id)); |
278 obj.PrintToJSONStream(js, false); | 481 obj.PrintToJSONStream(js, false); |
279 } | 482 } |
280 | 483 |
281 | 484 |
| 485 |
| 486 static void HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) { |
| 487 JSONObject jsobj(js); |
| 488 jsobj.AddProperty("type", "ScriptList"); |
| 489 { |
| 490 JSONArray members(&jsobj, "members"); |
| 491 const GrowableObjectArray& libs = |
| 492 GrowableObjectArray::Handle(isolate->object_store()->libraries()); |
| 493 int num_libs = libs.Length(); |
| 494 Library &lib = Library::Handle(); |
| 495 Script& script = Script::Handle(); |
| 496 for (intptr_t i = 0; i < num_libs; i++) { |
| 497 lib ^= libs.At(i); |
| 498 ASSERT(!lib.IsNull()); |
| 499 ASSERT(Smi::IsValid(lib.index())); |
| 500 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts()); |
| 501 ASSERT(!loaded_scripts.IsNull()); |
| 502 intptr_t num_scripts = loaded_scripts.Length(); |
| 503 for (intptr_t i = 0; i < num_scripts; i++) { |
| 504 script ^= loaded_scripts.At(i); |
| 505 members.AddValue(script); |
| 506 } |
| 507 } |
| 508 } |
| 509 } |
| 510 |
| 511 |
| 512 static void HandleScriptsFetch(Isolate* isolate, JSONStream* js) { |
| 513 const GrowableObjectArray& libs = |
| 514 GrowableObjectArray::Handle(isolate->object_store()->libraries()); |
| 515 int num_libs = libs.Length(); |
| 516 Library &lib = Library::Handle(); |
| 517 Script& script = Script::Handle(); |
| 518 String& url = String::Handle(); |
| 519 const String& id = String::Handle(String::New(js->GetArgument(1))); |
| 520 ASSERT(!id.IsNull()); |
| 521 // The id is the url of the script % encoded, decode it. |
| 522 String& requested_url = String::Handle(String::DecodeURI(id)); |
| 523 for (intptr_t i = 0; i < num_libs; i++) { |
| 524 lib ^= libs.At(i); |
| 525 ASSERT(!lib.IsNull()); |
| 526 ASSERT(Smi::IsValid(lib.index())); |
| 527 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts()); |
| 528 ASSERT(!loaded_scripts.IsNull()); |
| 529 intptr_t num_scripts = loaded_scripts.Length(); |
| 530 for (intptr_t i = 0; i < num_scripts; i++) { |
| 531 script ^= loaded_scripts.At(i); |
| 532 ASSERT(!script.IsNull()); |
| 533 url ^= script.url(); |
| 534 if (url.Equals(requested_url)) { |
| 535 script.PrintToJSONStream(js, false); |
| 536 return; |
| 537 } |
| 538 } |
| 539 } |
| 540 PrintError(js, "Cannot find script %s\n", requested_url.ToCString()); |
| 541 } |
| 542 |
| 543 |
| 544 static void HandleScripts(Isolate* isolate, JSONStream* js) { |
| 545 if (js->num_arguments() == 1) { |
| 546 // Enumerate all scripts. |
| 547 HandleScriptsEnumerate(isolate, js); |
| 548 } else if (js->num_arguments() == 2) { |
| 549 // Fetch specific script. |
| 550 HandleScriptsFetch(isolate, js); |
| 551 } else { |
| 552 PrintError(js, "Command too long"); |
| 553 } |
| 554 } |
| 555 |
| 556 |
282 static void HandleDebug(Isolate* isolate, JSONStream* js) { | 557 static void HandleDebug(Isolate* isolate, JSONStream* js) { |
283 if (js->num_arguments() == 1) { | 558 if (js->num_arguments() == 1) { |
284 PrintError(js, "Must specify a subcommand"); | 559 PrintError(js, "Must specify a subcommand"); |
285 return; | 560 return; |
286 } | 561 } |
287 const char* command = js->GetArgument(1); | 562 const char* command = js->GetArgument(1); |
288 if (!strcmp(command, "breakpoints")) { | 563 if (!strcmp(command, "breakpoints")) { |
289 if (js->num_arguments() == 2) { | 564 if (js->num_arguments() == 2) { |
290 // Print breakpoint list. | 565 // Print breakpoint list. |
291 JSONObject jsobj(js); | 566 JSONObject jsobj(js); |
292 jsobj.AddProperty("type", "BreakpointList"); | 567 jsobj.AddProperty("type", "BreakpointList"); |
293 JSONArray jsarr(&jsobj, "breakpoints"); | 568 JSONArray jsarr(&jsobj, "breakpoints"); |
294 isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr); | 569 isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr); |
295 | 570 |
296 } else if (js->num_arguments() == 3) { | 571 } else if (js->num_arguments() == 3) { |
297 // Print individual breakpoint. | 572 // Print individual breakpoint. |
298 intptr_t id = atoi(js->GetArgument(2)); | 573 intptr_t id = 0; |
299 SourceBreakpoint* bpt = isolate->debugger()->GetBreakpointById(id); | 574 SourceBreakpoint* bpt = NULL; |
| 575 if (GetIntegerId(js->GetArgument(2), &id)) { |
| 576 bpt = isolate->debugger()->GetBreakpointById(id); |
| 577 } |
300 if (bpt != NULL) { | 578 if (bpt != NULL) { |
301 bpt->PrintToJSONStream(js); | 579 bpt->PrintToJSONStream(js); |
302 } else { | 580 } else { |
303 PrintError(js, "Unrecognized breakpoint id %s", js->GetArgument(2)); | 581 PrintError(js, "Unrecognized breakpoint id %s", js->GetArgument(2)); |
304 } | 582 } |
305 | 583 |
306 } else { | 584 } else { |
307 PrintError(js, "Command too long"); | 585 PrintError(js, "Command too long"); |
308 } | 586 } |
309 } else { | 587 } else { |
310 PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1)); | 588 PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1)); |
311 } | 589 } |
312 } | 590 } |
313 | 591 |
314 | 592 |
315 static void HandleCpu(Isolate* isolate, JSONStream* js) { | 593 static void HandleCpu(Isolate* isolate, JSONStream* js) { |
316 JSONObject jsobj(js); | 594 JSONObject jsobj(js); |
317 jsobj.AddProperty("type", "CPU"); | 595 jsobj.AddProperty("type", "CPU"); |
318 jsobj.AddProperty("architecture", CPU::Id()); | 596 jsobj.AddProperty("architecture", CPU::Id()); |
319 } | 597 } |
320 | 598 |
321 | 599 |
| 600 static void HandleCode(Isolate* isolate, JSONStream* js) { |
| 601 REQUIRE_COLLECTION_ID("code"); |
| 602 uintptr_t pc; |
| 603 if (!GetUnsignedIntegerId(js->GetArgument(1), &pc, 16)) { |
| 604 PrintError(js, "Must specify code address: code/c0deadd0."); |
| 605 return; |
| 606 } |
| 607 Code& code = Code::Handle(Code::LookupCode(pc)); |
| 608 if (code.IsNull()) { |
| 609 PrintError(js, "Could not find code at %" Px "", pc); |
| 610 return; |
| 611 } |
| 612 code.PrintToJSONStream(js, false); |
| 613 } |
| 614 |
| 615 |
| 616 static void HandleProfile(Isolate* isolate, JSONStream* js) { |
| 617 Profiler::PrintToJSONStream(isolate, js, true); |
| 618 } |
| 619 |
| 620 |
322 static ServiceMessageHandlerEntry __message_handlers[] = { | 621 static ServiceMessageHandlerEntry __message_handlers[] = { |
323 { "_echo", HandleEcho }, | 622 { "_echo", HandleEcho }, |
324 { "classes", HandleClasses }, | 623 { "classes", HandleClasses }, |
| 624 { "code", HandleCode }, |
325 { "cpu", HandleCpu }, | 625 { "cpu", HandleCpu }, |
326 { "debug", HandleDebug }, | 626 { "debug", HandleDebug }, |
| 627 { "libraries", HandleLibraries }, |
327 { "library", HandleLibrary }, | 628 { "library", HandleLibrary }, |
328 { "name", HandleName }, | 629 { "name", HandleName }, |
329 { "objecthistogram", HandleObjectHistogram}, | 630 { "objecthistogram", HandleObjectHistogram}, |
330 { "objects", HandleObjects }, | 631 { "objects", HandleObjects }, |
| 632 { "profile", HandleProfile }, |
| 633 { "scripts", HandleScripts }, |
331 { "stacktrace", HandleStackTrace }, | 634 { "stacktrace", HandleStackTrace }, |
332 }; | 635 }; |
333 | 636 |
334 | 637 |
335 static void HandleFallthrough(Isolate* isolate, JSONStream* js) { | 638 static void HandleFallthrough(Isolate* isolate, JSONStream* js) { |
336 JSONObject jsobj(js); | 639 JSONObject jsobj(js); |
337 jsobj.AddProperty("type", "Error"); | 640 jsobj.AddProperty("type", "Error"); |
338 jsobj.AddProperty("text", "request not understood."); | 641 jsobj.AddProperty("text", "request not understood."); |
339 PrintArgumentsAndOptions(jsobj, js); | 642 PrintArgumentsAndOptions(jsobj, js); |
340 } | 643 } |
341 | 644 |
342 | 645 |
343 static ServiceMessageHandler FindServiceMessageHandler(const char* command) { | 646 static ServiceMessageHandler FindServiceMessageHandler(const char* command) { |
344 intptr_t num_message_handlers = sizeof(__message_handlers) / | 647 intptr_t num_message_handlers = sizeof(__message_handlers) / |
345 sizeof(__message_handlers[0]); | 648 sizeof(__message_handlers[0]); |
346 for (intptr_t i = 0; i < num_message_handlers; i++) { | 649 for (intptr_t i = 0; i < num_message_handlers; i++) { |
347 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; | 650 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; |
348 if (!strcmp(command, entry.command)) { | 651 if (!strcmp(command, entry.command)) { |
349 return entry.handler; | 652 return entry.handler; |
350 } | 653 } |
351 } | 654 } |
352 return HandleFallthrough; | 655 return HandleFallthrough; |
353 } | 656 } |
354 | 657 |
355 } // namespace dart | 658 } // namespace dart |
OLD | NEW |