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

Unified Diff: dart/runtime/vm/service.cc

Issue 119673004: Version 1.1.0-dev.5.2 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dart/runtime/vm/raw_object.h ('k') | dart/runtime/vm/service_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/runtime/vm/service.cc
===================================================================
--- dart/runtime/vm/service.cc (revision 31530)
+++ dart/runtime/vm/service.cc (working copy)
@@ -14,6 +14,7 @@
#include "vm/object_id_ring.h"
#include "vm/object_store.h"
#include "vm/port.h"
+#include "vm/profiler.h"
namespace dart {
@@ -196,15 +197,15 @@
jsobj.AddProperty("type", "StackTrace");
JSONArray jsarr(&jsobj, "members");
intptr_t n_frames = stack->Length();
- String& url = String::Handle();
String& function = String::Handle();
+ Script& script = Script::Handle();
for (int i = 0; i < n_frames; i++) {
ActivationFrame* frame = stack->FrameAt(i);
- url ^= frame->SourceUrl();
+ script ^= frame->SourceScript();
function ^= frame->function().UserVisibleName();
JSONObject jsobj(&jsarr);
jsobj.AddProperty("name", function.ToCString());
- jsobj.AddProperty("url", url.ToCString());
+ jsobj.AddProperty("script", script);
jsobj.AddProperty("line", frame->LineNumber());
jsobj.AddProperty("function", frame->function());
jsobj.AddProperty("code", frame->code());
@@ -239,6 +240,164 @@
}
+#define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \
+ if (!GetIntegerId(arg, &id)) { \
+ PrintError(js, "Must specify collection object id: %s/id", collection); \
+ return; \
+ } \
+ if ((id < 0) || (id >= length)) { \
+ PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \
+ length); \
+ return; \
+ }
+
+
+static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) {
+ if ((s == NULL) || (*s == '\0')) {
+ // Empty string.
+ return false;
+ }
+ if (id == NULL) {
+ // No id pointer.
+ return false;
+ }
+ intptr_t r = 0;
+ char* end_ptr = NULL;
+ r = strtol(s, &end_ptr, base);
+ if (end_ptr == s) {
+ // String was not advanced at all, cannot be valid.
+ return false;
+ }
+ *id = r;
+ return true;
+}
+
+
+static bool GetUnsignedIntegerId(const char* s, uintptr_t* id, int base = 10) {
+ if ((s == NULL) || (*s == '\0')) {
+ // Empty string.
+ return false;
+ }
+ if (id == NULL) {
+ // No id pointer.
+ return false;
+ }
+ uintptr_t r = 0;
+ char* end_ptr = NULL;
+ r = strtoul(s, &end_ptr, base);
+ if (end_ptr == s) {
+ // String was not advanced at all, cannot be valid.
+ return false;
+ }
+ *id = r;
+ return true;
+}
+
+
+static void HandleClassesClosures(Isolate* isolate, const Class& cls,
+ JSONStream* js) {
+ intptr_t id;
+ if (js->num_arguments() > 4) {
+ PrintError(js, "Command too long");
+ return;
+ }
+ if (!GetIntegerId(js->GetArgument(3), &id)) {
+ PrintError(js, "Must specify collection object id: closures/id");
+ return;
+ }
+ Function& func = Function::Handle();
+ func ^= cls.ClosureFunctionFromIndex(id);
+ if (func.IsNull()) {
+ PrintError(js, "Closure function %" Pd " not found", id);
+ return;
+ }
+ func.PrintToJSONStream(js, false);
+}
+
+
+static void HandleClassesDispatchers(Isolate* isolate, const Class& cls,
+ JSONStream* js) {
+ intptr_t id;
+ if (js->num_arguments() > 4) {
+ PrintError(js, "Command too long");
+ return;
+ }
+ if (!GetIntegerId(js->GetArgument(3), &id)) {
+ PrintError(js, "Must specify collection object id: dispatchers/id");
+ return;
+ }
+ Function& func = Function::Handle();
+ func ^= cls.InvocationDispatcherFunctionFromIndex(id);
+ if (func.IsNull()) {
+ PrintError(js, "Dispatcher %" Pd " not found", id);
+ return;
+ }
+ func.PrintToJSONStream(js, false);
+}
+
+
+static void HandleClassesFunctions(Isolate* isolate, const Class& cls,
+ JSONStream* js) {
+ intptr_t id;
+ if (js->num_arguments() > 4) {
+ PrintError(js, "Command too long");
+ return;
+ }
+ if (!GetIntegerId(js->GetArgument(3), &id)) {
+ PrintError(js, "Must specify collection object id: functions/id");
+ return;
+ }
+ Function& func = Function::Handle();
+ func ^= cls.FunctionFromIndex(id);
+ if (func.IsNull()) {
+ PrintError(js, "Function %" Pd " not found", id);
+ return;
+ }
+ func.PrintToJSONStream(js, false);
+}
+
+
+static void HandleClassesImplicitClosures(Isolate* isolate, const Class& cls,
+ JSONStream* js) {
+ intptr_t id;
+ if (js->num_arguments() > 4) {
+ PrintError(js, "Command too long");
+ return;
+ }
+ if (!GetIntegerId(js->GetArgument(3), &id)) {
+ PrintError(js, "Must specify collection object id: implicit_closures/id");
+ return;
+ }
+ Function& func = Function::Handle();
+ func ^= cls.ImplicitClosureFunctionFromIndex(id);
+ if (func.IsNull()) {
+ PrintError(js, "Implicit closure function %" Pd " not found", id);
+ return;
+ }
+ func.PrintToJSONStream(js, false);
+}
+
+
+static void HandleClassesFields(Isolate* isolate, const Class& cls,
+ JSONStream* js) {
+ intptr_t id;
+ if (js->num_arguments() > 4) {
+ PrintError(js, "Command too long");
+ return;
+ }
+ if (!GetIntegerId(js->GetArgument(3), &id)) {
+ PrintError(js, "Must specify collection object id: fields/id");
+ return;
+ }
+ Field& field = Field::Handle(cls.FieldFromIndex(id));
+ if (field.IsNull()) {
+ PrintError(js, "Field %" Pd " not found", id);
+ return;
+ }
+ field.PrintToJSONStream(js, false);
+}
+
+
static void HandleClasses(Isolate* isolate, JSONStream* js) {
if (js->num_arguments() == 1) {
ClassTable* table = isolate->class_table();
@@ -246,14 +405,38 @@
return;
}
ASSERT(js->num_arguments() >= 2);
- intptr_t id = atoi(js->GetArgument(1));
+ intptr_t id;
+ if (!GetIntegerId(js->GetArgument(1), &id)) {
+ PrintError(js, "Must specify collection object id: /classes/id");
+ return;
+ }
ClassTable* table = isolate->class_table();
if (!table->IsValidIndex(id)) {
- Object::null_object().PrintToJSONStream(js, false);
- } else {
- Class& cls = Class::Handle(table->At(id));
+ PrintError(js, "%" Pd " is not a valid class id.", id);;
+ return;
+ }
+ Class& cls = Class::Handle(table->At(id));
+ if (js->num_arguments() == 2) {
cls.PrintToJSONStream(js, false);
+ return;
+ } else if (js->num_arguments() >= 3) {
+ const char* second = js->GetArgument(2);
+ if (!strcmp(second, "closures")) {
+ HandleClassesClosures(isolate, cls, js);
+ } else if (!strcmp(second, "fields")) {
+ HandleClassesFields(isolate, cls, js);
+ } else if (!strcmp(second, "functions")) {
+ HandleClassesFunctions(isolate, cls, js);
+ } else if (!strcmp(second, "implicit_closures")) {
+ HandleClassesImplicitClosures(isolate, cls, js);
+ } else if (!strcmp(second, "dispatchers")) {
+ HandleClassesDispatchers(isolate, cls, js);
+ } else {
+ PrintError(js, "Invalid sub collection %s", second);
+ }
+ return;
}
+ UNREACHABLE();
}
@@ -268,17 +451,109 @@
}
+static void HandleLibraries(Isolate* isolate, JSONStream* js) {
+ // TODO(johnmccutchan): Support fields and functions on libraries.
+ REQUIRE_COLLECTION_ID("libraries");
+ const GrowableObjectArray& libs =
+ GrowableObjectArray::Handle(isolate->object_store()->libraries());
+ ASSERT(!libs.IsNull());
+ intptr_t id = 0;
+ CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1),
+ id, js);
+ Library& lib = Library::Handle();
+ lib ^= libs.At(id);
+ ASSERT(!lib.IsNull());
+ lib.PrintToJSONStream(js, false);
+}
+
+
static void HandleObjects(Isolate* isolate, JSONStream* js) {
REQUIRE_COLLECTION_ID("objects");
ASSERT(js->num_arguments() >= 2);
ObjectIdRing* ring = isolate->object_id_ring();
ASSERT(ring != NULL);
- intptr_t id = atoi(js->GetArgument(1));
+ intptr_t id = -1;
+ if (!GetIntegerId(js->GetArgument(1), &id)) {
+ Object::null_object().PrintToJSONStream(js, false);
+ return;
+ }
Object& obj = Object::Handle(ring->GetObjectForId(id));
obj.PrintToJSONStream(js, false);
}
+
+static void HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) {
+ JSONObject jsobj(js);
+ jsobj.AddProperty("type", "ScriptList");
+ {
+ JSONArray members(&jsobj, "members");
+ const GrowableObjectArray& libs =
+ GrowableObjectArray::Handle(isolate->object_store()->libraries());
+ int num_libs = libs.Length();
+ Library &lib = Library::Handle();
+ Script& script = Script::Handle();
+ for (intptr_t i = 0; i < num_libs; i++) {
+ lib ^= libs.At(i);
+ ASSERT(!lib.IsNull());
+ ASSERT(Smi::IsValid(lib.index()));
+ const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
+ ASSERT(!loaded_scripts.IsNull());
+ intptr_t num_scripts = loaded_scripts.Length();
+ for (intptr_t i = 0; i < num_scripts; i++) {
+ script ^= loaded_scripts.At(i);
+ members.AddValue(script);
+ }
+ }
+ }
+}
+
+
+static void HandleScriptsFetch(Isolate* isolate, JSONStream* js) {
+ const GrowableObjectArray& libs =
+ GrowableObjectArray::Handle(isolate->object_store()->libraries());
+ int num_libs = libs.Length();
+ Library &lib = Library::Handle();
+ Script& script = Script::Handle();
+ String& url = String::Handle();
+ const String& id = String::Handle(String::New(js->GetArgument(1)));
+ ASSERT(!id.IsNull());
+ // The id is the url of the script % encoded, decode it.
+ String& requested_url = String::Handle(String::DecodeURI(id));
+ for (intptr_t i = 0; i < num_libs; i++) {
+ lib ^= libs.At(i);
+ ASSERT(!lib.IsNull());
+ ASSERT(Smi::IsValid(lib.index()));
+ const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
+ ASSERT(!loaded_scripts.IsNull());
+ intptr_t num_scripts = loaded_scripts.Length();
+ for (intptr_t i = 0; i < num_scripts; i++) {
+ script ^= loaded_scripts.At(i);
+ ASSERT(!script.IsNull());
+ url ^= script.url();
+ if (url.Equals(requested_url)) {
+ script.PrintToJSONStream(js, false);
+ return;
+ }
+ }
+ }
+ PrintError(js, "Cannot find script %s\n", requested_url.ToCString());
+}
+
+
+static void HandleScripts(Isolate* isolate, JSONStream* js) {
+ if (js->num_arguments() == 1) {
+ // Enumerate all scripts.
+ HandleScriptsEnumerate(isolate, js);
+ } else if (js->num_arguments() == 2) {
+ // Fetch specific script.
+ HandleScriptsFetch(isolate, js);
+ } else {
+ PrintError(js, "Command too long");
+ }
+}
+
+
static void HandleDebug(Isolate* isolate, JSONStream* js) {
if (js->num_arguments() == 1) {
PrintError(js, "Must specify a subcommand");
@@ -295,8 +570,11 @@
} else if (js->num_arguments() == 3) {
// Print individual breakpoint.
- intptr_t id = atoi(js->GetArgument(2));
- SourceBreakpoint* bpt = isolate->debugger()->GetBreakpointById(id);
+ intptr_t id = 0;
+ SourceBreakpoint* bpt = NULL;
+ if (GetIntegerId(js->GetArgument(2), &id)) {
+ bpt = isolate->debugger()->GetBreakpointById(id);
+ }
if (bpt != NULL) {
bpt->PrintToJSONStream(js);
} else {
@@ -319,15 +597,40 @@
}
+static void HandleCode(Isolate* isolate, JSONStream* js) {
+ REQUIRE_COLLECTION_ID("code");
+ uintptr_t pc;
+ if (!GetUnsignedIntegerId(js->GetArgument(1), &pc, 16)) {
+ PrintError(js, "Must specify code address: code/c0deadd0.");
+ return;
+ }
+ Code& code = Code::Handle(Code::LookupCode(pc));
+ if (code.IsNull()) {
+ PrintError(js, "Could not find code at %" Px "", pc);
+ return;
+ }
+ code.PrintToJSONStream(js, false);
+}
+
+
+static void HandleProfile(Isolate* isolate, JSONStream* js) {
+ Profiler::PrintToJSONStream(isolate, js, true);
+}
+
+
static ServiceMessageHandlerEntry __message_handlers[] = {
{ "_echo", HandleEcho },
{ "classes", HandleClasses },
+ { "code", HandleCode },
{ "cpu", HandleCpu },
{ "debug", HandleDebug },
+ { "libraries", HandleLibraries },
{ "library", HandleLibrary },
{ "name", HandleName },
{ "objecthistogram", HandleObjectHistogram},
{ "objects", HandleObjects },
+ { "profile", HandleProfile },
+ { "scripts", HandleScripts },
{ "stacktrace", HandleStackTrace },
};
« no previous file with comments | « dart/runtime/vm/raw_object.h ('k') | dart/runtime/vm/service_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698