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 |