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(); |
} |