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 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 PrintError(js, "Must specify collection object id: %s/id", collection); \ | 245 PrintError(js, "Must specify collection object id: %s/id", collection); \ |
245 return; \ | 246 return; \ |
246 } \ | 247 } \ |
247 if ((id < 0) || (id >= length)) { \ | 248 if ((id < 0) || (id >= length)) { \ |
248 PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \ | 249 PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \ |
249 length); \ | 250 length); \ |
250 return; \ | 251 return; \ |
251 } | 252 } |
252 | 253 |
253 | 254 |
254 static bool GetIntegerId(const char* s, intptr_t* id) { | 255 static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) { |
255 if ((s == NULL) || (*s == '\0')) { | 256 if ((s == NULL) || (*s == '\0')) { |
256 // Empty string. | 257 // Empty string. |
257 return false; | 258 return false; |
258 } | 259 } |
259 if (id == NULL) { | 260 if (id == NULL) { |
260 // No id pointer. | 261 // No id pointer. |
261 return false; | 262 return false; |
262 } | 263 } |
263 intptr_t r = 0; | 264 intptr_t r = 0; |
264 char* end_ptr = NULL; | 265 char* end_ptr = NULL; |
265 r = strtol(s, &end_ptr, 10); | 266 r = strtol(s, &end_ptr, base); |
266 if (end_ptr == s) { | 267 if (end_ptr == s) { |
267 // String was not advanced at all, cannot be valid. | 268 // String was not advanced at all, cannot be valid. |
268 return false; | 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; |
269 } | 291 } |
270 *id = r; | 292 *id = r; |
271 return true; | 293 return true; |
272 } | 294 } |
273 | 295 |
274 | 296 |
275 static void HandleClassesClosures(Isolate* isolate, const Class& cls, | 297 static void HandleClassesClosures(Isolate* isolate, const Class& cls, |
276 JSONStream* js) { | 298 JSONStream* js) { |
277 const GrowableObjectArray& closures = | |
278 GrowableObjectArray::Handle(cls.closures()); | |
279 intptr_t id; | 299 intptr_t id; |
280 if (js->num_arguments() > 4) { | 300 if (js->num_arguments() > 4) { |
281 PrintError(js, "Command too long"); | 301 PrintError(js, "Command too long"); |
282 return; | 302 return; |
283 } | 303 } |
284 CHECK_COLLECTION_ID_BOUNDS("closures", closures.Length(), js->GetArgument(3), | 304 if (!GetIntegerId(js->GetArgument(3), &id)) { |
285 id, js); | 305 PrintError(js, "Must specify collection object id: closures/id"); |
286 Function& function = Function::Handle(); | 306 return; |
287 function ^= closures.At(id); | 307 } |
288 ASSERT(!function.IsNull()); | 308 Function& func = Function::Handle(); |
289 function.PrintToJSONStream(js, false); | 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); |
290 } | 336 } |
291 | 337 |
292 | 338 |
293 static void HandleClassesFunctions(Isolate* isolate, const Class& cls, | 339 static void HandleClassesFunctions(Isolate* isolate, const Class& cls, |
294 JSONStream* js) { | 340 JSONStream* js) { |
295 const Array& functions = | |
296 Array::Handle(cls.functions()); | |
297 intptr_t id; | 341 intptr_t id; |
298 if (js->num_arguments() > 4) { | 342 if (js->num_arguments() > 4) { |
299 PrintError(js, "Command too long"); | 343 PrintError(js, "Command too long"); |
300 return; | 344 return; |
301 } | 345 } |
302 CHECK_COLLECTION_ID_BOUNDS("functions", functions.Length(), | 346 if (!GetIntegerId(js->GetArgument(3), &id)) { |
303 js->GetArgument(3), id, js); | 347 PrintError(js, "Must specify collection object id: functions/id"); |
304 Function& function = Function::Handle(); | 348 return; |
305 function ^= functions.At(id); | 349 } |
306 ASSERT(!function.IsNull()); | 350 Function& func = Function::Handle(); |
307 function.PrintToJSONStream(js, false); | 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); |
308 } | 378 } |
309 | 379 |
310 | 380 |
311 static void HandleClassesFields(Isolate* isolate, const Class& cls, | 381 static void HandleClassesFields(Isolate* isolate, const Class& cls, |
312 JSONStream* js) { | 382 JSONStream* js) { |
313 const Array& fields = | |
314 Array::Handle(cls.fields()); | |
315 intptr_t id; | 383 intptr_t id; |
316 if (js->num_arguments() > 4) { | 384 if (js->num_arguments() > 4) { |
317 PrintError(js, "Command too long"); | 385 PrintError(js, "Command too long"); |
318 return; | 386 return; |
319 } | 387 } |
320 CHECK_COLLECTION_ID_BOUNDS("fields", fields.Length(), js->GetArgument(3), | 388 if (!GetIntegerId(js->GetArgument(3), &id)) { |
321 id, js); | 389 PrintError(js, "Must specify collection object id: fields/id"); |
322 Field& field = Field::Handle(); | 390 return; |
323 field ^= fields.At(id); | 391 } |
324 ASSERT(!field.IsNull()); | 392 Field& field = Field::Handle(cls.FieldFromIndex(id)); |
| 393 if (field.IsNull()) { |
| 394 PrintError(js, "Field %" Pd " not found", id); |
| 395 return; |
| 396 } |
325 field.PrintToJSONStream(js, false); | 397 field.PrintToJSONStream(js, false); |
326 } | 398 } |
327 | 399 |
328 | 400 |
329 static void HandleClasses(Isolate* isolate, JSONStream* js) { | 401 static void HandleClasses(Isolate* isolate, JSONStream* js) { |
330 if (js->num_arguments() == 1) { | 402 if (js->num_arguments() == 1) { |
331 ClassTable* table = isolate->class_table(); | 403 ClassTable* table = isolate->class_table(); |
332 table->PrintToJSONStream(js); | 404 table->PrintToJSONStream(js); |
333 return; | 405 return; |
334 } | 406 } |
(...skipping 13 matching lines...) Expand all Loading... |
348 cls.PrintToJSONStream(js, false); | 420 cls.PrintToJSONStream(js, false); |
349 return; | 421 return; |
350 } else if (js->num_arguments() >= 3) { | 422 } else if (js->num_arguments() >= 3) { |
351 const char* second = js->GetArgument(2); | 423 const char* second = js->GetArgument(2); |
352 if (!strcmp(second, "closures")) { | 424 if (!strcmp(second, "closures")) { |
353 HandleClassesClosures(isolate, cls, js); | 425 HandleClassesClosures(isolate, cls, js); |
354 } else if (!strcmp(second, "fields")) { | 426 } else if (!strcmp(second, "fields")) { |
355 HandleClassesFields(isolate, cls, js); | 427 HandleClassesFields(isolate, cls, js); |
356 } else if (!strcmp(second, "functions")) { | 428 } else if (!strcmp(second, "functions")) { |
357 HandleClassesFunctions(isolate, cls, js); | 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); |
358 } else { | 434 } else { |
359 PrintError(js, "Invalid sub collection %s", second); | 435 PrintError(js, "Invalid sub collection %s", second); |
360 } | 436 } |
361 return; | 437 return; |
362 } | 438 } |
363 UNREACHABLE(); | 439 UNREACHABLE(); |
364 } | 440 } |
365 | 441 |
366 | 442 |
367 static void HandleLibrary(Isolate* isolate, JSONStream* js) { | 443 static void HandleLibrary(Isolate* isolate, JSONStream* js) { |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 } | 590 } |
515 | 591 |
516 | 592 |
517 static void HandleCpu(Isolate* isolate, JSONStream* js) { | 593 static void HandleCpu(Isolate* isolate, JSONStream* js) { |
518 JSONObject jsobj(js); | 594 JSONObject jsobj(js); |
519 jsobj.AddProperty("type", "CPU"); | 595 jsobj.AddProperty("type", "CPU"); |
520 jsobj.AddProperty("architecture", CPU::Id()); | 596 jsobj.AddProperty("architecture", CPU::Id()); |
521 } | 597 } |
522 | 598 |
523 | 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 |
524 static ServiceMessageHandlerEntry __message_handlers[] = { | 621 static ServiceMessageHandlerEntry __message_handlers[] = { |
525 { "_echo", HandleEcho }, | 622 { "_echo", HandleEcho }, |
526 { "classes", HandleClasses }, | 623 { "classes", HandleClasses }, |
| 624 { "code", HandleCode }, |
527 { "cpu", HandleCpu }, | 625 { "cpu", HandleCpu }, |
528 { "debug", HandleDebug }, | 626 { "debug", HandleDebug }, |
529 { "libraries", HandleLibraries }, | 627 { "libraries", HandleLibraries }, |
530 { "library", HandleLibrary }, | 628 { "library", HandleLibrary }, |
531 { "name", HandleName }, | 629 { "name", HandleName }, |
532 { "objecthistogram", HandleObjectHistogram}, | 630 { "objecthistogram", HandleObjectHistogram}, |
533 { "objects", HandleObjects }, | 631 { "objects", HandleObjects }, |
| 632 { "profile", HandleProfile }, |
534 { "scripts", HandleScripts }, | 633 { "scripts", HandleScripts }, |
535 { "stacktrace", HandleStackTrace }, | 634 { "stacktrace", HandleStackTrace }, |
536 }; | 635 }; |
537 | 636 |
538 | 637 |
539 static void HandleFallthrough(Isolate* isolate, JSONStream* js) { | 638 static void HandleFallthrough(Isolate* isolate, JSONStream* js) { |
540 JSONObject jsobj(js); | 639 JSONObject jsobj(js); |
541 jsobj.AddProperty("type", "Error"); | 640 jsobj.AddProperty("type", "Error"); |
542 jsobj.AddProperty("text", "request not understood."); | 641 jsobj.AddProperty("text", "request not understood."); |
543 PrintArgumentsAndOptions(jsobj, js); | 642 PrintArgumentsAndOptions(jsobj, js); |
544 } | 643 } |
545 | 644 |
546 | 645 |
547 static ServiceMessageHandler FindServiceMessageHandler(const char* command) { | 646 static ServiceMessageHandler FindServiceMessageHandler(const char* command) { |
548 intptr_t num_message_handlers = sizeof(__message_handlers) / | 647 intptr_t num_message_handlers = sizeof(__message_handlers) / |
549 sizeof(__message_handlers[0]); | 648 sizeof(__message_handlers[0]); |
550 for (intptr_t i = 0; i < num_message_handlers; i++) { | 649 for (intptr_t i = 0; i < num_message_handlers; i++) { |
551 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; | 650 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; |
552 if (!strcmp(command, entry.command)) { | 651 if (!strcmp(command, entry.command)) { |
553 return entry.handler; | 652 return entry.handler; |
554 } | 653 } |
555 } | 654 } |
556 return HandleFallthrough; | 655 return HandleFallthrough; |
557 } | 656 } |
558 | 657 |
559 } // namespace dart | 658 } // namespace dart |
OLD | NEW |