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