| 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 "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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |