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

Unified Diff: runtime/vm/isolate.cc

Issue 1299493007: Rework service extensions to be safe (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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/isolate.h ('k') | runtime/vm/json_stream.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/isolate.cc
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 7af37bfbcff69f3d9213c7ee37e0aa812b6ec5b6..ab18bf47c79630b487f2801f5c4a48b20792beaa 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -492,6 +492,15 @@ bool IsolateMessageHandler::HandleMessage(Message* message) {
}
}
delete message;
+ if (success) {
+ const Object& result =
+ Object::Handle(zone, I->InvokePendingExtensionCalls());
+ if (result.IsError()) {
+ success = ProcessUnhandledException(Error::Cast(result));
+ } else {
+ ASSERT(result.IsNull());
+ }
+ }
return success;
}
@@ -696,6 +705,8 @@ Isolate::Isolate(const Dart_IsolateFlags& api_flags)
default_tag_(UserTag::null()),
collected_closures_(GrowableObjectArray::null()),
deoptimized_code_array_(GrowableObjectArray::null()),
+ pending_extension_calls_(GrowableObjectArray::null()),
+ registered_extension_handlers_(GrowableObjectArray::null()),
metrics_list_head_(NULL),
compilation_allowed_(true),
cha_(NULL),
@@ -1624,6 +1635,10 @@ void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
visitor->VisitPointer(
reinterpret_cast<RawObject**>(&deoptimized_code_array_));
+ // Visit the pending service extension calls.
+ visitor->VisitPointer(
+ reinterpret_cast<RawObject**>(&pending_extension_calls_));
+
// Visit objects in the debugger.
debugger()->VisitObjectPointers(visitor);
@@ -1845,6 +1860,160 @@ void Isolate::TrackDeoptimizedCode(const Code& code) {
}
+void Isolate::set_pending_extension_calls(const GrowableObjectArray& value) {
+ pending_extension_calls_ = value.raw();
+}
+
+
+void Isolate::set_registered_extension_handlers(
+ const GrowableObjectArray& value) {
+ registered_extension_handlers_ = value.raw();
+}
+
+
+RawObject* Isolate::InvokePendingExtensionCalls() {
+ GrowableObjectArray& calls =
+ GrowableObjectArray::Handle(GetAndClearPendingExtensionCalls());
+ if (calls.IsNull()) {
+ return Object::null();
+ }
+ // Grab run function.
+ const Library& developer_lib = Library::Handle(Library::DeveloperLibrary());
+ ASSERT(!developer_lib.IsNull());
+ const Function& run_extension = Function::Handle(
+ developer_lib.LookupLocalFunction(Symbols::_runExtension()));
+ ASSERT(!run_extension.IsNull());
+
+ const Array& arguments =
+ Array::Handle(Array::New(kPendingEntrySize, Heap::kNew));
+ Object& result = Object::Handle();
+ String& method_name = String::Handle();
+ Instance& closure = Instance::Handle();
+ Array& parameter_keys = Array::Handle();
+ Array& parameter_values = Array::Handle();
+ Instance& reply_port = Instance::Handle();
+ Instance& id = Instance::Handle();
+ for (intptr_t i = 0; i < calls.Length(); i += kPendingEntrySize) {
+ // Grab arguments for call.
+ closure ^= calls.At(i + kPendingHandlerIndex);
+ ASSERT(!closure.IsNull());
+ arguments.SetAt(kPendingHandlerIndex, closure);
+ method_name ^= calls.At(i + kPendingMethodNameIndex);
+ ASSERT(!method_name.IsNull());
+ arguments.SetAt(kPendingMethodNameIndex, method_name);
+ parameter_keys ^= calls.At(i + kPendingKeysIndex);
+ ASSERT(!parameter_keys.IsNull());
+ arguments.SetAt(kPendingKeysIndex, parameter_keys);
+ parameter_values ^= calls.At(i + kPendingValuesIndex);
+ ASSERT(!parameter_values.IsNull());
+ arguments.SetAt(kPendingValuesIndex, parameter_values);
+ reply_port ^= calls.At(i + kPendingReplyPortIndex);
+ ASSERT(!reply_port.IsNull());
+ arguments.SetAt(kPendingReplyPortIndex, reply_port);
+ id ^= calls.At(i + kPendingIdIndex);
+ arguments.SetAt(kPendingIdIndex, id);
+
+ result = DartEntry::InvokeFunction(run_extension, arguments);
+ if (result.IsError()) {
+ if (result.IsUnwindError()) {
+ // Propagate the unwind error. Remaining service extension calls
+ // are dropped.
+ return result.raw();
+ } else {
+ // Send error back over the protocol.
+ Service::PostError(method_name,
+ parameter_keys,
+ parameter_values,
+ reply_port,
+ id,
+ Error::Cast(result));
+ }
+ }
+ result = DartLibraryCalls::DrainMicrotaskQueue();
+ if (result.IsError()) {
+ return result.raw();
+ }
+ }
+ return Object::null();
+}
+
+
+RawGrowableObjectArray* Isolate::GetAndClearPendingExtensionCalls() {
+ RawGrowableObjectArray* r = pending_extension_calls_;
+ pending_extension_calls_ = GrowableObjectArray::null();
+ return r;
+}
+
+
+void Isolate::AppendExtensionCall(const Instance& closure,
+ const String& method_name,
+ const Array& parameter_keys,
+ const Array& parameter_values,
+ const Instance& reply_port,
+ const Instance& id) {
+ GrowableObjectArray& calls =
+ GrowableObjectArray::Handle(pending_extension_calls());
+ if (calls.IsNull()) {
+ calls ^= GrowableObjectArray::New(Heap::kOld);
Ivan Posva 2015/08/27 06:15:29 Why in old space?
Cutch 2015/08/27 13:27:49 Done.
+ ASSERT(!calls.IsNull());
+ set_pending_extension_calls(calls);
+ }
+ ASSERT(kPendingHandlerIndex == 0);
+ calls.Add(closure, Heap::kOld);
Ivan Posva 2015/08/27 06:15:29 ditto here and below. Why old?
Cutch 2015/08/27 13:27:49 Done.
+ ASSERT(kPendingMethodNameIndex == 1);
+ calls.Add(method_name, Heap::kOld);
+ ASSERT(kPendingKeysIndex == 2);
+ calls.Add(parameter_keys, Heap::kOld);
+ ASSERT(kPendingValuesIndex == 3);
+ calls.Add(parameter_values, Heap::kOld);
+ ASSERT(kPendingReplyPortIndex == 4);
+ calls.Add(reply_port, Heap::kOld);
+ ASSERT(kPendingIdIndex == 5);
+ calls.Add(id, Heap::kOld);
+}
+
+
+void Isolate::RegisterExtensionHandler(const String& name,
Ivan Posva 2015/08/27 06:15:29 These are really VM service extension handlers, co
Cutch 2015/08/27 13:27:49 Done.
+ const Instance& closure) {
+ GrowableObjectArray& handlers =
+ GrowableObjectArray::Handle(registered_extension_handlers());
+ if (handlers.IsNull()) {
+ handlers ^= GrowableObjectArray::New(Heap::kOld);
+ set_registered_extension_handlers(handlers);
+ }
+#if defined(DEBUG)
+ {
+ // Sanity check.
+ const Instance& existing_handler =
+ Instance::Handle(LookupExtensionHandler(name));
+ ASSERT(existing_handler.IsNull());
+ }
+#endif
+ ASSERT(kRegisteredNameIndex == 0);
+ handlers.Add(name, Heap::kOld);
+ ASSERT(kRegisteredHandlerIndex == 1);
+ handlers.Add(closure, Heap::kOld);
+}
+
+
+RawInstance* Isolate::LookupExtensionHandler(const String& name) {
Ivan Posva 2015/08/27 06:15:29 Why isn't the extension list not maintained in the
Cutch 2015/08/27 13:27:49 Because doing that in Dart code could lead to inco
Ivan Posva 2015/08/27 18:12:26 Many thanks for the explanation. Please add it as
Cutch 2015/08/27 18:23:29 Done.
+ const GrowableObjectArray& handlers =
+ GrowableObjectArray::Handle(registered_extension_handlers());
+ if (handlers.IsNull()) {
+ return Instance::null();
+ }
+ String& handler_name = String::Handle();
+ for (intptr_t i = 0; i < handlers.Length(); i += kRegisteredEntrySize) {
+ handler_name ^= handlers.At(i + kRegisteredNameIndex);
+ ASSERT(!handler_name.IsNull());
+ if (handler_name.Equals(name)) {
+ return Instance::RawCast(handlers.At(i + kRegisteredHandlerIndex));
+ }
+ }
+ return Instance::null();
+}
+
+
void Isolate::WakePauseEventHandler(Dart_Isolate isolate) {
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
MonitorLocker ml(iso->pause_loop_monitor_);
« no previous file with comments | « runtime/vm/isolate.h ('k') | runtime/vm/json_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698