Index: runtime/vm/service.cc |
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc |
index cff1f2819d34e85f5dbb8a2a6533170a449116f1..54f5a5b9d2ccfef7a78b28b82000cb3a3e4238e3 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; |
@@ -290,8 +312,29 @@ static void HandleClassesClosures(Isolate* isolate, const Class& cls, |
} |
+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 " is not a function.", id); |
+ return; |
+ } |
+ func.PrintToJSONStream(js, false); |
+} |
+ |
+ |
static void HandleClassesFunctions(Isolate* isolate, const Class& cls, |
- JSONStream* js) { |
+ JSONStream* js, bool implicit_closure) { |
const Array& functions = |
Array::Handle(cls.functions()); |
intptr_t id; |
@@ -299,12 +342,28 @@ static void HandleClassesFunctions(Isolate* isolate, const Class& cls, |
PrintError(js, "Command too long"); |
return; |
} |
- CHECK_COLLECTION_ID_BOUNDS("functions", functions.Length(), |
- js->GetArgument(3), id, js); |
+ if (implicit_closure) { |
+ CHECK_COLLECTION_ID_BOUNDS("implicit_closures", functions.Length(), |
+ js->GetArgument(3), id, js); |
+ } else { |
+ 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 (!implicit_closure) { |
+ function.PrintToJSONStream(js, false); |
+ return; |
+ } |
+ if (!function.HasImplicitClosureFunction()) { |
+ PrintError(js, "Function %" Pd " does not have an implicit closure.", id); |
+ return; |
+ } |
+ Function& closure_function = Function::Handle(); |
+ closure_function ^= function.ImplicitClosureFunction(); |
+ ASSERT(!closure_function.IsNull()); |
+ closure_function.PrintToJSONStream(js, false); |
} |
@@ -354,7 +413,11 @@ static void HandleClasses(Isolate* isolate, JSONStream* js) { |
} else if (!strcmp(second, "fields")) { |
HandleClassesFields(isolate, cls, js); |
} else if (!strcmp(second, "functions")) { |
- HandleClassesFunctions(isolate, cls, js); |
+ HandleClassesFunctions(isolate, cls, js, false); |
+ } else if (!strcmp(second, "implicit_closures")) { |
+ HandleClassesFunctions(isolate, cls, js, true); |
+ } else if (!strcmp(second, "dispatchers")) { |
+ HandleClassesDispatchers(isolate, cls, js); |
} else { |
PrintError(js, "Invalid sub collection %s", second); |
} |
@@ -521,9 +584,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 +616,7 @@ static ServiceMessageHandlerEntry __message_handlers[] = { |
{ "name", HandleName }, |
{ "objecthistogram", HandleObjectHistogram}, |
{ "objects", HandleObjects }, |
+ { "profile", HandleProfile }, |
{ "scripts", HandleScripts }, |
{ "stacktrace", HandleStackTrace }, |
}; |