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

Unified Diff: runtime/vm/service.cc

Issue 889443002: Service isolate rework take 2 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 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 | « runtime/vm/service.h ('k') | runtime/vm/service/vmservice.dart » ('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 1aae8ae64c4d35c927ca989d2e35f6cd5c974a73..0d0502b1d284b18f451c29a68a3b9a08d4b02965 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -14,6 +14,7 @@
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/isolate.h"
+#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/native_entry.h"
@@ -247,6 +248,53 @@ static void SendRootServiceMessage(Dart_NativeArguments args) {
}
+class ScopeStopwatch : public ValueObject {
+ public:
+ explicit ScopeStopwatch(const char* name) : name_(name) {
+ start_ = OS::GetCurrentTimeMicros();
+ }
+
+ int64_t GetElapsed() const {
+ int64_t end = OS::GetCurrentTimeMicros();
+ ASSERT(end >= start_);
+ return end - start_;
+ }
+
+ ~ScopeStopwatch() {
+ int64_t elapsed = GetElapsed();
+ OS::Print("[%" Pd "] %s took %" Pd64 " micros.\n",
+ OS::ProcessId(), name_, elapsed);
+ }
+
+ private:
+ const char* name_;
+ int64_t start_;
+};
+
+
+Dart_Port Service::WaitForLoadPort() {
+ MonitorLocker ml(monitor_);
+
+ while (initializing_ && (load_port_ == ILLEGAL_PORT)) {
+ ml.Wait();
+ }
+
+ return load_port_;
+}
+
+
+Dart_Port Service::LoadPort() {
+ MonitorLocker ml(monitor_);
+ return load_port_;
+}
+
+
+void Service::SetLoadPort(Dart_Port port) {
+ MonitorLocker ml(monitor_);
+ load_port_ = port;
+}
+
+
void Service::SetEventMask(uint32_t mask) {
event_mask_ = mask;
}
@@ -324,6 +372,11 @@ class RegisterRunningIsolatesVisitor : public IsolateVisitor {
args.SetAt(2, name);
Object& r = Object::Handle(service_isolate_);
r = DartEntry::InvokeFunction(register_function_, args);
+ if (FLAG_trace_service) {
+ OS::Print("Isolate %s %" Pd64 " registered with service \n",
+ name.ToCString(),
+ port_id);
+ }
ASSERT(!r.IsError());
}
@@ -348,6 +401,9 @@ static void OnStart(Dart_NativeArguments args) {
StackZone zone(isolate);
HANDLESCOPE(isolate);
{
+ if (FLAG_trace_service) {
+ OS::Print("Booting dart:vmservice library\n");
+ }
// Boot the dart:vmservice library.
Dart_EnterScope();
Dart_Handle url_str =
@@ -362,7 +418,11 @@ static void OnStart(Dart_NativeArguments args) {
Service::set_port(port);
Dart_ExitScope();
}
+
{
+ if (FLAG_trace_service) {
+ OS::Print("Registering running isolates\n");
+ }
// Register running isolates with service.
RegisterRunningIsolatesVisitor register_isolates(isolate);
Isolate::VisitIsolates(&register_isolates);
@@ -408,77 +468,20 @@ static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
return NULL;
}
-
+const char* Service::kServiceIsolateName = "vm-service";
EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
EmbedderServiceHandler* Service::root_service_handler_head_ = NULL;
Isolate* Service::service_isolate_ = NULL;
-Dart_LibraryTagHandler Service::embedder_provided_handler_ = NULL;
Dart_Port Service::port_ = ILLEGAL_PORT;
+Dart_Port Service::load_port_ = ILLEGAL_PORT;
+Monitor* Service::monitor_ = NULL;
+bool Service::initializing_ = true;
uint32_t Service::event_mask_ = 0;
-Isolate* Service::GetServiceIsolate(void* callback_data) {
- if (service_isolate_ != NULL) {
- // Already initialized, return service isolate.
- return service_isolate_;
- }
- Dart_ServiceIsolateCreateCalback create_callback =
- Isolate::ServiceCreateCallback();
- if (create_callback == NULL) {
- return NULL;
- }
- Isolate::SetCurrent(NULL);
- char* error = NULL;
- Isolate* isolate =
- reinterpret_cast<Isolate*>(create_callback(callback_data, &error));
- if (isolate == NULL) {
- return NULL;
- }
- StartIsolateScope isolate_scope(isolate);
- {
- // Install the dart:vmservice library.
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
- Library& library =
- Library::Handle(isolate, isolate->object_store()->root_library());
- // Isolate is empty.
- ASSERT(library.IsNull());
- // Grab embedder tag handler.
- embedder_provided_handler_ = isolate->library_tag_handler();
- // Temporarily install our own.
- isolate->set_library_tag_handler(LibraryTagHandler);
- // Get script resource.
- 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 String& url_str = String::Handle(Symbols::DartVMService().raw());
- library ^= Library::LookupLibrary(url_str);
- ASSERT(library.IsNull());
- // Setup library.
- library = Library::New(url_str);
- library.Register();
- const Script& script = Script::Handle(
- isolate, Script::New(url_str, source_str, RawScript::kLibraryTag));
- library.SetLoadInProgress();
- Dart_EnterScope(); // Need to enter scope for tag handler.
- 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();
- // Install embedder default library tag handler again.
- isolate->set_library_tag_handler(embedder_provided_handler_);
- embedder_provided_handler_ = NULL;
- library.set_native_entry_resolver(VmServiceNativeResolver);
- }
- service_isolate_ = reinterpret_cast<Isolate*>(isolate);
- return service_isolate_;
+bool Service::IsServiceIsolateName(const char* name) {
+ ASSERT(name != NULL);
+ return strcmp(name, kServiceIsolateName) == 0;
}
@@ -487,6 +490,9 @@ bool Service::SendIsolateStartupMessage() {
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()));
@@ -515,6 +521,9 @@ bool Service::SendIsolateShutdownMessage() {
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()));
@@ -560,32 +569,22 @@ Dart_Handle Service::GetSource(const char* name) {
}
-Dart_Handle Service::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle library,
+Dart_Handle Service::LibraryTagHandler(Dart_LibraryTag tag,
+ Dart_Handle library,
Dart_Handle url) {
- if (!Dart_IsLibrary(library)) {
- return Dart_NewApiError("not a library");
+ if (tag == Dart_kCanonicalizeUrl) {
+ // url is already canonicalized.
+ return url;
}
- if (!Dart_IsString(url)) {
- return Dart_NewApiError("url is not a string");
+ 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;
}
- if (tag == Dart_kImportTag) {
- // Embedder handles all requests for external libraries.
- if (embedder_provided_handler_ == NULL) {
- return Dart_NewApiError("Unable to import module as no library tag "
- "handler has been provided by embedder");
- }
- return embedder_provided_handler_(tag, library, url);
- }
- ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl));
- if (tag == Dart_kCanonicalizeUrl) {
- // url is already canonicalized.
- return url;
- }
Dart_Handle source = GetSource(url_string);
if (Dart_IsError(source)) {
return source;
@@ -594,6 +593,170 @@ Dart_Handle Service::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle library,
}
+void Service::MaybeInjectVMServiceLibrary(Isolate* isolate) {
+ if (service_isolate_ != NULL) {
+ // Service isolate already exists.
+ return;
+ }
+ if (!Service::IsServiceIsolateName(isolate->name())) {
+ // Not service isolate.
+ return;
+ }
+ service_isolate_ = isolate;
+ ASSERT(isolate != NULL);
+
+ 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();
+}
+
+
+static void ShutdownIsolate(uword parameter) {
+ Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
+ {
+ // 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("Service shutting down: %s\n", error.ToErrorCString());
+ }
+ Dart::RunShutdownCallback();
+ }
+ {
+ // Shut the isolate down.
+ SwitchIsolateScope switch_scope(isolate);
+ Dart::ShutdownIsolate();
+ }
+}
+
+
+class RunServiceTask : public ThreadPool::Task {
+ public:
+ virtual void Run() {
+ ASSERT(Isolate::Current() == NULL);
+ char* error = NULL;
+ Isolate* isolate = NULL;
+
+ Dart_IsolateCreateCallback create_callback = Isolate::CreateCallback();
+ if (create_callback == NULL) {
+ Service::FinishedInitializing();
+ return;
+ }
+
+ isolate =
+ reinterpret_cast<Isolate*>(create_callback(Service::kServiceIsolateName,
+ NULL,
+ NULL,
+ NULL,
+ &error));
+ Isolate::SetCurrent(NULL);
+
+ if (isolate == NULL) {
+ OS::PrintErr("Service startup error: %s\n", error);
+ Service::FinishedInitializing();
+ return;
+ }
+
+ RunMain(isolate);
+
+ Service::FinishedInitializing();
+
+ isolate->message_handler()->Run(Dart::thread_pool(),
+ NULL,
+ ShutdownIsolate,
+ reinterpret_cast<uword>(isolate));
+ }
+
+ 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()) {
+ // 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.
+ 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.
+ return;
+ }
+ ASSERT(result.IsReceivePort());
+ const ReceivePort& rp = ReceivePort::Cast(result);
+ Service::SetLoadPort(rp.Id());
+ }
+};
+
+
+void Service::RunService() {
+ ASSERT(monitor_ == NULL);
+ monitor_ = new Monitor();
+ ASSERT(monitor_ != NULL);
+ Dart::thread_pool()->Run(new RunServiceTask());
+}
+
// A handler for a per-isolate request.
//
// If a handler returns true, the reply is complete and ready to be
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service/vmservice.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698