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

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
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service/message.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "include/dart_api.h" 7 #include "include/dart_api.h"
8 8
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); 99 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources);
100 }; 100 };
101 101
102 102
103 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { 103 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
104 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); 104 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
105 return reinterpret_cast<uint8_t*>(new_ptr); 105 return reinterpret_cast<uint8_t*>(new_ptr);
106 } 106 }
107 107
108 108
109 static void SendServiceMessage(Dart_NativeArguments args) { 109 static void SendIsolateServiceMessage(Dart_NativeArguments args) {
110 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); 110 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
111 Isolate* isolate = arguments->isolate(); 111 Isolate* isolate = arguments->isolate();
112 StackZone zone(isolate); 112 StackZone zone(isolate);
113 HANDLESCOPE(isolate); 113 HANDLESCOPE(isolate);
114 GET_NON_NULL_NATIVE_ARGUMENT(Instance, sp, arguments->NativeArgAt(0)); 114 GET_NON_NULL_NATIVE_ARGUMENT(Instance, sp, arguments->NativeArgAt(0));
115 GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(1)); 115 GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(1));
116 116
117 // Extract SendPort port id. 117 // Extract SendPort port id.
118 const Object& sp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(sp)); 118 const Object& sp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(sp));
119 if (sp_id_obj.IsError()) { 119 if (sp_id_obj.IsError()) {
120 Exceptions::PropagateError(Error::Cast(sp_id_obj)); 120 Exceptions::PropagateError(Error::Cast(sp_id_obj));
121 } 121 }
122 Integer& id = Integer::Handle(); 122 Integer& id = Integer::Handle(isolate);
123 id ^= sp_id_obj.raw(); 123 id ^= sp_id_obj.raw();
124 Dart_Port sp_id = static_cast<Dart_Port>(id.AsInt64Value()); 124 Dart_Port sp_id = static_cast<Dart_Port>(id.AsInt64Value());
125 ASSERT(sp_id != ILLEGAL_PORT); 125 ASSERT(sp_id != ILLEGAL_PORT);
126 126
127 // Serialize message. 127 // Serialize message.
128 uint8_t* data = NULL; 128 uint8_t* data = NULL;
129 MessageWriter writer(&data, &allocator); 129 MessageWriter writer(&data, &allocator);
130 writer.WriteMessage(message); 130 writer.WriteMessage(message);
131 131
132 // TODO(turnidge): Throw an exception when the return value is false? 132 // TODO(turnidge): Throw an exception when the return value is false?
133 PortMap::PostMessage(new Message(sp_id, data, writer.BytesWritten(), 133 PortMap::PostMessage(new Message(sp_id, data, writer.BytesWritten(),
134 Message::kOOBPriority)); 134 Message::kOOBPriority));
135 } 135 }
136 136
137 137
138 static void SendRootServiceMessage(Dart_NativeArguments args) {
139 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
140 Isolate* isolate = arguments->isolate();
141 StackZone zone(isolate);
142 HANDLESCOPE(isolate);
143 GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(0));
144 Service::HandleRootMessage(message);
145 }
146
147
138 struct VmServiceNativeEntry { 148 struct VmServiceNativeEntry {
139 const char* name; 149 const char* name;
140 int num_arguments; 150 int num_arguments;
141 Dart_NativeFunction function; 151 Dart_NativeFunction function;
142 }; 152 };
143 153
144 154
145 static VmServiceNativeEntry _VmServiceNativeEntries[] = { 155 static VmServiceNativeEntry _VmServiceNativeEntries[] = {
146 {"VMService_SendServiceMessage", 2, SendServiceMessage} 156 {"VMService_SendIsolateServiceMessage", 2, SendIsolateServiceMessage},
157 {"VMService_SendRootServiceMessage", 1, SendRootServiceMessage}
147 }; 158 };
148 159
149 160
150 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name, 161 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
151 int num_arguments, 162 int num_arguments,
152 bool* auto_setup_scope) { 163 bool* auto_setup_scope) {
153 const Object& obj = Object::Handle(Api::UnwrapHandle(name)); 164 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
154 if (!obj.IsString()) { 165 if (!obj.IsString()) {
155 return NULL; 166 return NULL;
156 } 167 }
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 return url; 398 return url;
388 } 399 }
389 Dart_Handle source = GetSource(url_string); 400 Dart_Handle source = GetSource(url_string);
390 if (Dart_IsError(source)) { 401 if (Dart_IsError(source)) {
391 return source; 402 return source;
392 } 403 }
393 return Dart_LoadSource(library, url, source); 404 return Dart_LoadSource(library, url, source);
394 } 405 }
395 406
396 407
397 typedef void (*ServiceMessageHandler)(Isolate* isolate, JSONStream* stream); 408 // A handler for a per-isolate request.
409 //
410 // If a handler returns true, the reply is complete and ready to be
411 // posted. If a handler returns false, then it is responsible for
412 // posting the reply (this can be used for asynchronous delegation of
413 // the response handling).
414 typedef bool (*IsolateMessageHandler)(Isolate* isolate, JSONStream* stream);
398 415
399 struct ServiceMessageHandlerEntry { 416 struct IsolateMessageHandlerEntry {
400 const char* command; 417 const char* command;
401 ServiceMessageHandler handler; 418 IsolateMessageHandler handler;
402 }; 419 };
403 420
404 static ServiceMessageHandler FindServiceMessageHandler(const char* command); 421 static IsolateMessageHandler FindIsolateMessageHandler(const char* command);
405 422
406 static void PostReply(const String& reply, const Instance& reply_port) { 423
424 // A handler for a root (vm-global) request.
425 //
426 // If a handler returns true, the reply is complete and ready to be
427 // posted. If a handler returns false, then it is responsible for
428 // posting the reply (this can be used for asynchronous delegation of
429 // the response handling).
430 typedef bool (*RootMessageHandler)(JSONStream* stream);
431
432 struct RootMessageHandlerEntry {
433 const char* command;
434 RootMessageHandler handler;
435 };
436
437 static RootMessageHandler FindRootMessageHandler(const char* command);
438
439
440 static void PostReply(JSONStream* js) {
441 Dart_Port reply_port = js->reply_port();
442 ASSERT(reply_port != ILLEGAL_PORT);
443 js->set_reply_port(ILLEGAL_PORT); // Prevent double replies.
444
445 const String& reply = String::Handle(String::New(js->ToCString()));
446 ASSERT(!reply.IsNull());
447
448 uint8_t* data = NULL;
449 MessageWriter writer(&data, &allocator);
450 writer.WriteMessage(reply);
451 PortMap::PostMessage(new Message(reply_port, data,
452 writer.BytesWritten(),
453 Message::kNormalPriority));
454 }
455
456
457 static void SetupJSONStream(JSONStream* js, Zone* zone,
458 const Instance& reply_port,
459 const GrowableObjectArray& path,
460 const GrowableObjectArray& option_keys,
461 const GrowableObjectArray& option_values) {
462 // Setup the reply port.
407 const Object& id_obj = Object::Handle( 463 const Object& id_obj = Object::Handle(
408 DartLibraryCalls::PortGetId(reply_port)); 464 DartLibraryCalls::PortGetId(reply_port));
409 if (id_obj.IsError()) { 465 if (id_obj.IsError()) {
410 Exceptions::PropagateError(Error::Cast(id_obj)); 466 Exceptions::PropagateError(Error::Cast(id_obj));
411 } 467 }
412 const Integer& id = Integer::Cast(id_obj); 468 const Integer& id = Integer::Cast(id_obj);
413 Dart_Port port = static_cast<Dart_Port>(id.AsInt64Value()); 469 Dart_Port port = static_cast<Dart_Port>(id.AsInt64Value());
414 ASSERT(port != ILLEGAL_PORT); 470 ASSERT(port != ILLEGAL_PORT);
471 js->set_reply_port(port);
415 472
416 uint8_t* data = NULL; 473 // Setup JSONStream arguments and options. The arguments and options
417 MessageWriter writer(&data, &allocator); 474 // are zone allocated and will be freed immediately after handling the
418 writer.WriteMessage(reply); 475 // message.
419 PortMap::PostMessage(new Message(port, data, 476 const char** arguments = zone->Alloc<const char*>(path.Length());
420 writer.BytesWritten(), 477 String& string_iterator = String::Handle();
421 Message::kNormalPriority)); 478 for (intptr_t i = 0; i < path.Length(); i++) {
422 } 479 string_iterator ^= path.At(i);
423 480 arguments[i] = zone->MakeCopyOfString(string_iterator.ToCString());
424 481 }
425 void Service::HandleServiceMessage(Isolate* isolate, const Instance& msg) { 482 js->SetArguments(arguments, path.Length());
426 ASSERT(isolate != NULL); 483 if (option_keys.Length() > 0) {
427 ASSERT(!msg.IsNull()); 484 const char** option_keys_native =
428 ASSERT(msg.IsGrowableObjectArray()); 485 zone->Alloc<const char*>(option_keys.Length());
429 486 const char** option_values_native =
430 { 487 zone->Alloc<const char*>(option_keys.Length());
431 StackZone zone(isolate); 488 for (intptr_t i = 0; i < option_keys.Length(); i++) {
432 HANDLESCOPE(isolate); 489 string_iterator ^= option_keys.At(i);
433 490 option_keys_native[i] =
434 const GrowableObjectArray& message = GrowableObjectArray::Cast(msg); 491 zone->MakeCopyOfString(string_iterator.ToCString());
435 // Message is a list with three entries. 492 string_iterator ^= option_values.At(i);
436 ASSERT(message.Length() == 4); 493 option_values_native[i] =
437 494 zone->MakeCopyOfString(string_iterator.ToCString());
438 Instance& reply_port = Instance::Handle(isolate);
439 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
440 GrowableObjectArray& option_keys = GrowableObjectArray::Handle(isolate);
441 GrowableObjectArray& option_values = GrowableObjectArray::Handle(isolate);
442 reply_port ^= message.At(0);
443 path ^= message.At(1);
444 option_keys ^= message.At(2);
445 option_values ^= message.At(3);
446
447 ASSERT(!path.IsNull());
448 ASSERT(!option_keys.IsNull());
449 ASSERT(!option_values.IsNull());
450 // Path always has at least one entry in it.
451 ASSERT(path.Length() > 0);
452 // Same number of option keys as values.
453 ASSERT(option_keys.Length() == option_values.Length());
454
455 String& pathSegment = String::Handle();
456 pathSegment ^= path.At(0);
457 ASSERT(!pathSegment.IsNull());
458
459 ServiceMessageHandler handler =
460 FindServiceMessageHandler(pathSegment.ToCString());
461 ASSERT(handler != NULL);
462 {
463 JSONStream js;
464
465 // Setup JSONStream arguments and options. The arguments and options
466 // are zone allocated and will be freed immediately after handling the
467 // message.
468 Zone* zoneAllocator = zone.GetZone();
469 const char** arguments = zoneAllocator->Alloc<const char*>(path.Length());
470 String& string_iterator = String::Handle();
471 for (intptr_t i = 0; i < path.Length(); i++) {
472 string_iterator ^= path.At(i);
473 arguments[i] =
474 zoneAllocator->MakeCopyOfString(string_iterator.ToCString());
475 }
476 js.SetArguments(arguments, path.Length());
477 if (option_keys.Length() > 0) {
478 const char** option_keys_native =
479 zoneAllocator->Alloc<const char*>(option_keys.Length());
480 const char** option_values_native =
481 zoneAllocator->Alloc<const char*>(option_keys.Length());
482 for (intptr_t i = 0; i < option_keys.Length(); i++) {
483 string_iterator ^= option_keys.At(i);
484 option_keys_native[i] =
485 zoneAllocator->MakeCopyOfString(string_iterator.ToCString());
486 string_iterator ^= option_values.At(i);
487 option_values_native[i] =
488 zoneAllocator->MakeCopyOfString(string_iterator.ToCString());
489 }
490 js.SetOptions(option_keys_native, option_values_native,
491 option_keys.Length());
492 }
493
494 handler(isolate, &js);
495 const String& reply = String::Handle(String::New(js.ToCString()));
496 ASSERT(!reply.IsNull());
497 PostReply(reply, reply_port);
498 } 495 }
496 js->SetOptions(option_keys_native, option_values_native,
497 option_keys.Length());
499 } 498 }
500 } 499 }
501 500
502 501
503 static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) { 502 static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) {
504 JSONObject jsobj(&obj, "message"); 503 JSONObject jsobj(&obj, "message");
505 { 504 {
506 JSONArray jsarr(&jsobj, "arguments"); 505 JSONArray jsarr(&jsobj, "arguments");
507 for (intptr_t i = 0; i < js->num_arguments(); i++) { 506 for (intptr_t i = 0; i < js->num_arguments(); i++) {
508 jsarr.AddValue(js->GetArgument(i)); 507 jsarr.AddValue(js->GetArgument(i));
509 } 508 }
510 } 509 }
511 { 510 {
512 JSONArray jsarr(&jsobj, "option_keys"); 511 JSONArray jsarr(&jsobj, "option_keys");
513 for (intptr_t i = 0; i < js->num_options(); i++) { 512 for (intptr_t i = 0; i < js->num_options(); i++) {
514 jsarr.AddValue(js->GetOptionKey(i)); 513 jsarr.AddValue(js->GetOptionKey(i));
515 } 514 }
516 } 515 }
517 { 516 {
518 JSONArray jsarr(&jsobj, "option_values"); 517 JSONArray jsarr(&jsobj, "option_values");
519 for (intptr_t i = 0; i < js->num_options(); i++) { 518 for (intptr_t i = 0; i < js->num_options(); i++) {
520 jsarr.AddValue(js->GetOptionValue(i)); 519 jsarr.AddValue(js->GetOptionValue(i));
521 } 520 }
522 } 521 }
523 } 522 }
524 523
525 524
526 static void PrintGenericError(JSONStream* js) {
527 JSONObject jsobj(js);
528 jsobj.AddProperty("type", "Error");
529 jsobj.AddProperty("text", "Invalid request.");
530 PrintArgumentsAndOptions(jsobj, js);
531 }
532
533
534 static void PrintError(JSONStream* js, const char* format, ...) { 525 static void PrintError(JSONStream* js, const char* format, ...) {
535 Isolate* isolate = Isolate::Current(); 526 Isolate* isolate = Isolate::Current();
536 527
537 va_list args; 528 va_list args;
538 va_start(args, format); 529 va_start(args, format);
539 intptr_t len = OS::VSNPrint(NULL, 0, format, args); 530 intptr_t len = OS::VSNPrint(NULL, 0, format, args);
540 va_end(args); 531 va_end(args);
541 532
542 char* buffer = isolate->current_zone()->Alloc<char>(len + 1); 533 char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
543 va_list args2; 534 va_list args2;
544 va_start(args2, format); 535 va_start(args2, format);
545 OS::VSNPrint(buffer, (len + 1), format, args2); 536 OS::VSNPrint(buffer, (len + 1), format, args2);
546 va_end(args2); 537 va_end(args2);
547 538
548 JSONObject jsobj(js); 539 JSONObject jsobj(js);
549 jsobj.AddProperty("type", "Error"); 540 jsobj.AddProperty("type", "Error");
550 jsobj.AddProperty("text", buffer); 541 jsobj.AddProperty("text", buffer);
551 PrintArgumentsAndOptions(jsobj, js); 542 PrintArgumentsAndOptions(jsobj, js);
552 } 543 }
553 544
554 545
555 static void HandleName(Isolate* isolate, JSONStream* js) { 546 void Service::HandleIsolateMessage(Isolate* isolate, const Instance& msg) {
547 ASSERT(isolate != NULL);
548 ASSERT(!msg.IsNull());
549 ASSERT(msg.IsGrowableObjectArray());
550
551 {
552 StackZone zone(isolate);
553 HANDLESCOPE(isolate);
554
555 const GrowableObjectArray& message = GrowableObjectArray::Cast(msg);
556 // Message is a list with four entries.
557 ASSERT(message.Length() == 4);
558
559 Instance& reply_port = Instance::Handle(isolate);
560 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
561 GrowableObjectArray& option_keys = GrowableObjectArray::Handle(isolate);
562 GrowableObjectArray& option_values = GrowableObjectArray::Handle(isolate);
563 reply_port ^= message.At(0);
564 path ^= message.At(1);
565 option_keys ^= message.At(2);
566 option_values ^= message.At(3);
567
568 ASSERT(!path.IsNull());
569 ASSERT(!option_keys.IsNull());
570 ASSERT(!option_values.IsNull());
571 // Path always has at least one entry in it.
572 ASSERT(path.Length() > 0);
573 // Same number of option keys as values.
574 ASSERT(option_keys.Length() == option_values.Length());
575
576 String& pathSegment = String::Handle();
577 pathSegment ^= path.At(0);
578 ASSERT(!pathSegment.IsNull());
579
580 IsolateMessageHandler handler =
581 FindIsolateMessageHandler(pathSegment.ToCString());
582 {
583 JSONStream js;
584 SetupJSONStream(&js, zone.GetZone(),
585 reply_port, path, option_keys, option_values);
586 if (handler == NULL) {
587 PrintError(&js, "Unrecognized path");
588 PostReply(&js);
589 } else {
590 if (handler(isolate, &js)) {
591 // Handler returns true if the reply is ready to be posted.
592 PostReply(&js);
593 }
594 }
595 }
596 }
597 }
598
599
600 static bool HandleName(Isolate* isolate, JSONStream* js) {
556 JSONObject jsobj(js); 601 JSONObject jsobj(js);
557 jsobj.AddProperty("type", "IsolateName"); 602 jsobj.AddProperty("type", "IsolateName");
558 jsobj.AddProperty("id", static_cast<intptr_t>(isolate->main_port())); 603 jsobj.AddProperty("id", static_cast<intptr_t>(isolate->main_port()));
559 jsobj.AddProperty("name", isolate->name()); 604 jsobj.AddProperty("name", isolate->name());
605 return true;
560 } 606 }
561 607
562 608
563 static void HandleStackTrace(Isolate* isolate, JSONStream* js) { 609 static bool HandleStackTrace(Isolate* isolate, JSONStream* js) {
564 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); 610 DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
565 JSONObject jsobj(js); 611 JSONObject jsobj(js);
566 jsobj.AddProperty("type", "StackTrace"); 612 jsobj.AddProperty("type", "StackTrace");
567 JSONArray jsarr(&jsobj, "members"); 613 JSONArray jsarr(&jsobj, "members");
568 intptr_t n_frames = stack->Length(); 614 intptr_t n_frames = stack->Length();
569 String& function = String::Handle(); 615 String& function = String::Handle();
570 Script& script = Script::Handle(); 616 Script& script = Script::Handle();
571 for (int i = 0; i < n_frames; i++) { 617 for (int i = 0; i < n_frames; i++) {
572 ActivationFrame* frame = stack->FrameAt(i); 618 ActivationFrame* frame = stack->FrameAt(i);
573 script ^= frame->SourceScript(); 619 script ^= frame->SourceScript();
574 function ^= frame->function().UserVisibleName(); 620 function ^= frame->function().UserVisibleName();
575 JSONObject jsobj(&jsarr); 621 JSONObject jsobj(&jsarr);
576 jsobj.AddProperty("name", function.ToCString()); 622 jsobj.AddProperty("name", function.ToCString());
577 jsobj.AddProperty("script", script); 623 jsobj.AddProperty("script", script);
578 jsobj.AddProperty("line", frame->LineNumber()); 624 jsobj.AddProperty("line", frame->LineNumber());
579 jsobj.AddProperty("function", frame->function()); 625 jsobj.AddProperty("function", frame->function());
580 jsobj.AddProperty("code", frame->code()); 626 jsobj.AddProperty("code", frame->code());
581 } 627 }
628 return true;
582 } 629 }
583 630
584 631
585 static void HandleObjectHistogram(Isolate* isolate, JSONStream* js) { 632 static bool HandleObjectHistogram(Isolate* isolate, JSONStream* js) {
586 ObjectHistogram* histogram = Isolate::Current()->object_histogram(); 633 ObjectHistogram* histogram = Isolate::Current()->object_histogram();
587 if (histogram == NULL) { 634 if (histogram == NULL) {
588 JSONObject jsobj(js); 635 JSONObject jsobj(js);
589 jsobj.AddProperty("type", "Error"); 636 jsobj.AddProperty("type", "Error");
590 jsobj.AddProperty("text", "Run with --print_object_histogram"); 637 jsobj.AddProperty("text", "Run with --print_object_histogram");
591 return; 638 return true;
592 } 639 }
593 histogram->PrintToJSONStream(js); 640 histogram->PrintToJSONStream(js);
641 return true;
594 } 642 }
595 643
596 644
597 static void HandleEcho(Isolate* isolate, JSONStream* js) { 645 static bool HandleIsolateEcho(Isolate* isolate, JSONStream* js) {
598 JSONObject jsobj(js); 646 JSONObject jsobj(js);
599 jsobj.AddProperty("type", "message"); 647 jsobj.AddProperty("type", "message");
600 PrintArgumentsAndOptions(jsobj, js); 648 PrintArgumentsAndOptions(jsobj, js);
649 return true;
601 } 650 }
602 651
603 652
604 // Print an error message if there is no ID argument. 653 // Print an error message if there is no ID argument.
605 #define REQUIRE_COLLECTION_ID(collection) \ 654 #define REQUIRE_COLLECTION_ID(collection) \
606 if (js->num_arguments() == 1) { \ 655 if (js->num_arguments() == 1) { \
607 PrintError(js, "Must specify collection object id: /%s/id", collection); \ 656 PrintError(js, "Must specify collection object id: /%s/id", collection); \
608 return; \ 657 return true; \
609 } 658 }
610 659
611 660
612 #define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \ 661 #define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \
613 if (!GetIntegerId(arg, &id)) { \ 662 if (!GetIntegerId(arg, &id)) { \
614 PrintError(js, "Must specify collection object id: %s/id", collection); \ 663 PrintError(js, "Must specify collection object id: %s/id", collection); \
615 return; \ 664 return true; \
616 } \ 665 } \
617 if ((id < 0) || (id >= length)) { \ 666 if ((id < 0) || (id >= length)) { \
618 PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \ 667 PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \
619 length); \ 668 length); \
620 return; \ 669 return true; \
621 } 670 }
622 671
623 672
624 static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) { 673 static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) {
625 if ((s == NULL) || (*s == '\0')) { 674 if ((s == NULL) || (*s == '\0')) {
626 // Empty string. 675 // Empty string.
627 return false; 676 return false;
628 } 677 }
629 if (id == NULL) { 678 if (id == NULL) {
630 // No id pointer. 679 // No id pointer.
(...skipping 25 matching lines...) Expand all
656 r = strtoul(s, &end_ptr, base); 705 r = strtoul(s, &end_ptr, base);
657 if (end_ptr == s) { 706 if (end_ptr == s) {
658 // String was not advanced at all, cannot be valid. 707 // String was not advanced at all, cannot be valid.
659 return false; 708 return false;
660 } 709 }
661 *id = r; 710 *id = r;
662 return true; 711 return true;
663 } 712 }
664 713
665 714
666 static void HandleClassesClosures(Isolate* isolate, const Class& cls, 715 static bool HandleClassesClosures(Isolate* isolate, const Class& cls,
667 JSONStream* js) { 716 JSONStream* js) {
668 intptr_t id; 717 intptr_t id;
669 if (js->num_arguments() > 4) { 718 if (js->num_arguments() > 4) {
670 PrintError(js, "Command too long"); 719 PrintError(js, "Command too long");
671 return; 720 return true;
672 } 721 }
673 if (!GetIntegerId(js->GetArgument(3), &id)) { 722 if (!GetIntegerId(js->GetArgument(3), &id)) {
674 PrintError(js, "Must specify collection object id: closures/id"); 723 PrintError(js, "Must specify collection object id: closures/id");
675 return; 724 return true;
676 } 725 }
677 Function& func = Function::Handle(); 726 Function& func = Function::Handle();
678 func ^= cls.ClosureFunctionFromIndex(id); 727 func ^= cls.ClosureFunctionFromIndex(id);
679 if (func.IsNull()) { 728 if (func.IsNull()) {
680 PrintError(js, "Closure function %" Pd " not found", id); 729 PrintError(js, "Closure function %" Pd " not found", id);
681 return; 730 return true;
682 } 731 }
683 func.PrintToJSONStream(js, false); 732 func.PrintToJSONStream(js, false);
733 return true;
684 } 734 }
685 735
686 736
687 static void HandleClassesDispatchers(Isolate* isolate, const Class& cls, 737 static bool HandleClassesDispatchers(Isolate* isolate, const Class& cls,
688 JSONStream* js) { 738 JSONStream* js) {
689 intptr_t id; 739 intptr_t id;
690 if (js->num_arguments() > 4) { 740 if (js->num_arguments() > 4) {
691 PrintError(js, "Command too long"); 741 PrintError(js, "Command too long");
692 return; 742 return true;
693 } 743 }
694 if (!GetIntegerId(js->GetArgument(3), &id)) { 744 if (!GetIntegerId(js->GetArgument(3), &id)) {
695 PrintError(js, "Must specify collection object id: dispatchers/id"); 745 PrintError(js, "Must specify collection object id: dispatchers/id");
696 return; 746 return true;
697 } 747 }
698 Function& func = Function::Handle(); 748 Function& func = Function::Handle();
699 func ^= cls.InvocationDispatcherFunctionFromIndex(id); 749 func ^= cls.InvocationDispatcherFunctionFromIndex(id);
700 if (func.IsNull()) { 750 if (func.IsNull()) {
701 PrintError(js, "Dispatcher %" Pd " not found", id); 751 PrintError(js, "Dispatcher %" Pd " not found", id);
702 return; 752 return true;
703 } 753 }
704 func.PrintToJSONStream(js, false); 754 func.PrintToJSONStream(js, false);
755 return true;
705 } 756 }
706 757
707 758
708 static void HandleClassesFunctions(Isolate* isolate, const Class& cls, 759 static bool HandleClassesFunctions(Isolate* isolate, const Class& cls,
709 JSONStream* js) { 760 JSONStream* js) {
710 intptr_t id; 761 intptr_t id;
711 if (js->num_arguments() > 4) { 762 if (js->num_arguments() > 4) {
712 PrintError(js, "Command too long"); 763 PrintError(js, "Command too long");
713 return; 764 return true;
714 } 765 }
715 if (!GetIntegerId(js->GetArgument(3), &id)) { 766 if (!GetIntegerId(js->GetArgument(3), &id)) {
716 PrintError(js, "Must specify collection object id: functions/id"); 767 PrintError(js, "Must specify collection object id: functions/id");
717 return; 768 return true;
718 } 769 }
719 Function& func = Function::Handle(); 770 Function& func = Function::Handle();
720 func ^= cls.FunctionFromIndex(id); 771 func ^= cls.FunctionFromIndex(id);
721 if (func.IsNull()) { 772 if (func.IsNull()) {
722 PrintError(js, "Function %" Pd " not found", id); 773 PrintError(js, "Function %" Pd " not found", id);
723 return; 774 return true;
724 } 775 }
725 func.PrintToJSONStream(js, false); 776 func.PrintToJSONStream(js, false);
777 return true;
726 } 778 }
727 779
728 780
729 static void HandleClassesImplicitClosures(Isolate* isolate, const Class& cls, 781 static bool HandleClassesImplicitClosures(Isolate* isolate, const Class& cls,
730 JSONStream* js) { 782 JSONStream* js) {
731 intptr_t id; 783 intptr_t id;
732 if (js->num_arguments() > 4) { 784 if (js->num_arguments() > 4) {
733 PrintError(js, "Command too long"); 785 PrintError(js, "Command too long");
734 return; 786 return true;
735 } 787 }
736 if (!GetIntegerId(js->GetArgument(3), &id)) { 788 if (!GetIntegerId(js->GetArgument(3), &id)) {
737 PrintError(js, "Must specify collection object id: implicit_closures/id"); 789 PrintError(js, "Must specify collection object id: implicit_closures/id");
738 return; 790 return true;
739 } 791 }
740 Function& func = Function::Handle(); 792 Function& func = Function::Handle();
741 func ^= cls.ImplicitClosureFunctionFromIndex(id); 793 func ^= cls.ImplicitClosureFunctionFromIndex(id);
742 if (func.IsNull()) { 794 if (func.IsNull()) {
743 PrintError(js, "Implicit closure function %" Pd " not found", id); 795 PrintError(js, "Implicit closure function %" Pd " not found", id);
744 return; 796 return true;
745 } 797 }
746 func.PrintToJSONStream(js, false); 798 func.PrintToJSONStream(js, false);
799 return true;
747 } 800 }
748 801
749 802
750 static void HandleClassesFields(Isolate* isolate, const Class& cls, 803 static bool HandleClassesFields(Isolate* isolate, const Class& cls,
751 JSONStream* js) { 804 JSONStream* js) {
752 intptr_t id; 805 intptr_t id;
753 if (js->num_arguments() > 4) { 806 if (js->num_arguments() > 4) {
754 PrintError(js, "Command too long"); 807 PrintError(js, "Command too long");
755 return; 808 return true;
756 } 809 }
757 if (!GetIntegerId(js->GetArgument(3), &id)) { 810 if (!GetIntegerId(js->GetArgument(3), &id)) {
758 PrintError(js, "Must specify collection object id: fields/id"); 811 PrintError(js, "Must specify collection object id: fields/id");
759 return; 812 return true;
760 } 813 }
761 Field& field = Field::Handle(cls.FieldFromIndex(id)); 814 Field& field = Field::Handle(cls.FieldFromIndex(id));
762 if (field.IsNull()) { 815 if (field.IsNull()) {
763 PrintError(js, "Field %" Pd " not found", id); 816 PrintError(js, "Field %" Pd " not found", id);
764 return; 817 return true;
765 } 818 }
766 field.PrintToJSONStream(js, false); 819 field.PrintToJSONStream(js, false);
820 return true;
767 } 821 }
768 822
769 823
770 static void HandleClasses(Isolate* isolate, JSONStream* js) { 824 static bool HandleClasses(Isolate* isolate, JSONStream* js) {
771 if (js->num_arguments() == 1) { 825 if (js->num_arguments() == 1) {
772 ClassTable* table = isolate->class_table(); 826 ClassTable* table = isolate->class_table();
773 table->PrintToJSONStream(js); 827 table->PrintToJSONStream(js);
774 return; 828 return true;
775 } 829 }
776 ASSERT(js->num_arguments() >= 2); 830 ASSERT(js->num_arguments() >= 2);
777 intptr_t id; 831 intptr_t id;
778 if (!GetIntegerId(js->GetArgument(1), &id)) { 832 if (!GetIntegerId(js->GetArgument(1), &id)) {
779 PrintError(js, "Must specify collection object id: /classes/id"); 833 PrintError(js, "Must specify collection object id: /classes/id");
780 return; 834 return true;
781 } 835 }
782 ClassTable* table = isolate->class_table(); 836 ClassTable* table = isolate->class_table();
783 if (!table->IsValidIndex(id)) { 837 if (!table->IsValidIndex(id)) {
784 PrintError(js, "%" Pd " is not a valid class id.", id);; 838 PrintError(js, "%" Pd " is not a valid class id.", id);;
785 return; 839 return true;
786 } 840 }
787 Class& cls = Class::Handle(table->At(id)); 841 Class& cls = Class::Handle(table->At(id));
788 if (js->num_arguments() == 2) { 842 if (js->num_arguments() == 2) {
789 cls.PrintToJSONStream(js, false); 843 cls.PrintToJSONStream(js, false);
790 return; 844 return true;
791 } else if (js->num_arguments() >= 3) { 845 } else if (js->num_arguments() >= 3) {
792 const char* second = js->GetArgument(2); 846 const char* second = js->GetArgument(2);
793 if (!strcmp(second, "closures")) { 847 if (!strcmp(second, "closures")) {
794 HandleClassesClosures(isolate, cls, js); 848 return HandleClassesClosures(isolate, cls, js);
795 } else if (!strcmp(second, "fields")) { 849 } else if (!strcmp(second, "fields")) {
796 HandleClassesFields(isolate, cls, js); 850 return HandleClassesFields(isolate, cls, js);
797 } else if (!strcmp(second, "functions")) { 851 } else if (!strcmp(second, "functions")) {
798 HandleClassesFunctions(isolate, cls, js); 852 return HandleClassesFunctions(isolate, cls, js);
799 } else if (!strcmp(second, "implicit_closures")) { 853 } else if (!strcmp(second, "implicit_closures")) {
800 HandleClassesImplicitClosures(isolate, cls, js); 854 return HandleClassesImplicitClosures(isolate, cls, js);
801 } else if (!strcmp(second, "dispatchers")) { 855 } else if (!strcmp(second, "dispatchers")) {
802 HandleClassesDispatchers(isolate, cls, js); 856 return HandleClassesDispatchers(isolate, cls, js);
803 } else { 857 } else {
804 PrintError(js, "Invalid sub collection %s", second); 858 PrintError(js, "Invalid sub collection %s", second);
859 return true;
805 } 860 }
806 return;
807 } 861 }
808 UNREACHABLE(); 862 UNREACHABLE();
863 return true;
809 } 864 }
810 865
811 866
812 static void HandleLibrary(Isolate* isolate, JSONStream* js) { 867 static bool HandleLibrary(Isolate* isolate, JSONStream* js) {
813 if (js->num_arguments() == 1) { 868 if (js->num_arguments() == 1) {
814 const Library& lib = 869 const Library& lib =
815 Library::Handle(isolate->object_store()->root_library()); 870 Library::Handle(isolate->object_store()->root_library());
816 lib.PrintToJSONStream(js, false); 871 lib.PrintToJSONStream(js, false);
817 return; 872 return true;
818 } 873 }
819 PrintGenericError(js); 874 PrintError(js, "Command too long");
875 return true;
820 } 876 }
821 877
822 878
823 static void HandleLibraries(Isolate* isolate, JSONStream* js) { 879 static bool HandleLibraries(Isolate* isolate, JSONStream* js) {
824 // TODO(johnmccutchan): Support fields and functions on libraries. 880 // TODO(johnmccutchan): Support fields and functions on libraries.
825 REQUIRE_COLLECTION_ID("libraries"); 881 REQUIRE_COLLECTION_ID("libraries");
826 const GrowableObjectArray& libs = 882 const GrowableObjectArray& libs =
827 GrowableObjectArray::Handle(isolate->object_store()->libraries()); 883 GrowableObjectArray::Handle(isolate->object_store()->libraries());
828 ASSERT(!libs.IsNull()); 884 ASSERT(!libs.IsNull());
829 intptr_t id = 0; 885 intptr_t id = 0;
830 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1), 886 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1),
831 id, js); 887 id, js);
832 Library& lib = Library::Handle(); 888 Library& lib = Library::Handle();
833 lib ^= libs.At(id); 889 lib ^= libs.At(id);
834 ASSERT(!lib.IsNull()); 890 ASSERT(!lib.IsNull());
835 lib.PrintToJSONStream(js, false); 891 lib.PrintToJSONStream(js, false);
892 return true;
836 } 893 }
837 894
838 895
839 static void HandleObjects(Isolate* isolate, JSONStream* js) { 896 static bool HandleObjects(Isolate* isolate, JSONStream* js) {
840 REQUIRE_COLLECTION_ID("objects"); 897 REQUIRE_COLLECTION_ID("objects");
841 ASSERT(js->num_arguments() >= 2); 898 ASSERT(js->num_arguments() >= 2);
842 ObjectIdRing* ring = isolate->object_id_ring(); 899 ObjectIdRing* ring = isolate->object_id_ring();
843 ASSERT(ring != NULL); 900 ASSERT(ring != NULL);
844 intptr_t id = -1; 901 intptr_t id = -1;
845 if (!GetIntegerId(js->GetArgument(1), &id)) { 902 if (!GetIntegerId(js->GetArgument(1), &id)) {
846 Object::null_object().PrintToJSONStream(js, false); 903 Object::null_object().PrintToJSONStream(js, false);
847 return; 904 return true;
848 } 905 }
849 Object& obj = Object::Handle(ring->GetObjectForId(id)); 906 Object& obj = Object::Handle(ring->GetObjectForId(id));
850 obj.PrintToJSONStream(js, false); 907 obj.PrintToJSONStream(js, false);
908 return true;
851 } 909 }
852 910
853 911
854 912
855 static void HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) { 913 static bool HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) {
856 JSONObject jsobj(js); 914 JSONObject jsobj(js);
857 jsobj.AddProperty("type", "ScriptList"); 915 jsobj.AddProperty("type", "ScriptList");
858 { 916 JSONArray members(&jsobj, "members");
859 JSONArray members(&jsobj, "members"); 917 const GrowableObjectArray& libs =
860 const GrowableObjectArray& libs =
861 GrowableObjectArray::Handle(isolate->object_store()->libraries()); 918 GrowableObjectArray::Handle(isolate->object_store()->libraries());
862 int num_libs = libs.Length(); 919 int num_libs = libs.Length();
863 Library &lib = Library::Handle(); 920 Library &lib = Library::Handle();
864 Script& script = Script::Handle(); 921 Script& script = Script::Handle();
865 for (intptr_t i = 0; i < num_libs; i++) { 922 for (intptr_t i = 0; i < num_libs; i++) {
866 lib ^= libs.At(i); 923 lib ^= libs.At(i);
867 ASSERT(!lib.IsNull()); 924 ASSERT(!lib.IsNull());
868 ASSERT(Smi::IsValid(lib.index())); 925 ASSERT(Smi::IsValid(lib.index()));
869 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts()); 926 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
870 ASSERT(!loaded_scripts.IsNull()); 927 ASSERT(!loaded_scripts.IsNull());
871 intptr_t num_scripts = loaded_scripts.Length(); 928 intptr_t num_scripts = loaded_scripts.Length();
872 for (intptr_t i = 0; i < num_scripts; i++) { 929 for (intptr_t i = 0; i < num_scripts; i++) {
873 script ^= loaded_scripts.At(i); 930 script ^= loaded_scripts.At(i);
874 members.AddValue(script); 931 members.AddValue(script);
875 }
876 } 932 }
877 } 933 }
934 return true;
878 } 935 }
879 936
880 937
881 static void HandleScriptsFetch(Isolate* isolate, JSONStream* js) { 938 static bool HandleScriptsFetch(Isolate* isolate, JSONStream* js) {
882 const GrowableObjectArray& libs = 939 const GrowableObjectArray& libs =
883 GrowableObjectArray::Handle(isolate->object_store()->libraries()); 940 GrowableObjectArray::Handle(isolate->object_store()->libraries());
884 int num_libs = libs.Length(); 941 int num_libs = libs.Length();
885 Library &lib = Library::Handle(); 942 Library &lib = Library::Handle();
886 Script& script = Script::Handle(); 943 Script& script = Script::Handle();
887 String& url = String::Handle(); 944 String& url = String::Handle();
888 const String& id = String::Handle(String::New(js->GetArgument(1))); 945 const String& id = String::Handle(String::New(js->GetArgument(1)));
889 ASSERT(!id.IsNull()); 946 ASSERT(!id.IsNull());
890 // The id is the url of the script % encoded, decode it. 947 // The id is the url of the script % encoded, decode it.
891 String& requested_url = String::Handle(String::DecodeURI(id)); 948 String& requested_url = String::Handle(String::DecodeURI(id));
892 for (intptr_t i = 0; i < num_libs; i++) { 949 for (intptr_t i = 0; i < num_libs; i++) {
893 lib ^= libs.At(i); 950 lib ^= libs.At(i);
894 ASSERT(!lib.IsNull()); 951 ASSERT(!lib.IsNull());
895 ASSERT(Smi::IsValid(lib.index())); 952 ASSERT(Smi::IsValid(lib.index()));
896 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts()); 953 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
897 ASSERT(!loaded_scripts.IsNull()); 954 ASSERT(!loaded_scripts.IsNull());
898 intptr_t num_scripts = loaded_scripts.Length(); 955 intptr_t num_scripts = loaded_scripts.Length();
899 for (intptr_t i = 0; i < num_scripts; i++) { 956 for (intptr_t i = 0; i < num_scripts; i++) {
900 script ^= loaded_scripts.At(i); 957 script ^= loaded_scripts.At(i);
901 ASSERT(!script.IsNull()); 958 ASSERT(!script.IsNull());
902 url ^= script.url(); 959 url ^= script.url();
903 if (url.Equals(requested_url)) { 960 if (url.Equals(requested_url)) {
904 script.PrintToJSONStream(js, false); 961 script.PrintToJSONStream(js, false);
905 return; 962 return true;
906 } 963 }
907 } 964 }
908 } 965 }
909 PrintError(js, "Cannot find script %s\n", requested_url.ToCString()); 966 PrintError(js, "Cannot find script %s\n", requested_url.ToCString());
967 return true;
910 } 968 }
911 969
912 970
913 static void HandleScripts(Isolate* isolate, JSONStream* js) { 971 static bool HandleScripts(Isolate* isolate, JSONStream* js) {
914 if (js->num_arguments() == 1) { 972 if (js->num_arguments() == 1) {
915 // Enumerate all scripts. 973 // Enumerate all scripts.
916 HandleScriptsEnumerate(isolate, js); 974 return HandleScriptsEnumerate(isolate, js);
917 } else if (js->num_arguments() == 2) { 975 } else if (js->num_arguments() == 2) {
918 // Fetch specific script. 976 // Fetch specific script.
919 HandleScriptsFetch(isolate, js); 977 return HandleScriptsFetch(isolate, js);
920 } else { 978 } else {
921 PrintError(js, "Command too long"); 979 PrintError(js, "Command too long");
980 return true;
922 } 981 }
923 } 982 }
924 983
925 984
926 static void HandleDebug(Isolate* isolate, JSONStream* js) { 985 static bool HandleDebug(Isolate* isolate, JSONStream* js) {
927 if (js->num_arguments() == 1) { 986 if (js->num_arguments() == 1) {
928 PrintError(js, "Must specify a subcommand"); 987 PrintError(js, "Must specify a subcommand");
929 return; 988 return true;
930 } 989 }
931 const char* command = js->GetArgument(1); 990 const char* command = js->GetArgument(1);
932 if (!strcmp(command, "breakpoints")) { 991 if (!strcmp(command, "breakpoints")) {
933 if (js->num_arguments() == 2) { 992 if (js->num_arguments() == 2) {
934 // Print breakpoint list. 993 // Print breakpoint list.
935 JSONObject jsobj(js); 994 JSONObject jsobj(js);
936 jsobj.AddProperty("type", "BreakpointList"); 995 jsobj.AddProperty("type", "BreakpointList");
937 JSONArray jsarr(&jsobj, "breakpoints"); 996 JSONArray jsarr(&jsobj, "breakpoints");
938 isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr); 997 isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr);
939 998 return true;
940 } else if (js->num_arguments() == 3) { 999 } else if (js->num_arguments() == 3) {
941 // Print individual breakpoint. 1000 // Print individual breakpoint.
942 intptr_t id = 0; 1001 intptr_t id = 0;
943 SourceBreakpoint* bpt = NULL; 1002 SourceBreakpoint* bpt = NULL;
944 if (GetIntegerId(js->GetArgument(2), &id)) { 1003 if (GetIntegerId(js->GetArgument(2), &id)) {
945 bpt = isolate->debugger()->GetBreakpointById(id); 1004 bpt = isolate->debugger()->GetBreakpointById(id);
946 } 1005 }
947 if (bpt != NULL) { 1006 if (bpt != NULL) {
948 bpt->PrintToJSONStream(js); 1007 bpt->PrintToJSONStream(js);
1008 return true;
949 } else { 1009 } else {
950 PrintError(js, "Unrecognized breakpoint id %s", js->GetArgument(2)); 1010 PrintError(js, "Unrecognized breakpoint id %s", js->GetArgument(2));
1011 return true;
951 } 1012 }
952
953 } else { 1013 } else {
954 PrintError(js, "Command too long"); 1014 PrintError(js, "Command too long");
1015 return true;
955 } 1016 }
956 } else { 1017 } else {
957 PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1)); 1018 PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1));
1019 return true;
958 } 1020 }
959 } 1021 }
960 1022
961 1023
962 static void HandleCpu(Isolate* isolate, JSONStream* js) { 1024 static bool HandleCode(Isolate* isolate, JSONStream* js) {
963 JSONObject jsobj(js);
964 jsobj.AddProperty("type", "CPU");
965 jsobj.AddProperty("architecture", CPU::Id());
966 }
967
968
969 static void HandleCode(Isolate* isolate, JSONStream* js) {
970 REQUIRE_COLLECTION_ID("code"); 1025 REQUIRE_COLLECTION_ID("code");
971 uintptr_t pc; 1026 uintptr_t pc;
972 if (!GetUnsignedIntegerId(js->GetArgument(1), &pc, 16)) { 1027 if (!GetUnsignedIntegerId(js->GetArgument(1), &pc, 16)) {
973 PrintError(js, "Must specify code address: code/c0deadd0."); 1028 PrintError(js, "Must specify code address: code/c0deadd0.");
974 return; 1029 return true;
975 } 1030 }
976 Code& code = Code::Handle(Code::LookupCode(pc)); 1031 Code& code = Code::Handle(Code::LookupCode(pc));
977 if (code.IsNull()) { 1032 if (code.IsNull()) {
978 PrintError(js, "Could not find code at %" Px "", pc); 1033 PrintError(js, "Could not find code at %" Px "", pc);
979 return; 1034 return true;
980 } 1035 }
981 code.PrintToJSONStream(js, false); 1036 code.PrintToJSONStream(js, false);
1037 return true;
982 } 1038 }
983 1039
984 1040
985 static void HandleProfile(Isolate* isolate, JSONStream* js) { 1041 static bool HandleProfile(Isolate* isolate, JSONStream* js) {
986 Profiler::PrintToJSONStream(isolate, js, true); 1042 Profiler::PrintToJSONStream(isolate, js, true);
1043 return true;
987 } 1044 }
988 1045
989 1046
990 static ServiceMessageHandlerEntry __message_handlers[] = { 1047 static IsolateMessageHandlerEntry isolate_handlers[] = {
991 { "_echo", HandleEcho }, 1048 { "_echo", HandleIsolateEcho },
992 { "classes", HandleClasses }, 1049 { "classes", HandleClasses },
993 { "code", HandleCode }, 1050 { "code", HandleCode },
994 { "cpu", HandleCpu },
995 { "debug", HandleDebug }, 1051 { "debug", HandleDebug },
996 { "libraries", HandleLibraries }, 1052 { "libraries", HandleLibraries },
997 { "library", HandleLibrary }, 1053 { "library", HandleLibrary },
998 { "name", HandleName }, 1054 { "name", HandleName },
999 { "objecthistogram", HandleObjectHistogram}, 1055 { "objecthistogram", HandleObjectHistogram},
1000 { "objects", HandleObjects }, 1056 { "objects", HandleObjects },
1001 { "profile", HandleProfile }, 1057 { "profile", HandleProfile },
1002 { "scripts", HandleScripts }, 1058 { "scripts", HandleScripts },
1003 { "stacktrace", HandleStackTrace }, 1059 { "stacktrace", HandleStackTrace },
1004 }; 1060 };
1005 1061
1006 1062
1007 static void HandleFallthrough(Isolate* isolate, JSONStream* js) { 1063 static IsolateMessageHandler FindIsolateMessageHandler(const char* command) {
1008 JSONObject jsobj(js); 1064 intptr_t num_message_handlers = sizeof(isolate_handlers) /
1009 jsobj.AddProperty("type", "Error"); 1065 sizeof(isolate_handlers[0]);
1010 jsobj.AddProperty("text", "request not understood.");
1011 PrintArgumentsAndOptions(jsobj, js);
1012 }
1013
1014
1015 static ServiceMessageHandler FindServiceMessageHandler(const char* command) {
1016 intptr_t num_message_handlers = sizeof(__message_handlers) /
1017 sizeof(__message_handlers[0]);
1018 for (intptr_t i = 0; i < num_message_handlers; i++) { 1066 for (intptr_t i = 0; i < num_message_handlers; i++) {
1019 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; 1067 const IsolateMessageHandlerEntry& entry = isolate_handlers[i];
1020 if (!strcmp(command, entry.command)) { 1068 if (!strcmp(command, entry.command)) {
1021 return entry.handler; 1069 return entry.handler;
1022 } 1070 }
1023 } 1071 }
1024 return HandleFallthrough; 1072 return NULL;
1073 }
1074
1075
1076 void Service::HandleRootMessage(const Instance& msg) {
1077 Isolate* isolate = Isolate::Current();
1078 ASSERT(!msg.IsNull());
1079 ASSERT(msg.IsGrowableObjectArray());
1080
1081 {
1082 StackZone zone(isolate);
1083 HANDLESCOPE(isolate);
1084
1085 const GrowableObjectArray& message = GrowableObjectArray::Cast(msg);
1086 // Message is a list with four entries.
1087 ASSERT(message.Length() == 4);
1088
1089 Instance& reply_port = Instance::Handle(isolate);
1090 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
1091 GrowableObjectArray& option_keys = GrowableObjectArray::Handle(isolate);
1092 GrowableObjectArray& option_values = GrowableObjectArray::Handle(isolate);
1093 reply_port ^= message.At(0);
1094 path ^= message.At(1);
1095 option_keys ^= message.At(2);
1096 option_values ^= message.At(3);
1097
1098 ASSERT(!path.IsNull());
1099 ASSERT(!option_keys.IsNull());
1100 ASSERT(!option_values.IsNull());
1101 // Path always has at least one entry in it.
1102 ASSERT(path.Length() > 0);
1103 // Same number of option keys as values.
1104 ASSERT(option_keys.Length() == option_values.Length());
1105
1106 String& pathSegment = String::Handle();
1107 pathSegment ^= path.At(0);
1108 ASSERT(!pathSegment.IsNull());
1109
1110 RootMessageHandler handler =
1111 FindRootMessageHandler(pathSegment.ToCString());
1112 {
1113 JSONStream js;
1114 SetupJSONStream(&js, zone.GetZone(),
1115 reply_port, path, option_keys, option_values);
1116 if (handler == NULL) {
1117 PrintError(&js, "Unrecognized path");
1118 PostReply(&js);
1119 } else {
1120 if (handler(&js)) {
1121 // Handler returns true if the reply is ready to be posted.
1122 PostReply(&js);
1123 }
1124 }
1125 }
1126 }
1127 }
1128
1129
1130 static bool HandleRootEcho(JSONStream* js) {
1131 JSONObject jsobj(js);
1132 jsobj.AddProperty("type", "message");
1133 PrintArgumentsAndOptions(jsobj, js);
1134 return true;
1135 }
1136
1137
1138 static bool HandleCpu(JSONStream* js) {
1139 JSONObject jsobj(js);
1140 jsobj.AddProperty("type", "CPU");
1141 jsobj.AddProperty("architecture", CPU::Id());
1142 return true;
1143 }
1144
1145
1146 static RootMessageHandlerEntry root_handlers[] = {
1147 { "_echo", HandleRootEcho },
1148 { "cpu", HandleCpu },
1149 };
1150
1151
1152 static RootMessageHandler FindRootMessageHandler(const char* command) {
1153 intptr_t num_message_handlers = sizeof(root_handlers) /
1154 sizeof(root_handlers[0]);
1155 for (intptr_t i = 0; i < num_message_handlers; i++) {
1156 const RootMessageHandlerEntry& entry = root_handlers[i];
1157 if (!strcmp(command, entry.command)) {
1158 return entry.handler;
1159 }
1160 }
1161 return NULL;
1025 } 1162 }
1026 1163
1027 } // namespace dart 1164 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service/message.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698