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

Side by Side Diff: runtime/vm/service.cc

Issue 98253009: Refactor VM service IDs (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/service.h" 5 #include "vm/service.h"
6 6
7 #include "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"
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 } 146 }
147 { 147 {
148 JSONArray jsarr(&jsobj, "option_values"); 148 JSONArray jsarr(&jsobj, "option_values");
149 for (intptr_t i = 0; i < js->num_options(); i++) { 149 for (intptr_t i = 0; i < js->num_options(); i++) {
150 jsarr.AddValue(js->GetOptionValue(i)); 150 jsarr.AddValue(js->GetOptionValue(i));
151 } 151 }
152 } 152 }
153 } 153 }
154 154
155 155
156 static void PrintCollectionErrorResponse(const char* collection_name,
157 JSONStream* js) {
158 JSONObject jsobj(js);
159 jsobj.AddProperty("type", "Error");
160 jsobj.AddPropertyF("text", "Must specify collection object id: %s/id",
161 collection_name);
162 }
163
164
165 static void PrintCollectionRangeErrorResponse(const char* collection_name,
166 JSONStream* js,
167 intptr_t id,
168 intptr_t length) {
169 JSONObject jsobj(js);
170 jsobj.AddProperty("type", "Error");
171 jsobj.AddPropertyF("text", "%s id (%" Pd ") must be in [0, %" Pd ").",
172 collection_name, id, length);
173 }
174
175
156 static void PrintGenericError(JSONStream* js) { 176 static void PrintGenericError(JSONStream* js) {
157 JSONObject jsobj(js); 177 JSONObject jsobj(js);
158 jsobj.AddProperty("type", "Error"); 178 jsobj.AddProperty("type", "Error");
159 jsobj.AddProperty("text", "Invalid request."); 179 jsobj.AddProperty("text", "Invalid request.");
160 PrintArgumentsAndOptions(jsobj, js); 180 PrintArgumentsAndOptions(jsobj, js);
161 } 181 }
162 182
163 183
164 static void PrintError(JSONStream* js, const char* format, ...) { 184 static void PrintError(JSONStream* js, const char* format, ...) {
165 Isolate* isolate = Isolate::Current(); 185 Isolate* isolate = Isolate::Current();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 } 251 }
232 252
233 253
234 // Print an error message if there is no ID argument. 254 // Print an error message if there is no ID argument.
235 #define REQUIRE_COLLECTION_ID(collection) \ 255 #define REQUIRE_COLLECTION_ID(collection) \
236 if (js->num_arguments() == 1) { \ 256 if (js->num_arguments() == 1) { \
237 PrintError(js, "Must specify collection object id: /%s/id", collection); \ 257 PrintError(js, "Must specify collection object id: /%s/id", collection); \
238 return; \ 258 return; \
239 } 259 }
240 260
261 #define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \
262 if (!GetIntegerId(arg, &id)) { \
263 PrintCollectionErrorResponse(collection, js); \
turnidge 2013/12/19 20:39:29 Why not just use PrintError (accepts format string
Cutch 2013/12/19 21:53:58 Done.
264 return; \
265 } \
266 if ((id < 0) || (id >= length)) { \
267 PrintCollectionRangeErrorResponse(collection, js, id, length); \
268 }
269
270
271 static bool GetIntegerId(const char* s, intptr_t* id) {
272 if ((s == NULL) || (*s == '\0')) {
273 // Empty string.
274 return false;
275 }
276 if (id == NULL) {
277 // No id pointer.
278 return false;
279 }
280 intptr_t r = 0;
281 char* end_ptr = NULL;
282 r = strtol(s, &end_ptr, 10);
283 if (end_ptr == s) {
284 // String was not advanced at all, cannot be valid.
285 return false;
286 }
287 *id = r;
288 return true;
289 }
290
291
292 static void HandleClassesClosures(Isolate* isolate, const Class& cls,
293 JSONStream* js) {
294 const GrowableObjectArray& closures =
295 GrowableObjectArray::Handle(cls.closures());
296 intptr_t id;
297 CHECK_COLLECTION_ID_BOUNDS("closures", closures.Length(), js->GetArgument(3),
298 id, js);
299 Function& function = Function::Handle();
300 function ^= closures.At(id);
301 ASSERT(!function.IsNull());
302 function.PrintToJSONStream(js, false);
303 }
304
305
306 static void HandleClassesFunctions(Isolate* isolate, const Class& cls,
307 JSONStream* js) {
308 const Array& functions =
309 Array::Handle(cls.functions());
310 intptr_t id;
311 CHECK_COLLECTION_ID_BOUNDS("functions", functions.Length(),
312 js->GetArgument(3), id, js);
313 Function& function = Function::Handle();
314 function ^= functions.At(id);
315 ASSERT(!function.IsNull());
316 function.PrintToJSONStream(js, false);
317 }
318
319
320 static void HandleClassesFields(Isolate* isolate, const Class& cls,
321 JSONStream* js) {
322 const Array& fields =
323 Array::Handle(cls.fields());
324 intptr_t id;
325 CHECK_COLLECTION_ID_BOUNDS("fields", fields.Length(), js->GetArgument(3),
326 id, js);
327 Field& field = Field::Handle();
328 field ^= fields.At(id);
329 ASSERT(!field.IsNull());
330 field.PrintToJSONStream(js, false);
331 }
332
241 333
242 static void HandleClasses(Isolate* isolate, JSONStream* js) { 334 static void HandleClasses(Isolate* isolate, JSONStream* js) {
243 if (js->num_arguments() == 1) { 335 if (js->num_arguments() == 1) {
244 ClassTable* table = isolate->class_table(); 336 ClassTable* table = isolate->class_table();
245 table->PrintToJSONStream(js); 337 table->PrintToJSONStream(js);
246 return; 338 return;
247 } 339 }
248 ASSERT(js->num_arguments() >= 2); 340 ASSERT(js->num_arguments() >= 2);
249 intptr_t id = atoi(js->GetArgument(1)); 341 intptr_t id;
342 if (!GetIntegerId(js->GetArgument(1), &id)) {
343 PrintGenericError(js);
turnidge 2013/12/19 20:39:29 Use PrintError and give a nice message here.
Cutch 2013/12/19 21:53:58 Done.
344 return;
345 }
250 ClassTable* table = isolate->class_table(); 346 ClassTable* table = isolate->class_table();
251 if (!table->IsValidIndex(id)) { 347 if (!table->IsValidIndex(id)) {
252 Object::null_object().PrintToJSONStream(js, false); 348 Object::null_object().PrintToJSONStream(js, false);
turnidge 2013/12/19 20:39:29 So null is what we give for an invalid reference?
Cutch 2013/12/19 21:53:58 Legacy code, returning Error now.
349 return;
350 }
351 Class& cls = Class::Handle(table->At(id));
352 if (js->num_arguments() == 2) {
353 cls.PrintToJSONStream(js, false);
354 return;
355 } else if (js->num_arguments() == 4) {
turnidge 2013/12/19 20:39:29 Maybe just check that num_arguments is >= 3 and le
Cutch 2013/12/19 21:53:58 Done.
356 const char* second = js->GetArgument(2);
357 if (!strcmp(second, "closures")) {
358 HandleClassesClosures(isolate, cls, js);
359 } else if (!strcmp(second, "fields")) {
360 HandleClassesFields(isolate, cls, js);
361 } else if (!strcmp(second, "functions")) {
362 HandleClassesFunctions(isolate, cls, js);
363 } else {
364 PrintError(js, "Invalid sub collection %s", second);
365 }
253 } else { 366 } else {
254 Class& cls = Class::Handle(table->At(id)); 367 PrintGenericError(js);
turnidge 2013/12/19 20:39:29 This goes away if you let helpers handle sub-error
Cutch 2013/12/19 21:53:58 Done.
255 cls.PrintToJSONStream(js, false);
256 } 368 }
257 } 369 }
turnidge 2013/12/19 20:39:29 Here and below... You should have my changes now
Cutch 2013/12/19 21:53:58 Done.
258 370
259 371
260 static void HandleLibrary(Isolate* isolate, JSONStream* js) { 372 static void HandleLibrary(Isolate* isolate, JSONStream* js) {
261 if (js->num_arguments() == 1) { 373 if (js->num_arguments() == 1) {
262 const Library& lib = 374 const Library& lib =
263 Library::Handle(isolate->object_store()->root_library()); 375 Library::Handle(isolate->object_store()->root_library());
264 lib.PrintToJSONStream(js, false); 376 lib.PrintToJSONStream(js, false);
265 return; 377 return;
266 } 378 }
267 PrintGenericError(js); 379 PrintGenericError(js);
268 } 380 }
269 381
270 382
383 static void HandleLibraries(Isolate* isolate, JSONStream* js) {
384 REQUIRE_COLLECTION_ID("libraries");
385 const GrowableObjectArray& libs =
386 GrowableObjectArray::Handle(isolate->object_store()->libraries());
387 ASSERT(!libs.IsNull());
388 intptr_t id = 0;
389 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1),
390 id, js);
391 Library& lib = Library::Handle();
392 lib ^= libs.At(id);
393 ASSERT(!lib.IsNull());
394 lib.PrintToJSONStream(js, false);
turnidge 2013/12/19 20:39:29 So do we not yet support Fields/Functions for libr
Cutch 2013/12/19 21:53:58 Good point! TODO added.
395 }
396
397
271 static void HandleObjects(Isolate* isolate, JSONStream* js) { 398 static void HandleObjects(Isolate* isolate, JSONStream* js) {
272 REQUIRE_COLLECTION_ID("objects"); 399 REQUIRE_COLLECTION_ID("objects");
273 ASSERT(js->num_arguments() >= 2); 400 ASSERT(js->num_arguments() >= 2);
274 ObjectIdRing* ring = isolate->object_id_ring(); 401 ObjectIdRing* ring = isolate->object_id_ring();
275 ASSERT(ring != NULL); 402 ASSERT(ring != NULL);
276 intptr_t id = atoi(js->GetArgument(1)); 403 intptr_t id = -1;
404 if (!GetIntegerId(js->GetArgument(1), &id)) {
405 Object::null_object().PrintToJSONStream(js, false);
turnidge 2013/12/19 20:39:29 Again, null object seems ambiguous. I might prefe
406 return;
407 }
277 Object& obj = Object::Handle(ring->GetObjectForId(id)); 408 Object& obj = Object::Handle(ring->GetObjectForId(id));
278 obj.PrintToJSONStream(js, false); 409 obj.PrintToJSONStream(js, false);
279 } 410 }
280 411
281 412
413
414 static void HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) {
415 JSONObject jsobj(js);
416 jsobj.AddProperty("type", "ScriptList");
417 {
418 JSONArray members(&jsobj, "members");
419 const GrowableObjectArray& libs =
420 GrowableObjectArray::Handle(isolate->object_store()->libraries());
421 int num_libs = libs.Length();
422 Library &lib = Library::Handle();
423 Script& script = Script::Handle();
424 for (intptr_t i = 0; i < num_libs; i++) {
425 lib ^= libs.At(i);
426 ASSERT(!lib.IsNull());
427 ASSERT(Smi::IsValid(lib.index()));
428 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
429 ASSERT(!loaded_scripts.IsNull());
430 intptr_t num_scripts = loaded_scripts.Length();
431 for (intptr_t i = 0; i < num_scripts; i++) {
432 script ^= loaded_scripts.At(i);
433 members.AddValue(script);
434 }
435 }
436 }
437 }
438
439
440 static void HandleScriptsFetch(Isolate* isolate, JSONStream* js) {
441 const GrowableObjectArray& libs =
442 GrowableObjectArray::Handle(isolate->object_store()->libraries());
443 int num_libs = libs.Length();
444 Library &lib = Library::Handle();
445 Script& script = Script::Handle();
446 String& url = String::Handle();
447 const String& id = String::Handle(String::New(js->GetArgument(1)));
448 ASSERT(!id.IsNull());
449 // The id is the url of the script % encoded, decode it.
450 String& requested_url = String::Handle(String::DecodeURI(id));
451 for (intptr_t i = 0; i < num_libs; i++) {
452 lib ^= libs.At(i);
453 ASSERT(!lib.IsNull());
454 ASSERT(Smi::IsValid(lib.index()));
455 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
456 ASSERT(!loaded_scripts.IsNull());
457 intptr_t num_scripts = loaded_scripts.Length();
458 for (intptr_t i = 0; i < num_scripts; i++) {
459 script ^= loaded_scripts.At(i);
460 ASSERT(!script.IsNull());
461 url ^= script.url();
462 if (url.Equals(requested_url)) {
463 script.PrintToJSONStream(js, false);
464 return;
465 }
466 }
467 }
468 PrintError(js, "Cannot find script %s\n", requested_url.ToCString());
469 }
470
471
472 static void HandleScripts(Isolate* isolate, JSONStream* js) {
473 if (js->num_arguments() == 1) {
474 // Enumerate all scripts.
475 HandleScriptsEnumerate(isolate, js);
476 } else if (js->num_arguments() == 2) {
477 // Fetch specific script.
478 HandleScriptsFetch(isolate, js);
479 } else {
480 PrintError(js, "Command too long");
481 }
482 }
483
484
282 static void HandleDebug(Isolate* isolate, JSONStream* js) { 485 static void HandleDebug(Isolate* isolate, JSONStream* js) {
283 if (js->num_arguments() == 1) { 486 if (js->num_arguments() == 1) {
284 PrintError(js, "Must specify a subcommand"); 487 PrintError(js, "Must specify a subcommand");
285 return; 488 return;
286 } 489 }
287 const char* command = js->GetArgument(1); 490 const char* command = js->GetArgument(1);
288 if (!strcmp(command, "breakpoints")) { 491 if (!strcmp(command, "breakpoints")) {
289 if (js->num_arguments() == 2) { 492 if (js->num_arguments() == 2) {
290 // Print breakpoint list. 493 // Print breakpoint list.
291 JSONObject jsobj(js); 494 JSONObject jsobj(js);
(...skipping 25 matching lines...) Expand all
317 jsobj.AddProperty("type", "CPU"); 520 jsobj.AddProperty("type", "CPU");
318 jsobj.AddProperty("architecture", CPU::Id()); 521 jsobj.AddProperty("architecture", CPU::Id());
319 } 522 }
320 523
321 524
322 static ServiceMessageHandlerEntry __message_handlers[] = { 525 static ServiceMessageHandlerEntry __message_handlers[] = {
323 { "_echo", HandleEcho }, 526 { "_echo", HandleEcho },
324 { "classes", HandleClasses }, 527 { "classes", HandleClasses },
325 { "cpu", HandleCpu }, 528 { "cpu", HandleCpu },
326 { "debug", HandleDebug }, 529 { "debug", HandleDebug },
530 { "libraries", HandleLibraries },
327 { "library", HandleLibrary }, 531 { "library", HandleLibrary },
turnidge 2013/12/19 20:39:29 Is the plan to have both library and libraries? I
Cutch 2013/12/19 21:53:58 library is how you get to the root library. librar
328 { "name", HandleName }, 532 { "name", HandleName },
329 { "objecthistogram", HandleObjectHistogram}, 533 { "objecthistogram", HandleObjectHistogram},
330 { "objects", HandleObjects }, 534 { "objects", HandleObjects },
535 { "scripts", HandleScripts },
331 { "stacktrace", HandleStackTrace }, 536 { "stacktrace", HandleStackTrace },
332 }; 537 };
333 538
334 539
335 static void HandleFallthrough(Isolate* isolate, JSONStream* js) { 540 static void HandleFallthrough(Isolate* isolate, JSONStream* js) {
336 JSONObject jsobj(js); 541 JSONObject jsobj(js);
337 jsobj.AddProperty("type", "Error"); 542 jsobj.AddProperty("type", "Error");
338 jsobj.AddProperty("text", "request not understood."); 543 jsobj.AddProperty("text", "request not understood.");
339 PrintArgumentsAndOptions(jsobj, js); 544 PrintArgumentsAndOptions(jsobj, js);
340 } 545 }
341 546
342 547
343 static ServiceMessageHandler FindServiceMessageHandler(const char* command) { 548 static ServiceMessageHandler FindServiceMessageHandler(const char* command) {
344 intptr_t num_message_handlers = sizeof(__message_handlers) / 549 intptr_t num_message_handlers = sizeof(__message_handlers) /
345 sizeof(__message_handlers[0]); 550 sizeof(__message_handlers[0]);
346 for (intptr_t i = 0; i < num_message_handlers; i++) { 551 for (intptr_t i = 0; i < num_message_handlers; i++) {
347 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; 552 const ServiceMessageHandlerEntry& entry = __message_handlers[i];
348 if (!strcmp(command, entry.command)) { 553 if (!strcmp(command, entry.command)) {
349 return entry.handler; 554 return entry.handler;
350 } 555 }
351 } 556 }
352 return HandleFallthrough; 557 return HandleFallthrough;
353 } 558 }
354 559
355 } // namespace dart 560 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698