Index: runtime/vm/service.cc |
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc |
index cff1f2819d34e85f5dbb8a2a6533170a449116f1..fe8aaa1b197084bb3e0518bcb6461d126f602382 100644 |
--- a/runtime/vm/service.cc |
+++ b/runtime/vm/service.cc |
@@ -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 { |
@@ -251,7 +252,7 @@ static void HandleEcho(Isolate* isolate, JSONStream* js) { |
} |
-static bool GetIntegerId(const char* s, intptr_t* id) { |
+static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) { |
if ((s == NULL) || (*s == '\0')) { |
// Empty string. |
return false; |
@@ -262,7 +263,28 @@ static bool GetIntegerId(const char* s, intptr_t* id) { |
} |
intptr_t r = 0; |
char* end_ptr = NULL; |
- r = strtol(s, &end_ptr, 10); |
+ 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; |
@@ -274,54 +296,104 @@ static bool GetIntegerId(const char* s, intptr_t* id) { |
static void HandleClassesClosures(Isolate* isolate, const Class& cls, |
JSONStream* js) { |
- const GrowableObjectArray& closures = |
- GrowableObjectArray::Handle(cls.closures()); |
intptr_t id; |
if (js->num_arguments() > 4) { |
PrintError(js, "Command too long"); |
return; |
} |
- CHECK_COLLECTION_ID_BOUNDS("closures", closures.Length(), js->GetArgument(3), |
- id, js); |
- Function& function = Function::Handle(); |
- function ^= closures.At(id); |
- ASSERT(!function.IsNull()); |
- function.PrintToJSONStream(js, false); |
+ 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) { |
- const Array& functions = |
- Array::Handle(cls.functions()); |
intptr_t id; |
if (js->num_arguments() > 4) { |
PrintError(js, "Command too long"); |
return; |
} |
- CHECK_COLLECTION_ID_BOUNDS("functions", functions.Length(), |
- js->GetArgument(3), id, js); |
- Function& function = Function::Handle(); |
- function ^= functions.At(id); |
- ASSERT(!function.IsNull()); |
- function.PrintToJSONStream(js, false); |
+ 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) { |
- const Array& fields = |
- Array::Handle(cls.fields()); |
intptr_t id; |
if (js->num_arguments() > 4) { |
PrintError(js, "Command too long"); |
return; |
} |
- CHECK_COLLECTION_ID_BOUNDS("fields", fields.Length(), js->GetArgument(3), |
- id, js); |
- Field& field = Field::Handle(); |
- field ^= fields.At(id); |
- ASSERT(!field.IsNull()); |
+ 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); |
} |
@@ -355,6 +427,10 @@ static void HandleClasses(Isolate* isolate, JSONStream* js) { |
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); |
} |
@@ -521,9 +597,31 @@ static void HandleCpu(Isolate* isolate, JSONStream* js) { |
} |
+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 }, |
@@ -531,6 +629,7 @@ static ServiceMessageHandlerEntry __message_handlers[] = { |
{ "name", HandleName }, |
{ "objecthistogram", HandleObjectHistogram}, |
{ "objects", HandleObjects }, |
+ { "profile", HandleProfile }, |
{ "scripts", HandleScripts }, |
{ "stacktrace", HandleStackTrace }, |
}; |