Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/isolate.h" | 5 #include "vm/isolate.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "platform/json.h" | 9 #include "platform/json.h" |
| 10 #include "vm/code_observers.h" | 10 #include "vm/code_observers.h" |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 virtual Isolate* isolate() const { return isolate_; } | 99 virtual Isolate* isolate() const { return isolate_; } |
| 100 bool UnhandledExceptionCallbackHandler(const Object& message, | 100 bool UnhandledExceptionCallbackHandler(const Object& message, |
| 101 const UnhandledException& error); | 101 const UnhandledException& error); |
| 102 | 102 |
| 103 private: | 103 private: |
| 104 // Keep in sync with isolate_patch.dart. | 104 // Keep in sync with isolate_patch.dart. |
| 105 enum { | 105 enum { |
| 106 kPauseMsg = 1, | 106 kPauseMsg = 1, |
| 107 kResumeMsg = 2, | 107 kResumeMsg = 2, |
| 108 kPingMsg = 3, | 108 kPingMsg = 3, |
| 109 kKillMsg = 4, | |
| 109 | 110 |
| 110 kImmediateAction = 0, | 111 kImmediateAction = 0, |
| 111 kBeforeNextEventAction = 1, | 112 kBeforeNextEventAction = 1, |
| 112 kAsEventAction = 2 | 113 kAsEventAction = 2 |
| 113 }; | 114 }; |
| 114 | 115 |
| 115 void HandleLibMessage(const Array& message); | 116 // A result of false indicates that the isolate should terminate the |
| 117 // processing of further events. | |
| 118 bool HandleLibMessage(const Array& message); | |
|
siva
2014/12/13 00:24:05
Not for this CL but it might be more readable to h
Ivan Posva
2014/12/13 00:36:47
Seems like a plan.
| |
| 119 | |
| 116 bool ProcessUnhandledException(const Object& message, const Error& result); | 120 bool ProcessUnhandledException(const Object& message, const Error& result); |
| 117 RawFunction* ResolveCallbackFunction(); | 121 RawFunction* ResolveCallbackFunction(); |
| 118 Isolate* isolate_; | 122 Isolate* isolate_; |
| 119 }; | 123 }; |
| 120 | 124 |
| 121 | 125 |
| 122 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) | 126 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) |
| 123 : isolate_(isolate) { | 127 : isolate_(isolate) { |
| 124 } | 128 } |
| 125 | 129 |
| 126 | 130 |
| 127 IsolateMessageHandler::~IsolateMessageHandler() { | 131 IsolateMessageHandler::~IsolateMessageHandler() { |
| 128 } | 132 } |
| 129 | 133 |
| 130 const char* IsolateMessageHandler::name() const { | 134 const char* IsolateMessageHandler::name() const { |
| 131 return isolate_->name(); | 135 return isolate_->name(); |
| 132 } | 136 } |
| 133 | 137 |
| 134 | 138 |
| 135 // Isolate library OOB messages are fixed sized arrays which have the | 139 // Isolate library OOB messages are fixed sized arrays which have the |
| 136 // following format: | 140 // following format: |
| 137 // [ OOB dispatch, Isolate library dispatch, <message specific data> ] | 141 // [ OOB dispatch, Isolate library dispatch, <message specific data> ] |
| 138 void IsolateMessageHandler::HandleLibMessage(const Array& message) { | 142 bool IsolateMessageHandler::HandleLibMessage(const Array& message) { |
| 139 if (message.Length() < 2) return; | 143 if (message.Length() < 2) return true; |
| 140 const Object& type = Object::Handle(I, message.At(1)); | 144 const Object& type = Object::Handle(I, message.At(1)); |
| 141 if (!type.IsSmi()) return; | 145 if (!type.IsSmi()) return true; |
| 142 const Smi& msg_type = Smi::Cast(type); | 146 const Smi& msg_type = Smi::Cast(type); |
| 143 switch (msg_type.Value()) { | 147 switch (msg_type.Value()) { |
| 144 case kPauseMsg: { | 148 case kPauseMsg: { |
| 145 // [ OOB, kPauseMsg, pause capability, resume capability ] | 149 // [ OOB, kPauseMsg, pause capability, resume capability ] |
| 146 if (message.Length() != 4) return; | 150 if (message.Length() != 4) return true; |
| 147 Object& obj = Object::Handle(I, message.At(2)); | 151 Object& obj = Object::Handle(I, message.At(2)); |
| 148 if (!obj.IsCapability()) return; | 152 if (!I->VerifyPauseCapability(obj)) return true; |
| 149 if (!I->VerifyPauseCapability(Capability::Cast(obj))) return; | |
| 150 obj = message.At(3); | 153 obj = message.At(3); |
| 151 if (!obj.IsCapability()) return; | 154 if (!obj.IsCapability()) return true; |
| 152 if (I->AddResumeCapability(Capability::Cast(obj))) { | 155 if (I->AddResumeCapability(Capability::Cast(obj))) { |
| 153 increment_paused(); | 156 increment_paused(); |
| 154 } | 157 } |
| 155 break; | 158 break; |
| 156 } | 159 } |
| 157 case kResumeMsg: { | 160 case kResumeMsg: { |
| 158 // [ OOB, kResumeMsg, pause capability, resume capability ] | 161 // [ OOB, kResumeMsg, pause capability, resume capability ] |
| 159 if (message.Length() != 4) return; | 162 if (message.Length() != 4) return true; |
| 160 Object& obj = Object::Handle(I, message.At(2)); | 163 Object& obj = Object::Handle(I, message.At(2)); |
| 161 if (!obj.IsCapability()) return; | 164 if (!I->VerifyPauseCapability(obj)) return true; |
| 162 if (!I->VerifyPauseCapability(Capability::Cast(obj))) return; | |
| 163 obj = message.At(3); | 165 obj = message.At(3); |
| 164 if (!obj.IsCapability()) return; | 166 if (!obj.IsCapability()) return true; |
| 165 if (I->RemoveResumeCapability(Capability::Cast(obj))) { | 167 if (I->RemoveResumeCapability(Capability::Cast(obj))) { |
| 166 decrement_paused(); | 168 decrement_paused(); |
| 167 } | 169 } |
| 168 break; | 170 break; |
| 169 } | 171 } |
| 170 case kPingMsg: { | 172 case kPingMsg: { |
| 171 // [ OOB, kPingMsg, responsePort, pingType ] | 173 // [ OOB, kPingMsg, responsePort, priority ] |
| 172 if (message.Length() != 4) return; | 174 if (message.Length() != 4) return true; |
| 173 const Object& obj2 = Object::Handle(I, message.At(2)); | 175 const Object& obj2 = Object::Handle(I, message.At(2)); |
| 174 if (!obj2.IsSendPort()) return; | 176 if (!obj2.IsSendPort()) return true; |
| 175 const SendPort& send_port = SendPort::Cast(obj2); | 177 const SendPort& send_port = SendPort::Cast(obj2); |
| 176 const Object& obj3 = Object::Handle(I, message.At(3)); | 178 const Object& obj3 = Object::Handle(I, message.At(3)); |
| 177 if (!obj3.IsSmi()) return; | 179 if (!obj3.IsSmi()) return true; |
| 178 const intptr_t ping_type = Smi::Cast(obj3).Value(); | 180 const intptr_t priority = Smi::Cast(obj3).Value(); |
| 179 if (ping_type == kImmediateAction) { | 181 if (priority == kImmediateAction) { |
| 180 uint8_t* data = NULL; | 182 uint8_t* data = NULL; |
| 181 intptr_t len = 0; | 183 intptr_t len = 0; |
| 182 SerializeObject(Object::null_instance(), &data, &len); | 184 SerializeObject(Object::null_instance(), &data, &len); |
| 183 PortMap::PostMessage(new Message(send_port.Id(), | 185 PortMap::PostMessage(new Message(send_port.Id(), |
| 184 data, len, | 186 data, len, |
| 185 Message::kNormalPriority)); | 187 Message::kNormalPriority)); |
| 186 } else if (ping_type == kBeforeNextEventAction) { | 188 } else { |
| 189 ASSERT((priority == kBeforeNextEventAction) || | |
| 190 (priority == kAsEventAction)); | |
| 187 // Update the message so that it will be handled immediately when it | 191 // Update the message so that it will be handled immediately when it |
| 188 // is picked up from the message queue the next time. | 192 // is picked up from the message queue the next time. |
| 189 message.SetAt( | 193 message.SetAt( |
| 190 0, Smi::Handle(I, Smi::New(Message::kDelayedIsolateLibOOBMsg))); | 194 0, Smi::Handle(I, Smi::New(Message::kDelayedIsolateLibOOBMsg))); |
| 191 message.SetAt(3, Smi::Handle(I, Smi::New(kImmediateAction))); | 195 message.SetAt(3, Smi::Handle(I, Smi::New(kImmediateAction))); |
| 192 uint8_t* data = NULL; | 196 uint8_t* data = NULL; |
| 193 intptr_t len = 0; | 197 intptr_t len = 0; |
| 194 SerializeObject(message, &data, &len); | 198 SerializeObject(message, &data, &len); |
| 195 this->PostMessage(new Message(Message::kIllegalPort, | 199 this->PostMessage(new Message(Message::kIllegalPort, |
| 196 data, len, | 200 data, len, |
| 197 Message::kNormalPriority), | 201 Message::kNormalPriority), |
| 198 true /* at_head */); | 202 priority == kBeforeNextEventAction /* at_head */); |
| 199 } else if (ping_type == kAsEventAction) { | 203 } |
| 204 break; | |
| 205 } | |
| 206 case kKillMsg: { | |
| 207 // [ OOB, kKillMsg, terminate capability, priority ] | |
| 208 if (message.Length() != 4) return true; | |
| 209 Object& obj = Object::Handle(I, message.At(3)); | |
| 210 if (!obj.IsSmi()) return true; | |
| 211 const intptr_t priority = Smi::Cast(obj).Value(); | |
| 212 if (priority == kImmediateAction) { | |
| 213 obj = message.At(2); | |
| 214 // Signal that the isolate should stop execution. | |
| 215 return !I->VerifyTerminateCapability(obj); | |
| 216 } else { | |
| 217 ASSERT((priority == kBeforeNextEventAction) || | |
| 218 (priority == kAsEventAction)); | |
| 200 // Update the message so that it will be handled immediately when it | 219 // Update the message so that it will be handled immediately when it |
| 201 // is picked up from the message queue the next time. | 220 // is picked up from the message queue the next time. |
| 202 message.SetAt( | 221 message.SetAt( |
| 203 0, Smi::Handle(I, Smi::New(Message::kDelayedIsolateLibOOBMsg))); | 222 0, Smi::Handle(I, Smi::New(Message::kDelayedIsolateLibOOBMsg))); |
| 204 message.SetAt(3, Smi::Handle(I, Smi::New(kImmediateAction))); | 223 message.SetAt(3, Smi::Handle(I, Smi::New(kImmediateAction))); |
| 205 uint8_t* data = NULL; | 224 uint8_t* data = NULL; |
| 206 intptr_t len = 0; | 225 intptr_t len = 0; |
| 207 SerializeObject(message, &data, &len); | 226 SerializeObject(message, &data, &len); |
| 208 this->PostMessage(new Message(Message::kIllegalPort, | 227 this->PostMessage(new Message(Message::kIllegalPort, |
| 209 data, len, | 228 data, len, |
| 210 Message::kNormalPriority)); | 229 Message::kNormalPriority), |
| 230 priority == kBeforeNextEventAction /* at_head */); | |
| 211 } | 231 } |
| 212 break; | 232 break; |
| 213 } | 233 } |
| 214 #if defined(DEBUG) | 234 #if defined(DEBUG) |
| 215 // Malformed OOB messages are silently ignored in release builds. | 235 // Malformed OOB messages are silently ignored in release builds. |
| 216 default: | 236 default: |
| 217 UNREACHABLE(); | 237 UNREACHABLE(); |
| 218 break; | 238 break; |
| 219 #endif // defined(DEBUG) | 239 #endif // defined(DEBUG) |
| 220 } | 240 } |
| 241 return true; | |
| 221 } | 242 } |
| 222 | 243 |
| 223 | 244 |
| 224 void IsolateMessageHandler::MessageNotify(Message::Priority priority) { | 245 void IsolateMessageHandler::MessageNotify(Message::Priority priority) { |
| 225 if (priority >= Message::kOOBPriority) { | 246 if (priority >= Message::kOOBPriority) { |
| 226 // Handle out of band messages even if the isolate is busy. | 247 // Handle out of band messages even if the isolate is busy. |
| 227 I->ScheduleInterrupts(Isolate::kMessageInterrupt); | 248 I->ScheduleInterrupts(Isolate::kMessageInterrupt); |
| 228 } | 249 } |
| 229 Dart_MessageNotifyCallback callback = I->message_notify_callback(); | 250 Dart_MessageNotifyCallback callback = I->message_notify_callback(); |
| 230 if (callback) { | 251 if (callback) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 const Array& oob_msg = Array::Cast(msg); | 317 const Array& oob_msg = Array::Cast(msg); |
| 297 if (oob_msg.Length() > 0) { | 318 if (oob_msg.Length() > 0) { |
| 298 const Object& oob_tag = Object::Handle(I, oob_msg.At(0)); | 319 const Object& oob_tag = Object::Handle(I, oob_msg.At(0)); |
| 299 if (oob_tag.IsSmi()) { | 320 if (oob_tag.IsSmi()) { |
| 300 switch (Smi::Cast(oob_tag).Value()) { | 321 switch (Smi::Cast(oob_tag).Value()) { |
| 301 case Message::kServiceOOBMsg: { | 322 case Message::kServiceOOBMsg: { |
| 302 Service::HandleIsolateMessage(I, oob_msg); | 323 Service::HandleIsolateMessage(I, oob_msg); |
| 303 break; | 324 break; |
| 304 } | 325 } |
| 305 case Message::kIsolateLibOOBMsg: { | 326 case Message::kIsolateLibOOBMsg: { |
| 306 HandleLibMessage(oob_msg); | 327 success = HandleLibMessage(oob_msg); |
| 307 break; | 328 break; |
| 308 } | 329 } |
| 309 #if defined(DEBUG) | 330 #if defined(DEBUG) |
| 310 // Malformed OOB messages are silently ignored in release builds. | 331 // Malformed OOB messages are silently ignored in release builds. |
| 311 default: { | 332 default: { |
| 312 UNREACHABLE(); | 333 UNREACHABLE(); |
| 313 break; | 334 break; |
| 314 } | 335 } |
| 315 #endif // defined(DEBUG) | 336 #endif // defined(DEBUG) |
| 316 } | 337 } |
| 317 } | 338 } |
| 318 } | 339 } |
| 319 } | 340 } |
| 320 } else if (message->dest_port() == Message::kIllegalPort) { | 341 } else if (message->dest_port() == Message::kIllegalPort) { |
| 321 // Check whether this is a delayed OOB message which needed handling as | 342 // Check whether this is a delayed OOB message which needed handling as |
| 322 // part of the regular message dispatch. All other messages are dropped on | 343 // part of the regular message dispatch. All other messages are dropped on |
| 323 // the floor. | 344 // the floor. |
| 324 if (msg.IsArray()) { | 345 if (msg.IsArray()) { |
| 325 const Array& msg_arr = Array::Cast(msg); | 346 const Array& msg_arr = Array::Cast(msg); |
| 326 if (msg_arr.Length() > 0) { | 347 if (msg_arr.Length() > 0) { |
| 327 const Object& oob_tag = Object::Handle(I, msg_arr.At(0)); | 348 const Object& oob_tag = Object::Handle(I, msg_arr.At(0)); |
| 328 if (oob_tag.IsSmi() && | 349 if (oob_tag.IsSmi() && |
| 329 (Smi::Cast(oob_tag).Value() == Message::kDelayedIsolateLibOOBMsg)) { | 350 (Smi::Cast(oob_tag).Value() == Message::kDelayedIsolateLibOOBMsg)) { |
| 330 HandleLibMessage(Array::Cast(msg_arr)); | 351 success = HandleLibMessage(Array::Cast(msg_arr)); |
| 331 } | 352 } |
| 332 } | 353 } |
| 333 } | 354 } |
| 334 } else { | 355 } else { |
| 335 const Object& result = Object::Handle(I, | 356 const Object& result = Object::Handle(I, |
| 336 DartLibraryCalls::HandleMessage(msg_handler, msg)); | 357 DartLibraryCalls::HandleMessage(msg_handler, msg)); |
| 337 if (result.IsError()) { | 358 if (result.IsError()) { |
| 338 success = ProcessUnhandledException(msg, Error::Cast(result)); | 359 success = ProcessUnhandledException(msg, Error::Cast(result)); |
| 339 } else { | 360 } else { |
| 340 ASSERT(result.IsNull()); | 361 ASSERT(result.IsNull()); |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 814 } | 835 } |
| 815 IsolateSpawnState* state = spawn_state(); | 836 IsolateSpawnState* state = spawn_state(); |
| 816 if (state != NULL) { | 837 if (state != NULL) { |
| 817 ASSERT(this == state->isolate()); | 838 ASSERT(this == state->isolate()); |
| 818 Run(); | 839 Run(); |
| 819 } | 840 } |
| 820 return true; | 841 return true; |
| 821 } | 842 } |
| 822 | 843 |
| 823 | 844 |
| 824 bool Isolate::VerifyPauseCapability(const Capability& capability) const { | 845 bool Isolate::VerifyPauseCapability(const Object& capability) const { |
| 825 return !capability.IsNull() && (pause_capability() == capability.Id()); | 846 return !capability.IsNull() && |
| 847 capability.IsCapability() && | |
| 848 (pause_capability() == Capability::Cast(capability).Id()); | |
| 849 } | |
| 850 | |
| 851 | |
| 852 bool Isolate::VerifyTerminateCapability(const Object& capability) const { | |
| 853 return !capability.IsNull() && | |
| 854 capability.IsCapability() && | |
| 855 (terminate_capability() == Capability::Cast(capability).Id()); | |
| 826 } | 856 } |
| 827 | 857 |
| 828 | 858 |
| 829 bool Isolate::AddResumeCapability(const Capability& capability) { | 859 bool Isolate::AddResumeCapability(const Capability& capability) { |
| 830 // Ensure a limit for the number of resume capabilities remembered. | 860 // Ensure a limit for the number of resume capabilities remembered. |
| 831 static const intptr_t kMaxResumeCapabilities = kSmiMax / (6*kWordSize); | 861 static const intptr_t kMaxResumeCapabilities = kSmiMax / (6*kWordSize); |
| 832 | 862 |
| 833 const GrowableObjectArray& caps = GrowableObjectArray::Handle( | 863 const GrowableObjectArray& caps = GrowableObjectArray::Handle( |
| 834 this, object_store()->resume_capabilities()); | 864 this, object_store()->resume_capabilities()); |
| 835 Capability& current = Capability::Handle(this); | 865 Capability& current = Capability::Handle(this); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 967 static void ShutdownIsolate(uword parameter) { | 997 static void ShutdownIsolate(uword parameter) { |
| 968 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 998 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
| 969 { | 999 { |
| 970 // Print the error if there is one. This may execute dart code to | 1000 // Print the error if there is one. This may execute dart code to |
| 971 // print the exception object, so we need to use a StartIsolateScope. | 1001 // print the exception object, so we need to use a StartIsolateScope. |
| 972 StartIsolateScope start_scope(isolate); | 1002 StartIsolateScope start_scope(isolate); |
| 973 StackZone zone(isolate); | 1003 StackZone zone(isolate); |
| 974 HandleScope handle_scope(isolate); | 1004 HandleScope handle_scope(isolate); |
| 975 Error& error = Error::Handle(); | 1005 Error& error = Error::Handle(); |
| 976 error = isolate->object_store()->sticky_error(); | 1006 error = isolate->object_store()->sticky_error(); |
| 977 if (!error.IsNull()) { | 1007 if (!error.IsNull() && !error.IsUnwindError()) { |
| 978 OS::PrintErr("in ShutdownIsolate: %s\n", error.ToErrorCString()); | 1008 OS::PrintErr("in ShutdownIsolate: %s\n", error.ToErrorCString()); |
| 979 } | 1009 } |
| 980 Dart::RunShutdownCallback(); | 1010 Dart::RunShutdownCallback(); |
| 981 } | 1011 } |
| 982 { | 1012 { |
| 983 // Shut the isolate down. | 1013 // Shut the isolate down. |
| 984 SwitchIsolateScope switch_scope(isolate); | 1014 SwitchIsolateScope switch_scope(isolate); |
| 985 Dart::ShutdownIsolate(); | 1015 Dart::ShutdownIsolate(); |
| 986 } | 1016 } |
| 987 } | 1017 } |
| (...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1639 serialized_message_, serialized_message_len_); | 1669 serialized_message_, serialized_message_len_); |
| 1640 } | 1670 } |
| 1641 | 1671 |
| 1642 | 1672 |
| 1643 void IsolateSpawnState::Cleanup() { | 1673 void IsolateSpawnState::Cleanup() { |
| 1644 SwitchIsolateScope switch_scope(I); | 1674 SwitchIsolateScope switch_scope(I); |
| 1645 Dart::ShutdownIsolate(); | 1675 Dart::ShutdownIsolate(); |
| 1646 } | 1676 } |
| 1647 | 1677 |
| 1648 } // namespace dart | 1678 } // namespace dart |
| OLD | NEW |