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

Unified Diff: runtime/vm/isolate.cc

Issue 354763004: - Implement Isolate.pause and Isolate.resume. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 6 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
Index: runtime/vm/isolate.cc
===================================================================
--- runtime/vm/isolate.cc (revision 37860)
+++ runtime/vm/isolate.cc (working copy)
@@ -83,6 +83,13 @@
const UnhandledException& error);
private:
+ // Keep in sync with isolate_patch.dart.
+ enum {
+ kPauseMsg = 1,
+ kResumeMsg
+ };
+
+ void HandleLibMessage(const Array& message);
bool ProcessUnhandledException(const Object& message, const Error& result);
RawFunction* ResolveCallbackFunction();
Isolate* isolate_;
@@ -102,6 +109,46 @@
}
+void IsolateMessageHandler::HandleLibMessage(const Array& message) {
siva 2014/07/01 21:42:56 Would be good to document the message formats here
Ivan Posva 2014/07/03 12:51:16 Done.
+ if (message.Length() < 2) return;
+ const Object& type = Object::Handle(I, message.At(1));
+ if (!type.IsSmi()) return;
+ const Smi& msg_type = Smi::Cast(type);
+ switch (msg_type.Value()) {
+ case kPauseMsg: {
+ if (message.Length() != 4) return;
+ Object& obj = Object::Handle(I, message.At(2));
+ if (!obj.IsCapability()) return;
+ if (!I->VerifyPauseCapability(Capability::Cast(obj))) return;
+ obj = message.At(3);
+ if (!obj.IsCapability()) return;
+ if (I->AddPauseCapability(Capability::Cast(obj))) {
+ increment_paused();
+ }
+ break;
+ }
+ case kResumeMsg: {
+ if (message.Length() != 4) return;
+ Object& obj = Object::Handle(I, message.At(2));
+ if (!obj.IsCapability()) return;
+ if (!I->VerifyPauseCapability(Capability::Cast(obj))) return;
+ obj = message.At(3);
+ if (!obj.IsCapability()) return;
+ if (I->RemovePauseCapability(Capability::Cast(obj))) {
+ decrement_paused();
+ }
+ break;
+ }
+#if DEBUG
siva 2014/07/01 21:42:56 #if defined(DEBUG) to be consistent.
Ivan Posva 2014/07/03 12:51:16 Done.
+ // Malformed OOB messages are silently ignored in release builds.
+ default:
+ UNREACHABLE();
+ break;
+#endif // DEBUG
+ }
+}
+
+
void IsolateMessageHandler::MessageNotify(Message::Priority priority) {
if (priority >= Message::kOOBPriority) {
// Handle out of band messages even if the isolate is busy.
@@ -129,6 +176,7 @@
if (!message->IsOOB()) {
msg_handler = DartLibraryCalls::LookupHandler(message->dest_port());
if (msg_handler.IsError()) {
+ delete message;
return ProcessUnhandledException(Object::null_instance(),
Error::Cast(msg_handler));
}
@@ -149,6 +197,7 @@
const Object& msg_obj = Object::Handle(I, reader.ReadObject());
if (msg_obj.IsError()) {
// An error occurred while reading the message.
+ delete message;
return ProcessUnhandledException(Object::null_instance(),
Error::Cast(msg_obj));
}
@@ -166,18 +215,33 @@
bool success = true;
if (message->IsOOB()) {
- ASSERT(msg.IsArray());
- const Object& oob_tag = Object::Handle(I, Array::Cast(msg).At(0));
- ASSERT(oob_tag.IsSmi());
- switch (Smi::Cast(oob_tag).Value()) {
- case Message::kServiceOOBMsg: {
- Service::HandleIsolateMessage(I, msg);
- break;
+ // OOB messages are expected to be fixed length arrays where the first
+ // element is a Smi describing the OOB destination. Messages that do not
+ // confirm to this layout are silently ignored.
+ if (msg.IsArray()) {
+ const Array& oob_msg = Array::Cast(msg);
+ if (oob_msg.Length() > 0) {
+ const Object& oob_tag = Object::Handle(I, oob_msg.At(0));
+ if (oob_tag.IsSmi()) {
+ switch (Smi::Cast(oob_tag).Value()) {
+ case Message::kServiceOOBMsg: {
+ Service::HandleIsolateMessage(I, oob_msg);
+ break;
+ }
+ case Message::kIsolateLibOOBMsg: {
+ HandleLibMessage(oob_msg);
+ break;
+ }
+#if DEBUG
siva 2014/07/01 21:42:56 Ditto.
Ivan Posva 2014/07/03 12:51:16 Done.
+ // Malformed OOB messages are silently ignored in release builds.
+ default: {
+ UNREACHABLE();
+ break;
+ }
+#endif // DEBUG
+ }
+ }
}
- default: {
- UNREACHABLE();
- break;
- }
}
} else {
const Object& result = Object::Handle(I,
@@ -320,6 +384,8 @@
name_(NULL),
start_time_(OS::GetCurrentTimeMicros()),
main_port_(0),
+ pause_capability_(0),
+ terminate_capability_(0),
heap_(NULL),
object_store_(NULL),
top_context_(Context::null()),
@@ -463,6 +529,9 @@
// main thread.
result->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&result));
result->set_main_port(PortMap::CreatePort(result->message_handler()));
+ result->set_pause_capability(result->random()->NextUInt64());
+ result->set_terminate_capability(result->random()->NextUInt64());
+
result->BuildName(name_prefix);
result->debugger_ = new Debugger();
@@ -593,6 +662,52 @@
}
+bool Isolate::VerifyPauseCapability(const Capability& capability) {
+ return !capability.IsNull() && (pause_capability() == capability.Id());
+}
+
+
+bool Isolate::AddPauseCapability(const Capability& capability) {
+ const GrowableObjectArray& caps = GrowableObjectArray::Handle(
+ this, object_store()->pause_capabilities());
+ Capability& current = Capability::Handle(this);
+ intptr_t insertion_index = -1;
+ for (intptr_t i = 0; i < caps.Length(); i++) {
+ current ^= caps.At(i);
+ if (current.IsNull()) {
+ if (insertion_index < 0) {
+ insertion_index = i;
+ }
+ } else if (current.Id() == capability.Id()) {
+ return false;
+ }
+ }
+ if (insertion_index < 0) {
+ caps.Add(capability);
+ } else {
+ caps.SetAt(insertion_index, capability);
+ }
+ return true;
+}
+
+
+bool Isolate::RemovePauseCapability(const Capability& capability) {
+ const GrowableObjectArray& caps = GrowableObjectArray::Handle(
+ this, object_store()->pause_capabilities());
+ Capability& current = Capability::Handle(this);
+ for (intptr_t i = 0; i < caps.Length(); i++) {
+ current ^= caps.At(i);
+ if (!current.IsNull() && (current.Id() == capability.Id())) {
+ // Remove the matching capability from the list.
+ current = Capability::null();
+ caps.SetAt(i, current);
+ return true;
+ }
+ }
+ return false;
+}
+
+
static void StoreError(Isolate* isolate, const Object& obj) {
ASSERT(obj.IsError());
isolate->object_store()->set_sticky_error(Error::Cast(obj));
@@ -772,7 +887,7 @@
void VisitHandle(uword addr) {
FinalizablePersistentHandle* handle =
reinterpret_cast<FinalizablePersistentHandle*>(addr);
- handle->UpdateUnreachable(isolate());
+ handle->UpdateUnreachable(I);
}
private:
@@ -1212,7 +1327,7 @@
return LanguageError::New(msg);
}
} else {
- lib = isolate()->object_store()->root_library();
+ lib = I->object_store()->root_library();
}
ASSERT(!lib.IsNull());
@@ -1254,7 +1369,7 @@
void IsolateSpawnState::Cleanup() {
- SwitchIsolateScope switch_scope(isolate());
+ SwitchIsolateScope switch_scope(I);
Dart::ShutdownIsolate();
}

Powered by Google App Engine
This is Rietveld 408576698