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

Unified Diff: runtime/vm/service.cc

Issue 920813003: Refactor service code and service method parameters (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 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 | « runtime/vm/service.h ('k') | runtime/vm/service_isolate.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/service.cc
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index c05ba8c277015cf11625e02ac3e5b3863fb19227..f60cd9655fd3dfc6ce6ee7736c0810900f7a05aa 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -27,6 +27,7 @@
#include "vm/port.h"
#include "vm/profiler_service.h"
#include "vm/reusable_handles.h"
+#include "vm/service_isolate.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/unicode.h"
@@ -34,962 +35,686 @@
namespace dart {
-DEFINE_FLAG(bool, trace_service, false, "Trace VM service requests.");
-DEFINE_FLAG(bool, trace_service_pause_events, false,
- "Trace VM service isolate pause events.");
+DECLARE_FLAG(bool, trace_service);
+DECLARE_FLAG(bool, trace_service_pause_events);
DECLARE_FLAG(bool, enable_type_checks);
DECLARE_FLAG(bool, enable_asserts);
-struct ResourcesEntry {
- const char* path_;
- const char* resource_;
- int length_;
-};
-
-extern ResourcesEntry __service_resources_[];
-
-class Resources {
- public:
- static const int kNoSuchInstance = -1;
- static int ResourceLookup(const char* path, const char** resource) {
- ResourcesEntry* table = ResourceTable();
- for (int i = 0; table[i].path_ != NULL; i++) {
- const ResourcesEntry& entry = table[i];
- if (strcmp(path, entry.path_) == 0) {
- *resource = entry.resource_;
- ASSERT(entry.length_ > 0);
- return entry.length_;
- }
- }
- return kNoSuchInstance;
- }
-
- static const char* Path(int idx) {
- ASSERT(idx >= 0);
- ResourcesEntry* entry = At(idx);
- if (entry == NULL) {
- return NULL;
- }
- ASSERT(entry->path_ != NULL);
- return entry->path_;
- }
+// TODO(johnmccutchan): Unify embedder service handler lists and their APIs.
+EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
+EmbedderServiceHandler* Service::root_service_handler_head_ = NULL;
+uint32_t Service::event_mask_ = 0;
+struct ServiceMethodDescriptor;
+ServiceMethodDescriptor* FindMethod(const char* method_name);
- static int Length(int idx) {
- ASSERT(idx >= 0);
- ResourcesEntry* entry = At(idx);
- if (entry == NULL) {
- return kNoSuchInstance;
- }
- ASSERT(entry->path_ != NULL);
- return entry->length_;
- }
+static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
+ void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
+ return reinterpret_cast<uint8_t*>(new_ptr);
+}
- static const uint8_t* Resource(int idx) {
- ASSERT(idx >= 0);
- ResourcesEntry* entry = At(idx);
- if (entry == NULL) {
- return NULL;
+static void PrintRequest(const JSONObject& obj, JSONStream* js) {
+ JSONObject jsobj(&obj, "request");
+ jsobj.AddProperty("method", js->method());
+ {
+ JSONArray jsarr(&jsobj, "param_keys");
+ for (intptr_t i = 0; i < js->num_params(); i++) {
+ jsarr.AddValue(js->GetParamKey(i));
}
- return reinterpret_cast<const uint8_t*>(entry->resource_);
}
-
- private:
- static ResourcesEntry* At(int idx) {
- ASSERT(idx >= 0);
- ResourcesEntry* table = ResourceTable();
- for (int i = 0; table[i].path_ != NULL; i++) {
- if (idx == i) {
- return &table[i];
- }
+ {
+ JSONArray jsarr(&jsobj, "param_values");
+ for (intptr_t i = 0; i < js->num_params(); i++) {
+ jsarr.AddValue(js->GetParamValue(i));
}
- return NULL;
- }
-
- static ResourcesEntry* ResourceTable() {
- return &__service_resources_[0];
- }
-
- DISALLOW_ALLOCATION();
- DISALLOW_IMPLICIT_CONSTRUCTORS(Resources);
-};
-
-
-class EmbedderServiceHandler {
- public:
- explicit EmbedderServiceHandler(const char* name) : name_(NULL),
- callback_(NULL),
- user_data_(NULL),
- next_(NULL) {
- ASSERT(name != NULL);
- name_ = strdup(name);
- }
-
- ~EmbedderServiceHandler() {
- free(name_);
- }
-
- const char* name() const { return name_; }
-
- Dart_ServiceRequestCallback callback() const { return callback_; }
- void set_callback(Dart_ServiceRequestCallback callback) {
- callback_ = callback;
- }
-
- void* user_data() const { return user_data_; }
- void set_user_data(void* user_data) {
- user_data_ = user_data;
- }
-
- EmbedderServiceHandler* next() const { return next_; }
- void set_next(EmbedderServiceHandler* next) {
- next_ = next;
}
+}
- private:
- char* name_;
- Dart_ServiceRequestCallback callback_;
- void* user_data_;
- EmbedderServiceHandler* next_;
-};
+static void PrintError(JSONStream* js,
+ const char* format, ...) {
+ Isolate* isolate = Isolate::Current();
-class LibraryCoverageFilter : public CoverageFilter {
- public:
- explicit LibraryCoverageFilter(const Library& lib) : lib_(lib) {}
- bool ShouldOutputCoverageFor(const Library& lib,
- const Script& script,
- const Class& cls,
- const Function& func) const {
- return lib.raw() == lib_.raw();
- }
- private:
- const Library& lib_;
-};
+ va_list args;
+ va_start(args, format);
+ intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+ va_end(args);
+ char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
+ va_list args2;
+ va_start(args2, format);
+ OS::VSNPrint(buffer, (len + 1), format, args2);
+ va_end(args2);
-class ScriptCoverageFilter : public CoverageFilter {
- public:
- explicit ScriptCoverageFilter(const Script& script)
- : script_(script) {}
- bool ShouldOutputCoverageFor(const Library& lib,
- const Script& script,
- const Class& cls,
- const Function& func) const {
- return script.raw() == script_.raw();
- }
- private:
- const Script& script_;
-};
+ JSONObject jsobj(js);
+ jsobj.AddProperty("type", "Error");
+ jsobj.AddProperty("message", buffer);
+ PrintRequest(jsobj, js);
+}
-class ClassCoverageFilter : public CoverageFilter {
- public:
- explicit ClassCoverageFilter(const Class& cls) : cls_(cls) {}
- bool ShouldOutputCoverageFor(const Library& lib,
- const Script& script,
- const Class& cls,
- const Function& func) const {
- return cls.raw() == cls_.raw();
- }
- private:
- const Class& cls_;
-};
+static void PrintMissingParamError(JSONStream* js,
+ const char* param) {
+ PrintError(js, "%s expects the '%s' parameter",
+ js->method(), param);
+}
-class FunctionCoverageFilter : public CoverageFilter {
- public:
- explicit FunctionCoverageFilter(const Function& func) : func_(func) {}
- bool ShouldOutputCoverageFor(const Library& lib,
- const Script& script,
- const Class& cls,
- const Function& func) const {
- return func.raw() == func_.raw();
- }
- private:
- const Function& func_;
-};
+static void PrintInvalidParamError(JSONStream* js,
+ const char* param) {
+ PrintError(js, "%s: invalid '%s' parameter: %s",
+ js->method(), param, js->LookupParam(param));
+}
-static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
- void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
- return reinterpret_cast<uint8_t*>(new_ptr);
+static void PrintUnrecognizedMethodError(JSONStream* js) {
+ PrintError(js, "unrecognized method: %s", js->method());
}
-static void SendIsolateServiceMessage(Dart_NativeArguments args) {
- NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->isolate();
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
- GET_NON_NULL_NATIVE_ARGUMENT(SendPort, sp, arguments->NativeArgAt(0));
- GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(1));
+static void PrintErrorWithKind(JSONStream* js,
+ const char* kind,
+ const char* format, ...) {
+ Isolate* isolate = Isolate::Current();
- // Set the type of the OOB message.
- message.SetAt(0, Smi::Handle(isolate, Smi::New(Message::kServiceOOBMsg)));
+ va_list args;
+ va_start(args, format);
+ intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+ va_end(args);
- // Serialize message.
- uint8_t* data = NULL;
- MessageWriter writer(&data, &allocator, false);
- writer.WriteMessage(message);
+ char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
+ va_list args2;
+ va_start(args2, format);
+ OS::VSNPrint(buffer, (len + 1), format, args2);
+ va_end(args2);
- // TODO(turnidge): Throw an exception when the return value is false?
- PortMap::PostMessage(new Message(sp.Id(), data, writer.BytesWritten(),
- Message::kOOBPriority));
+ JSONObject jsobj(js);
+ jsobj.AddProperty("type", "Error");
+ jsobj.AddProperty("id", "");
+ jsobj.AddProperty("kind", kind);
+ jsobj.AddProperty("message", buffer);
+ PrintRequest(jsobj, js);
}
-static void SendRootServiceMessage(Dart_NativeArguments args) {
- NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->isolate();
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(0));
- Service::HandleRootMessage(message);
+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;
}
-class ScopeStopwatch : public ValueObject {
- public:
- explicit ScopeStopwatch(const char* name) : name_(name) {
- start_ = OS::GetCurrentTimeMicros();
+static bool GetUnsignedIntegerId(const char* s, uintptr_t* id, int base = 10) {
+ if ((s == NULL) || (*s == '\0')) {
+ // Empty string.
+ return false;
}
-
- int64_t GetElapsed() const {
- int64_t end = OS::GetCurrentTimeMicros();
- ASSERT(end >= start_);
- return end - start_;
+ if (id == NULL) {
+ // No id pointer.
+ return false;
}
-
- ~ScopeStopwatch() {
- int64_t elapsed = GetElapsed();
- OS::Print("[%" Pd "] %s took %" Pd64 " micros.\n",
- OS::ProcessId(), name_, elapsed);
+ 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;
}
-
- private:
- const char* name_;
- int64_t start_;
-};
-
-
-bool Service::IsRunning() {
- MonitorLocker ml(monitor_);
- return (service_port_ != ILLEGAL_PORT) && (service_isolate_ != NULL);
+ *id = r;
+ return true;
}
-void Service::SetServicePort(Dart_Port port) {
- MonitorLocker ml(monitor_);
- service_port_ = port;
+static bool GetInteger64Id(const char* s, int64_t* id, int base = 10) {
+ if ((s == NULL) || (*s == '\0')) {
+ // Empty string.
+ return false;
+ }
+ if (id == NULL) {
+ // No id pointer.
+ return false;
+ }
+ int64_t r = 0;
+ char* end_ptr = NULL;
+ r = strtoll(s, &end_ptr, base);
+ if (end_ptr == s) {
+ // String was not advanced at all, cannot be valid.
+ return false;
+ }
+ *id = r;
+ return true;
}
-void Service::SetServiceIsolate(Isolate* isolate) {
- MonitorLocker ml(monitor_);
- service_isolate_ = isolate;
- if (service_isolate_ != NULL) {
- service_isolate_->is_service_isolate_ = true;
+// Scans the string until the '-' character. Returns pointer to string
+// at '-' character. Returns NULL if not found.
+static const char* ScanUntilDash(const char* s) {
+ if ((s == NULL) || (*s == '\0')) {
+ // Empty string.
+ return NULL;
+ }
+ while (*s != '\0') {
+ if (*s == '-') {
+ return s;
+ }
+ s++;
}
+ return NULL;
}
-bool Service::HasServiceIsolate() {
- MonitorLocker ml(monitor_);
- return service_isolate_ != NULL;
+static bool GetCodeId(const char* s, int64_t* timestamp, uword* address) {
+ if ((s == NULL) || (*s == '\0')) {
+ // Empty string.
+ return false;
+ }
+ if ((timestamp == NULL) || (address == NULL)) {
+ // Bad arguments.
+ return false;
+ }
+ // Extract the timestamp.
+ if (!GetInteger64Id(s, timestamp, 16) || (*timestamp < 0)) {
+ return false;
+ }
+ s = ScanUntilDash(s);
+ if (s == NULL) {
+ return false;
+ }
+ // Skip the dash.
+ s++;
+ // Extract the PC.
+ if (!GetUnsignedIntegerId(s, address, 16)) {
+ return false;
+ }
+ return true;
}
-bool Service::IsServiceIsolate(Isolate* isolate) {
- MonitorLocker ml(monitor_);
- return isolate == service_isolate_;
-}
+// TODO(johnmccutchan): Split into separate file and write unit tests.
+class MethodParameter {
+ public:
+ MethodParameter(const char* name, bool required)
+ : name_(name), required_(required) {
+ }
-Dart_Port Service::WaitForLoadPort() {
- MonitorLocker ml(monitor_);
+ virtual ~MethodParameter() { }
- while (initializing_ && (load_port_ == ILLEGAL_PORT)) {
- ml.Wait();
+ virtual bool Validate(const char* value) const {
+ return true;
}
- return load_port_;
-}
-
+ const char* name() const {
+ return name_;
+ }
-Dart_Port Service::LoadPort() {
- MonitorLocker ml(monitor_);
- return load_port_;
-}
+ bool required() const {
+ return required_;
+ }
+ private:
+ const char* name_;
+ bool required_;
+};
-void Service::SetLoadPort(Dart_Port port) {
- MonitorLocker ml(monitor_);
- load_port_ = port;
-}
+class NoSuchParameter : public MethodParameter {
+ public:
+ explicit NoSuchParameter(const char* name)
+ : MethodParameter(name, false) {
+ }
-void Service::SetEventMask(uint32_t mask) {
- event_mask_ = mask;
-}
+ virtual bool Validate(const char* value) const {
+ return (value == NULL);
+ }
+};
-static void SetEventMask(Dart_NativeArguments args) {
- NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->isolate();
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
- GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(0));
- Service::SetEventMask(mask.AsTruncatedUint32Value());
-}
+#define NO_ISOLATE_PARAMETER new NoSuchParameter("isolateId")
-// These must be kept in sync with service/constants.dart
-#define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1
-#define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2
+class BoolParameter : public MethodParameter {
+ public:
+ BoolParameter(const char* name, bool required)
+ : MethodParameter(name, required) {
+ }
+ virtual bool Validate(const char* value) const {
+ if (value == NULL) {
+ return false;
+ }
+ return (strcmp("true", value) == 0) || (strcmp("false", value) == 0);
+ }
-static RawArray* MakeServiceControlMessage(Dart_Port port_id, intptr_t code,
- const String& name) {
- const Array& list = Array::Handle(Array::New(4));
- ASSERT(!list.IsNull());
- const Integer& code_int = Integer::Handle(Integer::New(code));
- const Integer& port_int = Integer::Handle(Integer::New(port_id));
- const SendPort& send_port = SendPort::Handle(SendPort::New(port_id));
- list.SetAt(0, code_int);
- list.SetAt(1, port_int);
- list.SetAt(2, send_port);
- list.SetAt(3, name);
- return list.raw();
-}
+ static bool Interpret(const char* value) {
+ return strcmp("true", value) == 0;
+ }
+};
-class RegisterRunningIsolatesVisitor : public IsolateVisitor {
+class IdParameter : public MethodParameter {
public:
- explicit RegisterRunningIsolatesVisitor(Isolate* service_isolate)
- : IsolateVisitor(),
- register_function_(Function::Handle(service_isolate)),
- service_isolate_(service_isolate) {
- ASSERT(Service::IsServiceIsolate(Isolate::Current()));
- // Get library.
- const String& library_url = Symbols::DartVMService();
- ASSERT(!library_url.IsNull());
- const Library& library =
- Library::Handle(Library::LookupLibrary(library_url));
- ASSERT(!library.IsNull());
- // Get function.
- const String& function_name =
- String::Handle(String::New("_registerIsolate"));
- ASSERT(!function_name.IsNull());
- register_function_ = library.LookupFunctionAllowPrivate(function_name);
- ASSERT(!register_function_.IsNull());
- }
-
- virtual void VisitIsolate(Isolate* isolate) {
- ASSERT(Service::IsServiceIsolate(Isolate::Current()));
- if (Service::IsServiceIsolate(isolate) ||
- (isolate == Dart::vm_isolate())) {
- // We do not register the service or vm isolate.
- return;
- }
- // Setup arguments for call.
- Dart_Port port_id = isolate->main_port();
- const Integer& port_int = Integer::Handle(Integer::New(port_id));
- ASSERT(!port_int.IsNull());
- const SendPort& send_port = SendPort::Handle(SendPort::New(port_id));
- const String& name = String::Handle(String::New(isolate->name()));
- ASSERT(!name.IsNull());
- const Array& args = Array::Handle(Array::New(3));
- ASSERT(!args.IsNull());
- args.SetAt(0, port_int);
- args.SetAt(1, send_port);
- args.SetAt(2, name);
- Object& r = Object::Handle(service_isolate_);
- r = DartEntry::InvokeFunction(register_function_, args);
- if (FLAG_trace_service) {
- OS::Print("vm-service: Isolate %s %" Pd64 " registered.\n",
- name.ToCString(),
- port_id);
- }
- ASSERT(!r.IsError());
+ IdParameter(const char* name, bool required)
+ : MethodParameter(name, required) {
}
- private:
- Function& register_function_;
- Isolate* service_isolate_;
+ virtual bool Validate(const char* value) const {
+ return (value != NULL);
+ }
};
-static Dart_Port ExtractPort(Isolate* isolate, Dart_Handle receivePort) {
- const ReceivePort& rp = Api::UnwrapReceivePortHandle(isolate, receivePort);
- if (rp.IsNull()) {
- return ILLEGAL_PORT;
- }
- return rp.Id();
-}
+#define ISOLATE_PARAMETER new IdParameter("isolateId", true)
-static void OnStart(Dart_NativeArguments args) {
- NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->isolate();
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
- {
- if (FLAG_trace_service) {
- OS::Print("vm-service: Booting dart:vmservice library.\n");
- }
- // Boot the dart:vmservice library.
- Dart_EnterScope();
- Dart_Handle url_str =
- Dart_NewStringFromCString(Symbols::Name(Symbols::kDartVMServiceId));
- Dart_Handle library = Dart_LookupLibrary(url_str);
- ASSERT(Dart_IsLibrary(library));
- Dart_Handle result =
- Dart_Invoke(library, Dart_NewStringFromCString("boot"), 0, NULL);
- ASSERT(!Dart_IsError(result));
- Dart_Port port = ExtractPort(isolate, result);
- ASSERT(port != ILLEGAL_PORT);
- Service::SetServicePort(port);
- Dart_ExitScope();
+class EnumParameter : public MethodParameter {
+ public:
+ EnumParameter(const char* name, bool required, const char** enums)
+ : MethodParameter(name, required),
+ enums_(enums) {
}
- {
- if (FLAG_trace_service) {
- OS::Print("vm-service: Registering running isolates.\n");
+ virtual bool Validate(const char* value) const {
+ if (value == NULL) {
+ return true;
}
- // Register running isolates with service.
- RegisterRunningIsolatesVisitor register_isolates(isolate);
- Isolate::VisitIsolates(&register_isolates);
+ for (intptr_t i = 0; enums_[i] != NULL; i++) {
+ if (strcmp(value, enums_[i]) == 0) {
+ return true;
+ }
+ }
+ return false;
}
-}
-
-
-struct VmServiceNativeEntry {
- const char* name;
- int num_arguments;
- Dart_NativeFunction function;
-};
-
-static VmServiceNativeEntry _VmServiceNativeEntries[] = {
- {"VMService_SendIsolateServiceMessage", 2, SendIsolateServiceMessage},
- {"VMService_SendRootServiceMessage", 1, SendRootServiceMessage},
- {"VMService_SetEventMask", 1, SetEventMask},
- {"VMService_OnStart", 0, OnStart },
+ private:
+ const char** enums_;
};
-static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
- int num_arguments,
- bool* auto_setup_scope) {
- const Object& obj = Object::Handle(Api::UnwrapHandle(name));
- if (!obj.IsString()) {
- return NULL;
- }
- const char* function_name = obj.ToCString();
- ASSERT(function_name != NULL);
- ASSERT(auto_setup_scope != NULL);
- *auto_setup_scope = true;
- intptr_t n =
- sizeof(_VmServiceNativeEntries) / sizeof(_VmServiceNativeEntries[0]);
- for (intptr_t i = 0; i < n; i++) {
- VmServiceNativeEntry entry = _VmServiceNativeEntries[i];
- if ((strcmp(function_name, entry.name) == 0) &&
- (num_arguments == entry.num_arguments)) {
- return entry.function;
+// If the key is not found, this function returns the last element in the
+// values array. This can be used to encode the default value.
+template<typename T>
+T EnumMapper(const char* value, const char** enums, T* values) {
+ ASSERT(value != NULL);
+ intptr_t i = 0;
+ for (i = 0; enums[i] != NULL; i++) {
+ if (strcmp(value, enums[i]) == 0) {
+ return values[i];
}
}
- return NULL;
+ // Default value.
+ return values[i];
}
-const char* Service::kIsolateName = "vm-service";
-EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
-EmbedderServiceHandler* Service::root_service_handler_head_ = NULL;
-Isolate* Service::service_isolate_ = NULL;
-Dart_Port Service::service_port_ = ILLEGAL_PORT;
-Dart_Port Service::load_port_ = ILLEGAL_PORT;
-Dart_IsolateCreateCallback Service::create_callback_ = NULL;
-Monitor* Service::monitor_ = NULL;
-bool Service::initializing_ = true;
-uint32_t Service::event_mask_ = 0;
-
-bool Service::IsServiceIsolateName(const char* name) {
- ASSERT(name != NULL);
- return strcmp(name, kIsolateName) == 0;
-}
+typedef bool (*ServiceMethodEntry)(Isolate* isolate, JSONStream* js);
-bool Service::SendIsolateStartupMessage() {
- if (!IsRunning()) {
- return false;
- }
- Isolate* isolate = Isolate::Current();
- if (IsServiceIsolate(isolate)) {
- return false;
- }
- ASSERT(isolate != NULL);
- HANDLESCOPE(isolate);
- const String& name = String::Handle(String::New(isolate->name()));
- ASSERT(!name.IsNull());
- const Array& list = Array::Handle(
- MakeServiceControlMessage(Dart_GetMainPortId(),
- VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID,
- name));
- ASSERT(!list.IsNull());
- uint8_t* data = NULL;
- MessageWriter writer(&data, &allocator, false);
- writer.WriteMessage(list);
- intptr_t len = writer.BytesWritten();
- if (FLAG_trace_service) {
- OS::Print("vm-service: Isolate %s %" Pd64 " registered.\n",
- name.ToCString(),
- Dart_GetMainPortId());
- }
- return PortMap::PostMessage(
- new Message(service_port_, data, len, Message::kNormalPriority));
-}
+struct ServiceMethodDescriptor {
+ const char* name;
+ const ServiceMethodEntry entry;
+ const MethodParameter* const * parameters;
+};
-bool Service::SendIsolateShutdownMessage() {
- if (!IsRunning()) {
- return false;
- }
- Isolate* isolate = Isolate::Current();
- if (IsServiceIsolate(isolate)) {
- return false;
- }
- ASSERT(isolate != NULL);
- HANDLESCOPE(isolate);
- const String& name = String::Handle(String::New(isolate->name()));
- ASSERT(!name.IsNull());
- const Array& list = Array::Handle(
- MakeServiceControlMessage(Dart_GetMainPortId(),
- VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID,
- name));
- ASSERT(!list.IsNull());
- uint8_t* data = NULL;
- MessageWriter writer(&data, &allocator, false);
- writer.WriteMessage(list);
- intptr_t len = writer.BytesWritten();
- if (FLAG_trace_service) {
- OS::Print("vm-service: Isolate %s %" Pd64 " deregistered.\n",
- name.ToCString(),
- Dart_GetMainPortId());
+// TODO(johnmccutchan): Do we reject unexpected parameters?
+static bool ValidateParameters(const MethodParameter* const* parameters,
+ JSONStream* js) {
+ if (parameters == NULL) {
+ return true;
}
- return PortMap::PostMessage(
- new Message(service_port_, data, len, Message::kNormalPriority));
-}
-
-
-Dart_Handle Service::GetSource(const char* name) {
- ASSERT(name != NULL);
- int i = 0;
- while (true) {
- const char* path = Resources::Path(i);
- if (path == NULL) {
- break;
+ for (intptr_t i = 0; parameters[i] != NULL; i++) {
+ const MethodParameter* parameter = parameters[i];
+ const char* name = parameter->name();
+ const bool required = parameter->required();
+ const char* value = js->LookupParam(name);
+ const bool has_parameter = (value != NULL);
+ if (required && !has_parameter) {
+ PrintMissingParamError(js, name);
+ return false;
}
- ASSERT(*path != '\0');
- // Skip the '/'.
- path++;
- if (strcmp(name, path) == 0) {
- const uint8_t* str = Resources::Resource(i);
- intptr_t length = Resources::Length(i);
- return Dart_NewStringFromUTF8(str, length);
+ if (!parameter->Validate(value)) {
+ PrintInvalidParamError(js, name);
+ return false;
}
- i++;
- }
- return Dart_Null();
-}
-
-
-Dart_Handle Service::LibraryTagHandler(Dart_LibraryTag tag,
- Dart_Handle library,
- Dart_Handle url) {
- if (tag == Dart_kCanonicalizeUrl) {
- // url is already canonicalized.
- return url;
- }
- if (tag != Dart_kSourceTag) {
- FATAL("Service::LibraryTagHandler encountered an unexpected tag.");
}
- ASSERT(tag == Dart_kSourceTag);
- const char* url_string = NULL;
- Dart_Handle result = Dart_StringToCString(url, &url_string);
- if (Dart_IsError(result)) {
- return result;
- }
- Dart_Handle source = GetSource(url_string);
- if (Dart_IsError(source)) {
- return source;
- }
- return Dart_LoadSource(library, url, source, 0, 0);
+ return true;
}
-void Service::MaybeInjectVMServiceLibrary(Isolate* isolate) {
+void Service::InvokeMethod(Isolate* isolate, const Array& msg) {
ASSERT(isolate != NULL);
- ASSERT(isolate->name() != NULL);
- if (!Service::IsServiceIsolateName(isolate->name())) {
- // Not service isolate.
- return;
- }
- if (HasServiceIsolate()) {
- // Service isolate already exists.
- return;
- }
- SetServiceIsolate(isolate);
-
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
-
- // Register dart:vmservice library.
- const String& url_str = String::Handle(Symbols::DartVMService().raw());
- const Library& library = Library::Handle(Library::New(url_str));
- library.Register();
- library.set_native_entry_resolver(VmServiceNativeResolver);
-
- // Temporarily install our library tag handler.
- isolate->set_library_tag_handler(LibraryTagHandler);
-
- // Get script source.
- const char* resource = NULL;
- const char* path = "/vmservice.dart";
- intptr_t r = Resources::ResourceLookup(path, &resource);
- ASSERT(r != Resources::kNoSuchInstance);
- ASSERT(resource != NULL);
- const String& source_str = String::Handle(
- String::FromUTF8(reinterpret_cast<const uint8_t*>(resource), r));
- ASSERT(!source_str.IsNull());
- const Script& script = Script::Handle(
- isolate, Script::New(url_str, source_str, RawScript::kLibraryTag));
-
- // Compile script.
- Dart_EnterScope(); // Need to enter scope for tag handler.
- library.SetLoadInProgress();
- const Error& error = Error::Handle(isolate,
- Compiler::Compile(library, script));
- ASSERT(error.IsNull());
- Dart_Handle result = Dart_FinalizeLoading(false);
- ASSERT(!Dart_IsError(result));
- Dart_ExitScope();
-
- // Uninstall our library tag handler.
- isolate->set_library_tag_handler(NULL);
-}
-
-
-void Service::FinishedInitializing() {
- MonitorLocker ml(monitor_);
- initializing_ = false;
- ml.NotifyAll();
-}
-
+ ASSERT(!msg.IsNull());
+ ASSERT(msg.Length() == 5);
-static void ShutdownIsolate(uword parameter) {
- Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
- ASSERT(Service::IsServiceIsolate(isolate));
{
- // Print the error if there is one. This may execute dart code to
- // print the exception object, so we need to use a StartIsolateScope.
- StartIsolateScope start_scope(isolate);
StackZone zone(isolate);
- HandleScope handle_scope(isolate);
- Error& error = Error::Handle();
- error = isolate->object_store()->sticky_error();
- if (!error.IsNull()) {
- OS::PrintErr("vm-service: Error: %s\n", error.ToErrorCString());
- }
- Dart::RunShutdownCallback();
- }
- {
- // Shut the isolate down.
- SwitchIsolateScope switch_scope(isolate);
- Dart::ShutdownIsolate();
- }
- Service::SetServiceIsolate(NULL);
- Service::SetServicePort(ILLEGAL_PORT);
- if (FLAG_trace_service) {
- OS::Print("vm-service: Shutdown.\n");
- }
-}
+ HANDLESCOPE(isolate);
+ Instance& reply_port = Instance::Handle(isolate);
+ String& method_name = String::Handle(isolate);
+ Array& param_keys = Array::Handle(isolate);
+ Array& param_values = Array::Handle(isolate);
+ reply_port ^= msg.At(1);
+ method_name ^= msg.At(2);
+ param_keys ^= msg.At(3);
+ param_values ^= msg.At(4);
-class RunServiceTask : public ThreadPool::Task {
- public:
- virtual void Run() {
- ASSERT(Isolate::Current() == NULL);
- char* error = NULL;
- Isolate* isolate = NULL;
-
- Dart_IsolateCreateCallback create_callback = Service::create_callback();
- // TODO(johnmccutchan): Support starting up service isolate without embedder
- // provided isolate creation callback.
- if (create_callback == NULL) {
- Service::FinishedInitializing();
- return;
- }
+ ASSERT(!method_name.IsNull());
+ ASSERT(!param_keys.IsNull());
+ ASSERT(!param_values.IsNull());
+ ASSERT(param_keys.Length() == param_values.Length());
- isolate =
- reinterpret_cast<Isolate*>(create_callback(Service::kIsolateName,
- NULL,
- NULL,
- NULL,
- &error));
- if (isolate == NULL) {
- OS::PrintErr("vm-service: Isolate creation error: %s\n", error);
- Service::FinishedInitializing();
- return;
+ if (!reply_port.IsSendPort()) {
+ FATAL("SendPort expected.");
}
- Isolate::SetCurrent(NULL);
-
- RunMain(isolate);
-
- Service::FinishedInitializing();
+ JSONStream js;
+ js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
+ method_name, param_keys, param_values);
- isolate->message_handler()->Run(Dart::thread_pool(),
- NULL,
- ShutdownIsolate,
- reinterpret_cast<uword>(isolate));
- }
+ const char* c_method_name = method_name.ToCString();
- protected:
- void RunMain(Isolate* isolate) {
- StartIsolateScope iso_scope(isolate);
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
- // Invoke main which will return the loadScriptPort.
- const Library& root_library =
- Library::Handle(isolate, isolate->object_store()->root_library());
- if (root_library.IsNull()) {
- if (FLAG_trace_service) {
- OS::Print("vm-service: Embedder did not install a script.");
+ ServiceMethodDescriptor* method = FindMethod(c_method_name);
+ if (method != NULL) {
+ if (!ValidateParameters(method->parameters, &js)) {
+ js.PostReply();
+ return;
}
- // Service isolate is not supported by embedder.
- return;
- }
- ASSERT(!root_library.IsNull());
- const String& entry_name = String::Handle(isolate, String::New("main"));
- ASSERT(!entry_name.IsNull());
- const Function& entry =
- Function::Handle(isolate,
- root_library.LookupFunctionAllowPrivate(entry_name));
- if (entry.IsNull()) {
- // Service isolate is not supported by embedder.
- if (FLAG_trace_service) {
- OS::Print("vm-service: Embedder did not provide a main function.");
+ if (method->entry(isolate, &js)) {
+ js.PostReply();
}
return;
}
- ASSERT(!entry.IsNull());
- const Object& result =
- Object::Handle(isolate,
- DartEntry::InvokeFunction(entry,
- Object::empty_array()));
- ASSERT(!result.IsNull());
- if (result.IsError()) {
- // Service isolate did not initialize properly.
- if (FLAG_trace_service) {
- const Error& error = Error::Cast(result);
- OS::Print("vm-service: Calling main resulted in an error: %s",
- error.ToErrorCString());
- }
+
+ EmbedderServiceHandler* handler = FindIsolateEmbedderHandler(c_method_name);
+ if (handler == NULL) {
+ handler = FindRootEmbedderHandler(c_method_name);
+ }
+
+ if (handler != NULL) {
+ EmbedderHandleMessage(handler, &js);
+ js.PostReply();
return;
}
- ASSERT(result.IsReceivePort());
- const ReceivePort& rp = ReceivePort::Cast(result);
- Service::SetLoadPort(rp.Id());
+
+ PrintUnrecognizedMethodError(&js);
+ js.PostReply();
+ return;
}
-};
+}
-void Service::RunService() {
- ASSERT(monitor_ == NULL);
- monitor_ = new Monitor();
- ASSERT(monitor_ != NULL);
- // Grab the isolate create callback here to avoid race conditions with tests
- // that change this after Dart_Initialize returns.
- create_callback_ = Isolate::CreateCallback();
- Dart::thread_pool()->Run(new RunServiceTask());
+void Service::HandleRootMessage(const Array& msg_instance) {
+ Isolate* isolate = Isolate::Current();
+ InvokeMethod(isolate, msg_instance);
}
-// A handler for a per-isolate request.
-//
-// If a handler returns true, the reply is complete and ready to be
-// posted. If a handler returns false, then it is responsible for
-// posting the reply (this can be used for asynchronous delegation of
-// the response handling).
-typedef bool (*IsolateMessageHandler)(Isolate* isolate, JSONStream* stream);
-struct IsolateMessageHandlerEntry {
- const char* method;
- IsolateMessageHandler handler;
-};
+void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) {
+ ASSERT(isolate != NULL);
+ InvokeMethod(isolate, msg);
+}
-static IsolateMessageHandler FindIsolateMessageHandler(const char* method);
+bool Service::EventMaskHas(uint32_t mask) {
+ return (event_mask_ & mask) != 0;
+}
-// A handler for a root (vm-global) request.
-//
-// If a handler returns true, the reply is complete and ready to be
-// posted. If a handler returns false, then it is responsible for
-// posting the reply (this can be used for asynchronous delegation of
-// the response handling).
-typedef bool (*RootMessageHandler)(JSONStream* stream);
-struct RootMessageHandlerEntry {
- const char* method;
- RootMessageHandler handler;
-};
+bool Service::NeedsDebuggerEvents() {
+ return ServiceIsolate::IsRunning() && EventMaskHas(kEventFamilyDebugMask);
+}
-static RootMessageHandler FindRootMessageHandler(const char* method);
+bool Service::NeedsGCEvents() {
+ return ServiceIsolate::IsRunning() && EventMaskHas(kEventFamilyGCMask);
+}
-static void PrintRequest(const JSONObject& obj, JSONStream* js) {
- JSONObject jsobj(&obj, "request");
- jsobj.AddProperty("method", js->method());
- {
- JSONArray jsarr(&jsobj, "param_keys");
- for (intptr_t i = 0; i < js->num_params(); i++) {
- jsarr.AddValue(js->GetParamKey(i));
- }
- }
- {
- JSONArray jsarr(&jsobj, "param_values");
- for (intptr_t i = 0; i < js->num_params(); i++) {
- jsarr.AddValue(js->GetParamValue(i));
- }
- }
+
+void Service::SetEventMask(uint32_t mask) {
+ event_mask_ = mask;
}
-static void PrintError(JSONStream* js,
- const char* format, ...) {
+void Service::SendEvent(intptr_t eventId, const Object& eventMessage) {
+ if (!ServiceIsolate::IsRunning()) {
+ return;
+ }
Isolate* isolate = Isolate::Current();
+ ASSERT(isolate != NULL);
+ HANDLESCOPE(isolate);
- va_list args;
- va_start(args, format);
- intptr_t len = OS::VSNPrint(NULL, 0, format, args);
- va_end(args);
+ // Construct a list of the form [eventId, eventMessage].
+ const Array& list = Array::Handle(Array::New(2));
+ ASSERT(!list.IsNull());
+ list.SetAt(0, Integer::Handle(Integer::New(eventId)));
+ list.SetAt(1, eventMessage);
- char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
- va_list args2;
- va_start(args2, format);
- OS::VSNPrint(buffer, (len + 1), format, args2);
- va_end(args2);
+ // Push the event to port_.
+ uint8_t* data = NULL;
+ MessageWriter writer(&data, &allocator, false);
+ writer.WriteMessage(list);
+ intptr_t len = writer.BytesWritten();
+ if (FLAG_trace_service) {
+ OS::Print("vm-service: Pushing event of type %" Pd ", len %" Pd "\n",
+ eventId, len);
+ }
+ // TODO(turnidge): For now we ignore failure to send an event. Revisit?
+ PortMap::PostMessage(
+ new Message(ServiceIsolate::Port(), data, len, Message::kNormalPriority));
+}
- JSONObject jsobj(js);
- jsobj.AddProperty("type", "Error");
- jsobj.AddProperty("message", buffer);
- PrintRequest(jsobj, js);
+
+void Service::SendEvent(intptr_t eventId,
+ const String& meta,
+ const uint8_t* data,
+ intptr_t size) {
+ // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data]
+ const intptr_t meta_bytes = Utf8::Length(meta);
+ const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size;
+ const TypedData& message = TypedData::Handle(
+ TypedData::New(kTypedDataUint8ArrayCid, total_bytes));
+ intptr_t offset = 0;
+ // TODO(koda): Rename these methods SetHostUint64, etc.
+ message.SetUint64(0, Utils::HostToBigEndian64(meta_bytes));
+ offset += sizeof(uint64_t);
+ {
+ NoGCScope no_gc;
+ meta.ToUTF8(static_cast<uint8_t*>(message.DataAddr(offset)), meta_bytes);
+ offset += meta_bytes;
+ }
+ // TODO(koda): It would be nice to avoid this copy (requires changes to
+ // MessageWriter code).
+ {
+ NoGCScope no_gc;
+ memmove(message.DataAddr(offset), data, size);
+ offset += size;
+ }
+ ASSERT(offset == total_bytes);
+ SendEvent(eventId, message);
}
-static void PrintMissingParamError(JSONStream* js,
- const char* param) {
- PrintError(js, "%s expects the '%s' parameter",
- js->method(), param);
+void Service::HandleGCEvent(GCEvent* event) {
+ JSONStream js;
+ event->PrintJSON(&js);
+ const String& message = String::Handle(String::New(js.ToCString()));
+ SendEvent(kEventFamilyGC, message);
}
-static void PrintInvalidParamError(JSONStream* js,
- const char* param) {
- PrintError(js, "%s: invalid '%s' parameter: %s",
- js->method(), param, js->LookupParam(param));
+void Service::HandleDebuggerEvent(DebuggerEvent* event) {
+ JSONStream js;
+ event->PrintJSON(&js);
+ const String& message = String::Handle(String::New(js.ToCString()));
+ SendEvent(kEventFamilyDebug, message);
}
-static void PrintErrorWithKind(JSONStream* js,
- const char* kind,
- const char* format, ...) {
- Isolate* isolate = Isolate::Current();
+class EmbedderServiceHandler {
+ public:
+ explicit EmbedderServiceHandler(const char* name) : name_(NULL),
+ callback_(NULL),
+ user_data_(NULL),
+ next_(NULL) {
+ ASSERT(name != NULL);
+ name_ = strdup(name);
+ }
- va_list args;
- va_start(args, format);
- intptr_t len = OS::VSNPrint(NULL, 0, format, args);
- va_end(args);
+ ~EmbedderServiceHandler() {
+ free(name_);
+ }
- char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
- va_list args2;
- va_start(args2, format);
- OS::VSNPrint(buffer, (len + 1), format, args2);
- va_end(args2);
+ const char* name() const { return name_; }
- JSONObject jsobj(js);
- jsobj.AddProperty("type", "Error");
- jsobj.AddProperty("id", "");
- jsobj.AddProperty("kind", kind);
- jsobj.AddProperty("message", buffer);
- PrintRequest(jsobj, js);
+ Dart_ServiceRequestCallback callback() const { return callback_; }
+ void set_callback(Dart_ServiceRequestCallback callback) {
+ callback_ = callback;
+ }
+
+ void* user_data() const { return user_data_; }
+ void set_user_data(void* user_data) {
+ user_data_ = user_data;
+ }
+
+ EmbedderServiceHandler* next() const { return next_; }
+ void set_next(EmbedderServiceHandler* next) {
+ next_ = next;
+ }
+
+ private:
+ char* name_;
+ Dart_ServiceRequestCallback callback_;
+ void* user_data_;
+ EmbedderServiceHandler* next_;
+};
+
+
+void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler,
+ JSONStream* js) {
+ ASSERT(handler != NULL);
+ Dart_ServiceRequestCallback callback = handler->callback();
+ ASSERT(callback != NULL);
+ const char* r = NULL;
+ const char* name = js->method();
+ const char** keys = js->param_keys();
+ const char** values = js->param_values();
+ r = callback(name, keys, values, js->num_params(), handler->user_data());
+ ASSERT(r != NULL);
+ // TODO(johnmccutchan): Allow for NULL returns?
+ TextBuffer* buffer = js->buffer();
+ buffer->AddString(r);
+ free(const_cast<char*>(r));
}
-void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) {
- ASSERT(isolate != NULL);
- ASSERT(!msg.IsNull());
- ASSERT(msg.Length() == 5);
+void Service::RegisterIsolateEmbedderCallback(
+ const char* name,
+ Dart_ServiceRequestCallback callback,
+ void* user_data) {
+ if (name == NULL) {
+ return;
+ }
+ EmbedderServiceHandler* handler = FindIsolateEmbedderHandler(name);
+ if (handler != NULL) {
+ // Update existing handler entry.
+ handler->set_callback(callback);
+ handler->set_user_data(user_data);
+ return;
+ }
+ // Create a new handler.
+ handler = new EmbedderServiceHandler(name);
+ handler->set_callback(callback);
+ handler->set_user_data(user_data);
- {
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ // Insert into isolate_service_handler_head_ list.
+ handler->set_next(isolate_service_handler_head_);
+ isolate_service_handler_head_ = handler;
+}
- Instance& reply_port = Instance::Handle(isolate);
- String& method = String::Handle(isolate);
- Array& param_keys = Array::Handle(isolate);
- Array& param_values = Array::Handle(isolate);
- reply_port ^= msg.At(1);
- method ^= msg.At(2);
- param_keys ^= msg.At(3);
- param_values ^= msg.At(4);
- ASSERT(!method.IsNull());
- ASSERT(!param_keys.IsNull());
- ASSERT(!param_values.IsNull());
- ASSERT(param_keys.Length() == param_values.Length());
+EmbedderServiceHandler* Service::FindIsolateEmbedderHandler(
+ const char* name) {
+ EmbedderServiceHandler* current = isolate_service_handler_head_;
+ while (current != NULL) {
+ if (strcmp(name, current->name()) == 0) {
+ return current;
+ }
+ current = current->next();
+ }
+ return NULL;
+}
+
+
+void Service::RegisterRootEmbedderCallback(
+ const char* name,
+ Dart_ServiceRequestCallback callback,
+ void* user_data) {
+ if (name == NULL) {
+ return;
+ }
+ EmbedderServiceHandler* handler = FindRootEmbedderHandler(name);
+ if (handler != NULL) {
+ // Update existing handler entry.
+ handler->set_callback(callback);
+ handler->set_user_data(user_data);
+ return;
+ }
+ // Create a new handler.
+ handler = new EmbedderServiceHandler(name);
+ handler->set_callback(callback);
+ handler->set_user_data(user_data);
+
+ // Insert into root_service_handler_head_ list.
+ handler->set_next(root_service_handler_head_);
+ root_service_handler_head_ = handler;
+}
- if (!reply_port.IsSendPort()) {
- FATAL("SendPort expected.");
- }
- IsolateMessageHandler handler =
- FindIsolateMessageHandler(method.ToCString());
- {
- JSONStream js;
- js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
- method, param_keys, param_values);
- if (handler == NULL) {
- // Check for an embedder handler.
- EmbedderServiceHandler* e_handler =
- FindIsolateEmbedderHandler(method.ToCString());
- if (e_handler != NULL) {
- EmbedderHandleMessage(e_handler, &js);
- } else {
- if (FindRootMessageHandler(method.ToCString()) != NULL) {
- PrintError(&js, "%s does not expect the 'isolateId' parameter",
- method.ToCString());
- } else {
- PrintError(&js, "Unrecognized method: %s", method.ToCString());
- }
- }
- js.PostReply();
- } else {
- if (handler(isolate, &js)) {
- // Handler returns true if the reply is ready to be posted.
- // TODO(johnmccutchan): Support asynchronous replies.
- js.PostReply();
- }
- }
+EmbedderServiceHandler* Service::FindRootEmbedderHandler(
+ const char* name) {
+ EmbedderServiceHandler* current = root_service_handler_head_;
+ while (current != NULL) {
+ if (strcmp(name, current->name()) == 0) {
+ return current;
}
+ current = current->next();
}
+ return NULL;
}
+static const MethodParameter* get_isolate_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolate(Isolate* isolate, JSONStream* js) {
isolate->PrintJSON(js, false);
return true;
}
+static const MethodParameter* get_stack_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetStack(Isolate* isolate, JSONStream* js) {
DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
JSONObject jsobj(js);
@@ -1048,112 +773,6 @@ static bool HandleIsolateEcho(Isolate* isolate, JSONStream* js) {
}
-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 bool GetInteger64Id(const char* s, int64_t* id, int base = 10) {
- if ((s == NULL) || (*s == '\0')) {
- // Empty string.
- return false;
- }
- if (id == NULL) {
- // No id pointer.
- return false;
- }
- int64_t r = 0;
- char* end_ptr = NULL;
- r = strtoll(s, &end_ptr, base);
- if (end_ptr == s) {
- // String was not advanced at all, cannot be valid.
- return false;
- }
- *id = r;
- return true;
-}
-
-// Scans the string until the '-' character. Returns pointer to string
-// at '-' character. Returns NULL if not found.
-static const char* ScanUntilDash(const char* s) {
- if ((s == NULL) || (*s == '\0')) {
- // Empty string.
- return NULL;
- }
- while (*s != '\0') {
- if (*s == '-') {
- return s;
- }
- s++;
- }
- return NULL;
-}
-
-
-static bool GetCodeId(const char* s, int64_t* timestamp, uword* address) {
- if ((s == NULL) || (*s == '\0')) {
- // Empty string.
- return false;
- }
- if ((timestamp == NULL) || (address == NULL)) {
- // Bad arguments.
- return false;
- }
- // Extract the timestamp.
- if (!GetInteger64Id(s, timestamp, 16) || (*timestamp < 0)) {
- return false;
- }
- s = ScanUntilDash(s);
- if (s == NULL) {
- return false;
- }
- // Skip the dash.
- s++;
- // Extract the PC.
- if (!GetUnsignedIntegerId(s, address, 16)) {
- return false;
- }
- return true;
-}
-
-
static bool ContainsNonInstance(const Object& obj) {
if (obj.IsArray()) {
const Array& array = Array::Cast(obj);
@@ -1596,6 +1215,12 @@ static bool PrintInboundReferences(Isolate* isolate,
}
+static const MethodParameter* get_inbound_references_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetInboundReferences(Isolate* isolate,
JSONStream* js) {
const char* target_id = js->LookupParam("targetId");
@@ -1694,6 +1319,13 @@ static bool PrintRetainingPath(Isolate* isolate,
return true;
}
+
+static const MethodParameter* get_retaining_path_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetRetainingPath(Isolate* isolate,
JSONStream* js) {
const char* target_id = js->LookupParam("targetId");
@@ -1737,6 +1369,12 @@ static bool HandleIsolateGetRetainingPath(Isolate* isolate,
}
+static const MethodParameter* get_retained_size_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) {
const char* target_id = js->LookupParam("targetId");
if (target_id == NULL) {
@@ -1784,6 +1422,12 @@ static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) {
}
+static const MethodParameter* eval_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) {
const char* target_id = js->LookupParam("targetId");
if (target_id == NULL) {
@@ -1876,6 +1520,12 @@ class GetInstancesVisitor : public ObjectGraph::Visitor {
};
+static const MethodParameter* get_instances_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) {
const char* target_id = js->LookupParam("classId");
if (target_id == NULL) {
@@ -1922,6 +1572,69 @@ static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) {
}
+class LibraryCoverageFilter : public CoverageFilter {
+ public:
+ explicit LibraryCoverageFilter(const Library& lib) : lib_(lib) {}
+ bool ShouldOutputCoverageFor(const Library& lib,
+ const Script& script,
+ const Class& cls,
+ const Function& func) const {
+ return lib.raw() == lib_.raw();
+ }
+ private:
+ const Library& lib_;
+};
+
+
+class ScriptCoverageFilter : public CoverageFilter {
+ public:
+ explicit ScriptCoverageFilter(const Script& script)
+ : script_(script) {}
+ bool ShouldOutputCoverageFor(const Library& lib,
+ const Script& script,
+ const Class& cls,
+ const Function& func) const {
+ return script.raw() == script_.raw();
+ }
+ private:
+ const Script& script_;
+};
+
+
+class ClassCoverageFilter : public CoverageFilter {
+ public:
+ explicit ClassCoverageFilter(const Class& cls) : cls_(cls) {}
+ bool ShouldOutputCoverageFor(const Library& lib,
+ const Script& script,
+ const Class& cls,
+ const Function& func) const {
+ return cls.raw() == cls_.raw();
+ }
+ private:
+ const Class& cls_;
+};
+
+
+class FunctionCoverageFilter : public CoverageFilter {
+ public:
+ explicit FunctionCoverageFilter(const Function& func) : func_(func) {}
+ bool ShouldOutputCoverageFor(const Library& lib,
+ const Script& script,
+ const Class& cls,
+ const Function& func) const {
+ return func.raw() == func_.raw();
+ }
+ private:
+ const Function& func_;
+};
+
+
+static const MethodParameter* get_coverage_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetCoverage(Isolate* isolate, JSONStream* js) {
if (!js->HasParam("targetId")) {
CodeCoverage::PrintJSON(isolate, js, NULL);
@@ -1960,6 +1673,12 @@ static bool HandleIsolateGetCoverage(Isolate* isolate, JSONStream* js) {
}
+static const MethodParameter* add_breakpoint_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) {
if (!js->HasParam("line")) {
PrintMissingParamError(js, "line");
@@ -1990,6 +1709,12 @@ static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) {
}
+static const MethodParameter* remove_breakpoint_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateRemoveBreakpoint(Isolate* isolate, JSONStream* js) {
if (!js->HasParam("breakpointId")) {
PrintMissingParamError(js, "breakpointId");
@@ -2026,6 +1751,7 @@ static RawClass* GetMetricsClass(Isolate* isolate) {
}
+
static bool HandleNativeMetricsList(Isolate* isolate, JSONStream* js) {
JSONObject obj(js);
obj.AddProperty("type", "MetricList");
@@ -2106,6 +1832,12 @@ static bool HandleDartMetric(Isolate* isolate, JSONStream* js, const char* id) {
}
+static const MethodParameter* get_metric_list_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetMetricList(Isolate* isolate, JSONStream* js) {
bool native_metrics = false;
if (js->HasParam("type")) {
@@ -2128,6 +1860,12 @@ static bool HandleIsolateGetMetricList(Isolate* isolate, JSONStream* js) {
}
+static const MethodParameter* get_metric_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetMetric(Isolate* isolate, JSONStream* js) {
const char* metric_id = js->LookupParam("metricId");
if (metric_id == NULL) {
@@ -2154,12 +1892,24 @@ static bool HandleIsolateGetMetric(Isolate* isolate, JSONStream* js) {
}
-static bool HandleVMGetMetricList(JSONStream* js) {
+static const MethodParameter* get_vm_metric_list_params[] = {
+ NO_ISOLATE_PARAMETER,
+ NULL,
+};
+
+
+static bool HandleVMGetMetricList(Isolate* isolate, JSONStream* js) {
return false;
}
-static bool HandleVMGetMetric(JSONStream* js) {
+static const MethodParameter* get_vm_metric_params[] = {
+ NO_ISOLATE_PARAMETER,
+ NULL,
+};
+
+
+static bool HandleVMGetMetric(Isolate* isolate, JSONStream* js) {
const char* metric_id = js->LookupParam("metricId");
if (metric_id == NULL) {
PrintMissingParamError(js, "metricId");
@@ -2168,6 +1918,12 @@ static bool HandleVMGetMetric(JSONStream* js) {
}
+static const MethodParameter* resume_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateResume(Isolate* isolate, JSONStream* js) {
const char* step_param = js->LookupParam("step");
if (isolate->message_handler()->paused_on_start()) {
@@ -2214,6 +1970,12 @@ static bool HandleIsolateResume(Isolate* isolate, JSONStream* js) {
}
+static const MethodParameter* get_breakpoints_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetBreakpoints(Isolate* isolate, JSONStream* js) {
JSONObject jsobj(js);
jsobj.AddProperty("type", "BreakpointList");
@@ -2223,6 +1985,12 @@ static bool HandleIsolateGetBreakpoints(Isolate* isolate, JSONStream* js) {
}
+static const MethodParameter* pause_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolatePause(Isolate* isolate, JSONStream* js) {
// TODO(turnidge): Don't double-interrupt the isolate here.
isolate->ScheduleInterrupts(Isolate::kApiInterrupt);
@@ -2233,6 +2001,12 @@ static bool HandleIsolatePause(Isolate* isolate, JSONStream* js) {
}
+static const MethodParameter* get_tag_profile_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetTagProfile(Isolate* isolate, JSONStream* js) {
JSONObject miniProfile(js);
miniProfile.AddProperty("type", "TagProfile");
@@ -2241,29 +2015,48 @@ static bool HandleIsolateGetTagProfile(Isolate* isolate, JSONStream* js) {
return true;
}
+
+static const char* tags_enum_names[] = {
+ "None",
+ "UserVM",
+ "UserOnly",
+ "VMUser",
+ "VMOnly",
+ NULL,
+};
+
+
+static ProfilerService::TagOrder tags_enum_values[] = {
+ ProfilerService::kNoTags,
+ ProfilerService::kUserVM,
+ ProfilerService::kUser,
+ ProfilerService::kVMUser,
+ ProfilerService::kVM,
+ ProfilerService::kNoTags, // Default value.
+};
+
+
+static const MethodParameter* get_cpu_profile_params[] = {
+ ISOLATE_PARAMETER,
+ new EnumParameter("tags", true, tags_enum_names),
+ NULL,
+};
+
+
static bool HandleIsolateGetCpuProfile(Isolate* isolate, JSONStream* js) {
- ProfilerService::TagOrder tag_order = ProfilerService::kUserVM;
- if (js->HasParam("tags")) {
- if (js->ParamIs("tags", "None")) {
- tag_order = ProfilerService::kNoTags;
- } else if (js->ParamIs("tags", "UserVM")) {
- tag_order = ProfilerService::kUserVM;
- } else if (js->ParamIs("tags", "UserOnly")) {
- tag_order = ProfilerService::kUser;
- } else if (js->ParamIs("tags", "VMUser")) {
- tag_order = ProfilerService::kVMUser;
- } else if (js->ParamIs("tags", "VMOnly")) {
- tag_order = ProfilerService::kVM;
- } else {
- PrintInvalidParamError(js, "tags");
- return true;
- }
- }
+ ProfilerService::TagOrder tag_order =
+ EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
ProfilerService::PrintJSON(js, tag_order);
return true;
}
+static const MethodParameter* get_allocation_profile_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetAllocationProfile(Isolate* isolate,
JSONStream* js) {
bool should_reset_accumulator = false;
@@ -2297,12 +2090,24 @@ static bool HandleIsolateGetAllocationProfile(Isolate* isolate,
}
+static const MethodParameter* get_heap_map_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetHeapMap(Isolate* isolate, JSONStream* js) {
isolate->heap()->PrintHeapMapToJSONStream(isolate, js);
return true;
}
+static const MethodParameter* request_heap_snapshot_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateRequestHeapSnapshot(Isolate* isolate, JSONStream* js) {
Service::SendGraphEvent(isolate);
// TODO(koda): Provide some id that ties this request to async response(s).
@@ -2353,6 +2158,12 @@ class ContainsAddressVisitor : public FindObjectVisitor {
};
+static const MethodParameter* get_object_by_address_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetObjectByAddress(Isolate* isolate, JSONStream* js) {
const char* addr_str = js->LookupParam("address");
if (addr_str == NULL) {
@@ -2400,6 +2211,12 @@ static bool HandleIsolateRespondWithMalformedObject(Isolate* isolate,
}
+static const MethodParameter* get_object_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) {
const char* id = js->LookupParam("objectId");
if (id == NULL) {
@@ -2435,6 +2252,12 @@ static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) {
}
+static const MethodParameter* get_class_list_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) {
ClassTable* table = isolate->class_table();
JSONObject jsobj(js);
@@ -2443,6 +2266,12 @@ static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) {
}
+static const MethodParameter* get_type_arguments_list_params[] = {
+ ISOLATE_PARAMETER,
+ NULL,
+};
+
+
static bool HandleIsolateGetTypeArgumentsList(Isolate* isolate,
JSONStream* js) {
bool only_with_instantiations = false;
@@ -2472,122 +2301,6 @@ static bool HandleIsolateGetTypeArgumentsList(Isolate* isolate,
}
-static IsolateMessageHandlerEntry isolate_handlers_new[] = {
- { "getIsolate", HandleIsolate },
- { "getObject", HandleIsolateGetObject },
- { "getObjectByAddress", HandleIsolateGetObjectByAddress },
- { "getBreakpoints", HandleIsolateGetBreakpoints },
- { "pause", HandleIsolatePause },
- { "resume", HandleIsolateResume },
- { "getStack", HandleIsolateGetStack },
- { "getCpuProfile", HandleIsolateGetCpuProfile },
- { "getTagProfile", HandleIsolateGetTagProfile },
- { "getAllocationProfile", HandleIsolateGetAllocationProfile },
- { "getHeapMap", HandleIsolateGetHeapMap },
- { "addBreakpoint", HandleIsolateAddBreakpoint },
- { "removeBreakpoint", HandleIsolateRemoveBreakpoint },
- { "getCoverage", HandleIsolateGetCoverage },
- { "eval", HandleIsolateEval },
- { "getRetainedSize", HandleIsolateGetRetainedSize },
- { "getRetainingPath", HandleIsolateGetRetainingPath },
- { "getInboundReferences", HandleIsolateGetInboundReferences },
- { "getInstances", HandleIsolateGetInstances },
- { "requestHeapSnapshot", HandleIsolateRequestHeapSnapshot },
- { "getClassList", HandleIsolateGetClassList },
- { "getTypeArgumentsList", HandleIsolateGetTypeArgumentsList },
- { "getIsolateMetricList", HandleIsolateGetMetricList },
- { "getIsolateMetric", HandleIsolateGetMetric },
- { "_echo", HandleIsolateEcho },
- { "_triggerEchoEvent", HandleIsolateTriggerEchoEvent },
- { "_respondWithMalformedJson", HandleIsolateRespondWithMalformedJson },
- { "_respondWithMalformedObject", HandleIsolateRespondWithMalformedObject },
-};
-
-
-static IsolateMessageHandler FindIsolateMessageHandler(const char* method) {
- intptr_t num_message_handlers = sizeof(isolate_handlers_new) /
- sizeof(isolate_handlers_new[0]);
- for (intptr_t i = 0; i < num_message_handlers; i++) {
- const IsolateMessageHandlerEntry& entry = isolate_handlers_new[i];
- if (strcmp(method, entry.method) == 0) {
- return entry.handler;
- }
- }
- if (FLAG_trace_service) {
- OS::Print("Service has no isolate message handler for <%s>\n", method);
- }
- return NULL;
-}
-
-
-void Service::HandleRootMessage(const Instance& msg_instance) {
- Isolate* isolate = Isolate::Current();
- ASSERT(!msg_instance.IsNull());
- ASSERT(msg_instance.IsArray());
-
- {
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
-
- const Array& msg = Array::Cast(msg_instance);
- ASSERT(msg.Length() == 5);
-
- Instance& reply_port = Instance::Handle(isolate);
- String& method = String::Handle(isolate);
- Array& param_keys = Array::Handle(isolate);
- Array& param_values = Array::Handle(isolate);
- reply_port ^= msg.At(1);
- method ^= msg.At(2);
- param_keys ^= msg.At(3);
- param_values ^= msg.At(4);
-
- ASSERT(!method.IsNull());
- ASSERT(!param_keys.IsNull());
- ASSERT(!param_values.IsNull());
- ASSERT(param_keys.Length() == param_values.Length());
-
- if (!reply_port.IsSendPort()) {
- FATAL("SendPort expected.");
- }
-
- RootMessageHandler handler =
- FindRootMessageHandler(method.ToCString());
- {
- JSONStream js;
- js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
- method, param_keys, param_values);
- if (handler == NULL) {
- // Check for an embedder handler.
- EmbedderServiceHandler* e_handler =
- FindRootEmbedderHandler(method.ToCString());
- if (e_handler != NULL) {
- EmbedderHandleMessage(e_handler, &js);
- } else {
- if (FindIsolateMessageHandler(method.ToCString()) != NULL) {
- PrintMissingParamError(&js, "isolateId");
- } else {
- PrintError(&js, "Unrecognized method: %s", method.ToCString());
- }
- }
- js.PostReply();
- } else {
- if (handler(&js)) {
- // Handler returns true if the reply is ready to be posted.
- // TODO(johnmccutchan): Support asynchronous replies.
- js.PostReply();
- }
- }
- }
- }
-}
-
-
-static bool HandleRootEcho(JSONStream* js) {
- JSONObject jsobj(js);
- return HandleCommonEcho(&jsobj, js);
-}
-
-
class ServiceIsolateVisitor : public IsolateVisitor {
public:
explicit ServiceIsolateVisitor(JSONArray* jsarr)
@@ -2597,7 +2310,8 @@ class ServiceIsolateVisitor : public IsolateVisitor {
virtual ~ServiceIsolateVisitor() {}
void VisitIsolate(Isolate* isolate) {
- if (isolate != Dart::vm_isolate() && !Service::IsServiceIsolate(isolate)) {
+ if ((isolate != Dart::vm_isolate()) &&
+ !ServiceIsolate::IsServiceIsolate(isolate)) {
jsarr_->AddValue(isolate);
}
}
@@ -2607,8 +2321,13 @@ class ServiceIsolateVisitor : public IsolateVisitor {
};
-static bool HandleVM(JSONStream* js) {
- Isolate* isolate = Isolate::Current();
+static const MethodParameter* get_vm_params[] = {
+ NO_ISOLATE_PARAMETER,
+ NULL,
+};
+
+
+static bool HandleVM(Isolate* isolate, JSONStream* js) {
JSONObject jsobj(js);
jsobj.AddProperty("type", "VM");
jsobj.AddProperty("id", "vm");
@@ -2639,13 +2358,25 @@ static bool HandleVM(JSONStream* js) {
}
-static bool HandleVMFlagList(JSONStream* js) {
+static const MethodParameter* get_flag_list_params[] = {
+ NO_ISOLATE_PARAMETER,
+ NULL,
+};
+
+
+static bool HandleVMFlagList(Isolate* isolate, JSONStream* js) {
Flags::PrintJSON(js);
return true;
}
-static bool HandleVMSetFlag(JSONStream* js) {
+static const MethodParameter* set_flags_params[] = {
+ NO_ISOLATE_PARAMETER,
+ NULL,
+};
+
+
+static bool HandleVMSetFlag(Isolate* isolate, JSONStream* js) {
const char* flag_name = js->LookupParam("name");
if (flag_name == NULL) {
PrintMissingParamError(js, "name");
@@ -2671,198 +2402,87 @@ static bool HandleVMSetFlag(JSONStream* js) {
}
-static RootMessageHandlerEntry root_handlers_new[] = {
- { "getVM", HandleVM },
- { "getFlagList", HandleVMFlagList },
- { "setFlag", HandleVMSetFlag },
- { "getVMMetricList", HandleVMGetMetricList },
- { "getVMMetric", HandleVMGetMetric },
- { "_echo", HandleRootEcho },
+static ServiceMethodDescriptor service_methods_[] = {
+ { "_echo", HandleIsolateEcho,
+ NULL },
+ { "_respondWithMalformedJson", HandleIsolateRespondWithMalformedJson,
+ NULL },
+ { "_respondWithMalformedObject", HandleIsolateRespondWithMalformedObject,
+ NULL },
+ { "_triggerEchoEvent", HandleIsolateTriggerEchoEvent,
+ NULL },
+ { "addBreakpoint", HandleIsolateAddBreakpoint,
+ add_breakpoint_params },
+ { "eval", HandleIsolateEval,
+ eval_params },
+ { "getAllocationProfile", HandleIsolateGetAllocationProfile,
+ get_allocation_profile_params },
+ { "getBreakpoints", HandleIsolateGetBreakpoints,
+ get_breakpoints_params },
+ { "getClassList", HandleIsolateGetClassList,
+ get_class_list_params },
+ { "getCoverage", HandleIsolateGetCoverage,
+ get_coverage_params },
+ { "getCpuProfile", HandleIsolateGetCpuProfile,
+ get_cpu_profile_params },
+ { "getFlagList", HandleVMFlagList ,
+ get_flag_list_params },
+ { "getHeapMap", HandleIsolateGetHeapMap,
+ get_heap_map_params },
+ { "getInboundReferences", HandleIsolateGetInboundReferences,
+ get_inbound_references_params },
+ { "getInstances", HandleIsolateGetInstances,
+ get_instances_params },
+ { "getIsolate", HandleIsolate,
+ get_isolate_params },
+ { "getIsolateMetric", HandleIsolateGetMetric,
+ get_metric_params },
+ { "getIsolateMetricList", HandleIsolateGetMetricList,
+ get_metric_list_params },
+ { "getObject", HandleIsolateGetObject,
+ get_object_params },
+ { "getObjectByAddress", HandleIsolateGetObjectByAddress,
+ get_object_by_address_params },
+ { "getRetainedSize", HandleIsolateGetRetainedSize,
+ get_retained_size_params },
+ { "getRetainingPath", HandleIsolateGetRetainingPath,
+ get_retaining_path_params },
+ { "getStack", HandleIsolateGetStack,
+ get_stack_params },
+ { "getTagProfile", HandleIsolateGetTagProfile,
+ get_tag_profile_params },
+ { "getTypeArgumentsList", HandleIsolateGetTypeArgumentsList,
+ get_type_arguments_list_params },
+ { "getVM", HandleVM ,
+ get_vm_params },
+ { "getVMMetric", HandleVMGetMetric,
+ get_vm_metric_params },
+ { "getVMMetricList", HandleVMGetMetricList,
+ get_vm_metric_list_params },
+ { "pause", HandleIsolatePause,
+ pause_params },
+ { "removeBreakpoint", HandleIsolateRemoveBreakpoint,
+ remove_breakpoint_params },
+ { "resume", HandleIsolateResume,
+ resume_params },
+ { "requestHeapSnapshot", HandleIsolateRequestHeapSnapshot,
+ request_heap_snapshot_params },
+ { "setFlag", HandleVMSetFlag ,
+ set_flags_params },
};
-static RootMessageHandler FindRootMessageHandler(const char* method) {
- intptr_t num_message_handlers = sizeof(root_handlers_new) /
- sizeof(root_handlers_new[0]);
- for (intptr_t i = 0; i < num_message_handlers; i++) {
- const RootMessageHandlerEntry& entry = root_handlers_new[i];
- if (strcmp(method, entry.method) == 0) {
- return entry.handler;
- }
- }
- if (FLAG_trace_service) {
- OS::Print("vm-service: No root message handler for <%s>.\n", method);
- }
- return NULL;
-}
-
-
-void Service::SendEvent(intptr_t eventId, const Object& eventMessage) {
- if (!IsRunning()) {
- return;
- }
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
- HANDLESCOPE(isolate);
-
- // Construct a list of the form [eventId, eventMessage].
- const Array& list = Array::Handle(Array::New(2));
- ASSERT(!list.IsNull());
- list.SetAt(0, Integer::Handle(Integer::New(eventId)));
- list.SetAt(1, eventMessage);
-
- // Push the event to port_.
- uint8_t* data = NULL;
- MessageWriter writer(&data, &allocator, false);
- writer.WriteMessage(list);
- intptr_t len = writer.BytesWritten();
- if (FLAG_trace_service) {
- OS::Print("vm-service: Pushing event of type %" Pd ", len %" Pd "\n",
- eventId, len);
- }
- // TODO(turnidge): For now we ignore failure to send an event. Revisit?
- PortMap::PostMessage(
- new Message(service_port_, data, len, Message::kNormalPriority));
-}
-
-
-void Service::SendEvent(intptr_t eventId,
- const String& meta,
- const uint8_t* data,
- intptr_t size) {
- // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data]
- const intptr_t meta_bytes = Utf8::Length(meta);
- const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size;
- const TypedData& message = TypedData::Handle(
- TypedData::New(kTypedDataUint8ArrayCid, total_bytes));
- intptr_t offset = 0;
- // TODO(koda): Rename these methods SetHostUint64, etc.
- message.SetUint64(0, Utils::HostToBigEndian64(meta_bytes));
- offset += sizeof(uint64_t);
- {
- NoGCScope no_gc;
- meta.ToUTF8(static_cast<uint8_t*>(message.DataAddr(offset)), meta_bytes);
- offset += meta_bytes;
- }
- // TODO(koda): It would be nice to avoid this copy (requires changes to
- // MessageWriter code).
- {
- NoGCScope no_gc;
- memmove(message.DataAddr(offset), data, size);
- offset += size;
- }
- ASSERT(offset == total_bytes);
- SendEvent(eventId, message);
-}
-
-
-void Service::HandleGCEvent(GCEvent* event) {
- JSONStream js;
- event->PrintJSON(&js);
- const String& message = String::Handle(String::New(js.ToCString()));
- SendEvent(kEventFamilyGC, message);
-}
-
-
-void Service::HandleDebuggerEvent(DebuggerEvent* event) {
- JSONStream js;
- event->PrintJSON(&js);
- const String& message = String::Handle(String::New(js.ToCString()));
- SendEvent(kEventFamilyDebug, message);
-}
-
-
-void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler,
- JSONStream* js) {
- ASSERT(handler != NULL);
- Dart_ServiceRequestCallback callback = handler->callback();
- ASSERT(callback != NULL);
- const char* r = NULL;
- const char* name = js->method();
- const char** keys = js->param_keys();
- const char** values = js->param_values();
- r = callback(name, keys, values, js->num_params(), handler->user_data());
- ASSERT(r != NULL);
- // TODO(johnmccutchan): Allow for NULL returns?
- TextBuffer* buffer = js->buffer();
- buffer->AddString(r);
- free(const_cast<char*>(r));
-}
-
-
-void Service::RegisterIsolateEmbedderCallback(
- const char* name,
- Dart_ServiceRequestCallback callback,
- void* user_data) {
- if (name == NULL) {
- return;
- }
- EmbedderServiceHandler* handler = FindIsolateEmbedderHandler(name);
- if (handler != NULL) {
- // Update existing handler entry.
- handler->set_callback(callback);
- handler->set_user_data(user_data);
- return;
- }
- // Create a new handler.
- handler = new EmbedderServiceHandler(name);
- handler->set_callback(callback);
- handler->set_user_data(user_data);
-
- // Insert into isolate_service_handler_head_ list.
- handler->set_next(isolate_service_handler_head_);
- isolate_service_handler_head_ = handler;
-}
-
-
-EmbedderServiceHandler* Service::FindIsolateEmbedderHandler(
- const char* name) {
- EmbedderServiceHandler* current = isolate_service_handler_head_;
- while (current != NULL) {
- if (strcmp(name, current->name()) == 0) {
- return current;
+ServiceMethodDescriptor* FindMethod(const char* method_name) {
+ intptr_t num_methods = sizeof(service_methods_) /
+ sizeof(service_methods_[0]);
+ for (intptr_t i = 0; i < num_methods; i++) {
+ ServiceMethodDescriptor& method = service_methods_[i];
+ if (strcmp(method_name, method.name) == 0) {
+ return &method;
}
- current = current->next();
}
return NULL;
}
-void Service::RegisterRootEmbedderCallback(
- const char* name,
- Dart_ServiceRequestCallback callback,
- void* user_data) {
- if (name == NULL) {
- return;
- }
- EmbedderServiceHandler* handler = FindRootEmbedderHandler(name);
- if (handler != NULL) {
- // Update existing handler entry.
- handler->set_callback(callback);
- handler->set_user_data(user_data);
- return;
- }
- // Create a new handler.
- handler = new EmbedderServiceHandler(name);
- handler->set_callback(callback);
- handler->set_user_data(user_data);
-
- // Insert into root_service_handler_head_ list.
- handler->set_next(root_service_handler_head_);
- root_service_handler_head_ = handler;
-}
-
-
-EmbedderServiceHandler* Service::FindRootEmbedderHandler(
- const char* name) {
- EmbedderServiceHandler* current = root_service_handler_head_;
- while (current != NULL) {
- if (strcmp(name, current->name()) == 0) {
- return current;
- }
- current = current->next();
- }
- return NULL;
-}
-
} // namespace dart
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service_isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698