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 "lib/mirrors.h" | 10 #include "lib/mirrors.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 namespace dart { | 38 namespace dart { |
39 | 39 |
40 DEFINE_FLAG(bool, trace_isolates, false, | 40 DEFINE_FLAG(bool, trace_isolates, false, |
41 "Trace isolate creation and shut down."); | 41 "Trace isolate creation and shut down."); |
42 DEFINE_FLAG(bool, pause_isolates_on_start, false, | 42 DEFINE_FLAG(bool, pause_isolates_on_start, false, |
43 "Pause isolates before starting."); | 43 "Pause isolates before starting."); |
44 DEFINE_FLAG(bool, pause_isolates_on_exit, false, | 44 DEFINE_FLAG(bool, pause_isolates_on_exit, false, |
45 "Pause isolates exiting."); | 45 "Pause isolates exiting."); |
46 | 46 |
47 | 47 |
| 48 // Quick access to the locally defined isolate() method. |
| 49 #define I (isolate()) |
| 50 |
| 51 |
48 void Isolate::RegisterClass(const Class& cls) { | 52 void Isolate::RegisterClass(const Class& cls) { |
49 class_table()->Register(cls); | 53 class_table()->Register(cls); |
50 } | 54 } |
51 | 55 |
52 | 56 |
53 void Isolate::RegisterClassAt(intptr_t index, const Class& cls) { | 57 void Isolate::RegisterClassAt(intptr_t index, const Class& cls) { |
54 class_table()->RegisterAt(index, cls); | 58 class_table()->RegisterAt(index, cls); |
55 } | 59 } |
56 | 60 |
57 | 61 |
58 void Isolate::ValidateClassTable() { | 62 void Isolate::ValidateClassTable() { |
59 class_table()->Validate(); | 63 class_table()->Validate(); |
60 } | 64 } |
61 | 65 |
62 | 66 |
63 class IsolateMessageHandler : public MessageHandler { | 67 class IsolateMessageHandler : public MessageHandler { |
64 public: | 68 public: |
65 explicit IsolateMessageHandler(Isolate* isolate); | 69 explicit IsolateMessageHandler(Isolate* isolate); |
66 ~IsolateMessageHandler(); | 70 ~IsolateMessageHandler(); |
67 | 71 |
68 const char* name() const; | 72 const char* name() const; |
69 void MessageNotify(Message::Priority priority); | 73 void MessageNotify(Message::Priority priority); |
70 bool HandleMessage(Message* message); | 74 bool HandleMessage(Message* message); |
71 | 75 |
72 #if defined(DEBUG) | 76 #if defined(DEBUG) |
73 // Check that it is safe to access this handler. | 77 // Check that it is safe to access this handler. |
74 void CheckAccess(); | 78 void CheckAccess(); |
75 #endif | 79 #endif |
76 bool IsCurrentIsolate() const; | 80 bool IsCurrentIsolate() const; |
77 virtual Isolate* GetIsolate() const { return isolate_; } | 81 virtual Isolate* isolate() const { return isolate_; } |
78 bool UnhandledExceptionCallbackHandler(const Object& message, | 82 bool UnhandledExceptionCallbackHandler(const Object& message, |
79 const UnhandledException& error); | 83 const UnhandledException& error); |
80 | 84 |
81 private: | 85 private: |
82 bool ProcessUnhandledException(const Object& message, const Error& result); | 86 bool ProcessUnhandledException(const Object& message, const Error& result); |
83 RawFunction* ResolveCallbackFunction(); | 87 RawFunction* ResolveCallbackFunction(); |
84 Isolate* isolate_; | 88 Isolate* isolate_; |
85 }; | 89 }; |
86 | 90 |
87 | 91 |
88 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) | 92 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) |
89 : isolate_(isolate) { | 93 : isolate_(isolate) { |
90 } | 94 } |
91 | 95 |
92 | 96 |
93 IsolateMessageHandler::~IsolateMessageHandler() { | 97 IsolateMessageHandler::~IsolateMessageHandler() { |
94 } | 98 } |
95 | 99 |
96 const char* IsolateMessageHandler::name() const { | 100 const char* IsolateMessageHandler::name() const { |
97 return isolate_->name(); | 101 return isolate_->name(); |
98 } | 102 } |
99 | 103 |
100 | 104 |
101 void IsolateMessageHandler::MessageNotify(Message::Priority priority) { | 105 void IsolateMessageHandler::MessageNotify(Message::Priority priority) { |
102 if (priority >= Message::kOOBPriority) { | 106 if (priority >= Message::kOOBPriority) { |
103 // Handle out of band messages even if the isolate is busy. | 107 // Handle out of band messages even if the isolate is busy. |
104 isolate_->ScheduleInterrupts(Isolate::kMessageInterrupt); | 108 I->ScheduleInterrupts(Isolate::kMessageInterrupt); |
105 } | 109 } |
106 Dart_MessageNotifyCallback callback = isolate_->message_notify_callback(); | 110 Dart_MessageNotifyCallback callback = I->message_notify_callback(); |
107 if (callback) { | 111 if (callback) { |
108 // Allow the embedder to handle message notification. | 112 // Allow the embedder to handle message notification. |
109 (*callback)(Api::CastIsolate(isolate_)); | 113 (*callback)(Api::CastIsolate(I)); |
110 } | 114 } |
111 } | 115 } |
112 | 116 |
113 | 117 |
114 bool IsolateMessageHandler::HandleMessage(Message* message) { | 118 bool IsolateMessageHandler::HandleMessage(Message* message) { |
115 StartIsolateScope start_scope(isolate_); | 119 StartIsolateScope start_scope(I); |
116 StackZone zone(isolate_); | 120 StackZone zone(I); |
117 HandleScope handle_scope(isolate_); | 121 HandleScope handle_scope(I); |
118 // TODO(turnidge): Rework collection total dart execution. This can | 122 // TODO(turnidge): Rework collection total dart execution. This can |
119 // overcount when other things (gc, compilation) are active. | 123 // overcount when other things (gc, compilation) are active. |
120 TIMERSCOPE(isolate_, time_dart_execution); | 124 TIMERSCOPE(isolate_, time_dart_execution); |
121 | 125 |
122 // If the message is in band we lookup the handler to dispatch to. If the | 126 // If the message is in band we lookup the handler to dispatch to. If the |
123 // receive port was closed, we drop the message without deserializing it. | 127 // receive port was closed, we drop the message without deserializing it. |
124 Object& msg_handler = Object::Handle(); | 128 Object& msg_handler = Object::Handle(I); |
125 if (!message->IsOOB()) { | 129 if (!message->IsOOB()) { |
126 msg_handler = DartLibraryCalls::LookupHandler(message->dest_port()); | 130 msg_handler = DartLibraryCalls::LookupHandler(message->dest_port()); |
127 if (msg_handler.IsError()) { | 131 if (msg_handler.IsError()) { |
128 return ProcessUnhandledException(Object::null_instance(), | 132 return ProcessUnhandledException(Object::null_instance(), |
129 Error::Cast(msg_handler)); | 133 Error::Cast(msg_handler)); |
130 } | 134 } |
131 if (msg_handler.IsNull()) { | 135 if (msg_handler.IsNull()) { |
132 delete message; | 136 // If the port has been closed then the message will be dropped at this |
| 137 // point. Make sure to post to the delivery failure port in that case. |
| 138 if (message->RedirectToDeliveryFailurePort()) { |
| 139 PortMap::PostMessage(message); |
| 140 } else { |
| 141 delete message; |
| 142 } |
133 return true; | 143 return true; |
134 } | 144 } |
135 } | 145 } |
136 | 146 |
137 // Parse the message. | 147 // Parse the message. |
138 SnapshotReader reader(message->data(), message->len(), | 148 SnapshotReader reader(message->data(), message->len(), Snapshot::kMessage, I); |
139 Snapshot::kMessage, Isolate::Current()); | 149 const Object& msg_obj = Object::Handle(I, reader.ReadObject()); |
140 const Object& msg_obj = Object::Handle(reader.ReadObject()); | |
141 if (msg_obj.IsError()) { | 150 if (msg_obj.IsError()) { |
142 // An error occurred while reading the message. | 151 // An error occurred while reading the message. |
143 return ProcessUnhandledException(Object::null_instance(), | 152 return ProcessUnhandledException(Object::null_instance(), |
144 Error::Cast(msg_obj)); | 153 Error::Cast(msg_obj)); |
145 } | 154 } |
146 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { | 155 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { |
147 // TODO(turnidge): We need to decide what an isolate does with | 156 // TODO(turnidge): We need to decide what an isolate does with |
148 // malformed messages. If they (eventually) come from a remote | 157 // malformed messages. If they (eventually) come from a remote |
149 // machine, then it might make sense to drop the message entirely. | 158 // machine, then it might make sense to drop the message entirely. |
150 // In the case that the message originated locally, which is | 159 // In the case that the message originated locally, which is |
151 // always true for now, then this should never occur. | 160 // always true for now, then this should never occur. |
152 UNREACHABLE(); | 161 UNREACHABLE(); |
153 } | 162 } |
154 | 163 |
155 Instance& msg = Instance::Handle(); | 164 Instance& msg = Instance::Handle(I); |
156 msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null. | 165 msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null. |
157 | 166 |
158 bool success = true; | 167 bool success = true; |
159 if (message->IsOOB()) { | 168 if (message->IsOOB()) { |
160 Service::HandleIsolateMessage(isolate_, msg); | 169 ASSERT(msg.IsArray()); |
| 170 const Object& oob_tag = Object::Handle(I, Array::Cast(msg).At(0)); |
| 171 ASSERT(oob_tag.IsSmi()); |
| 172 switch (Smi::Cast(oob_tag).Value()) { |
| 173 case Message::kServiceOOBMsg: { |
| 174 Service::HandleIsolateMessage(I, msg); |
| 175 break; |
| 176 } |
| 177 default: { |
| 178 UNREACHABLE(); |
| 179 break; |
| 180 } |
| 181 } |
161 } else { | 182 } else { |
162 const Object& result = Object::Handle( | 183 const Object& result = Object::Handle(I, |
163 DartLibraryCalls::HandleMessage(msg_handler, msg)); | 184 DartLibraryCalls::HandleMessage(msg_handler, msg)); |
164 if (result.IsError()) { | 185 if (result.IsError()) { |
165 success = ProcessUnhandledException(msg, Error::Cast(result)); | 186 success = ProcessUnhandledException(msg, Error::Cast(result)); |
166 } else { | 187 } else { |
167 ASSERT(result.IsNull()); | 188 ASSERT(result.IsNull()); |
168 } | 189 } |
169 } | 190 } |
170 delete message; | 191 delete message; |
171 return success; | 192 return success; |
172 } | 193 } |
173 | 194 |
174 | 195 |
175 RawFunction* IsolateMessageHandler::ResolveCallbackFunction() { | 196 RawFunction* IsolateMessageHandler::ResolveCallbackFunction() { |
176 ASSERT(isolate_->object_store()->unhandled_exception_handler() != NULL); | 197 ASSERT(I->object_store()->unhandled_exception_handler() != NULL); |
177 String& callback_name = String::Handle(isolate_); | 198 String& callback_name = String::Handle(I); |
178 if (isolate_->object_store()->unhandled_exception_handler() != | 199 if (I->object_store()->unhandled_exception_handler() != String::null()) { |
179 String::null()) { | 200 callback_name = I->object_store()->unhandled_exception_handler(); |
180 callback_name = isolate_->object_store()->unhandled_exception_handler(); | |
181 } else { | 201 } else { |
182 callback_name = String::New("_unhandledExceptionCallback"); | 202 callback_name = String::New("_unhandledExceptionCallback"); |
183 } | 203 } |
184 Library& lib = | 204 Library& lib = Library::Handle(I, I->object_store()->isolate_library()); |
185 Library::Handle(isolate_, isolate_->object_store()->isolate_library()); | 205 Function& func = Function::Handle(I, lib.LookupLocalFunction(callback_name)); |
186 Function& func = | |
187 Function::Handle(isolate_, lib.LookupLocalFunction(callback_name)); | |
188 if (func.IsNull()) { | 206 if (func.IsNull()) { |
189 lib = isolate_->object_store()->root_library(); | 207 lib = I->object_store()->root_library(); |
190 // Note: bootstrap code in builtin library may attempt to resolve a | 208 // Note: bootstrap code in builtin library may attempt to resolve a |
191 // callback function before the script is fully loaded, in which case | 209 // callback function before the script is fully loaded, in which case |
192 // the root library may not be registered yet. | 210 // the root library may not be registered yet. |
193 if (!lib.IsNull()) { | 211 if (!lib.IsNull()) { |
194 func = lib.LookupLocalFunction(callback_name); | 212 func = lib.LookupLocalFunction(callback_name); |
195 } | 213 } |
196 } | 214 } |
197 return func.raw(); | 215 return func.raw(); |
198 } | 216 } |
199 | 217 |
200 | 218 |
201 bool IsolateMessageHandler::UnhandledExceptionCallbackHandler( | 219 bool IsolateMessageHandler::UnhandledExceptionCallbackHandler( |
202 const Object& message, const UnhandledException& error) { | 220 const Object& message, const UnhandledException& error) { |
203 const Instance& cause = Instance::Handle(isolate_, error.exception()); | 221 const Instance& cause = Instance::Handle(I, error.exception()); |
204 const Instance& stacktrace = | 222 const Instance& stacktrace = Instance::Handle(I, error.stacktrace()); |
205 Instance::Handle(isolate_, error.stacktrace()); | |
206 | 223 |
207 // Wrap these args into an IsolateUncaughtException object. | 224 // Wrap these args into an IsolateUncaughtException object. |
208 const Array& exception_args = Array::Handle(Array::New(3)); | 225 const Array& exception_args = Array::Handle(I, Array::New(3)); |
209 exception_args.SetAt(0, message); | 226 exception_args.SetAt(0, message); |
210 exception_args.SetAt(1, cause); | 227 exception_args.SetAt(1, cause); |
211 exception_args.SetAt(2, stacktrace); | 228 exception_args.SetAt(2, stacktrace); |
212 const Object& exception = | 229 const Object& exception = Object::Handle(I, |
213 Object::Handle(isolate_, | 230 Exceptions::Create(Exceptions::kIsolateUnhandledException, |
214 Exceptions::Create(Exceptions::kIsolateUnhandledException, | 231 exception_args)); |
215 exception_args)); | |
216 if (exception.IsError()) { | 232 if (exception.IsError()) { |
217 return false; | 233 return false; |
218 } | 234 } |
219 ASSERT(exception.IsInstance()); | 235 ASSERT(exception.IsInstance()); |
220 | 236 |
221 // Invoke script's callback function. | 237 // Invoke script's callback function. |
222 Object& function = Object::Handle(isolate_, ResolveCallbackFunction()); | 238 Object& function = Object::Handle(I, ResolveCallbackFunction()); |
223 if (function.IsNull() || function.IsError()) { | 239 if (function.IsNull() || function.IsError()) { |
224 return false; | 240 return false; |
225 } | 241 } |
226 const Array& callback_args = Array::Handle(Array::New(1)); | 242 const Array& callback_args = Array::Handle(I, Array::New(1)); |
227 callback_args.SetAt(0, exception); | 243 callback_args.SetAt(0, exception); |
228 const Object& result = | 244 const Object& result = Object::Handle(I, |
229 Object::Handle(DartEntry::InvokeFunction(Function::Cast(function), | 245 DartEntry::InvokeFunction(Function::Cast(function), callback_args)); |
230 callback_args)); | |
231 if (result.IsError()) { | 246 if (result.IsError()) { |
232 const Error& err = Error::Cast(result); | 247 const Error& err = Error::Cast(result); |
233 OS::PrintErr("failed calling unhandled exception callback: %s\n", | 248 OS::PrintErr("failed calling unhandled exception callback: %s\n", |
234 err.ToErrorCString()); | 249 err.ToErrorCString()); |
235 return false; | 250 return false; |
236 } | 251 } |
237 | 252 |
238 ASSERT(result.IsBool()); | 253 ASSERT(result.IsBool()); |
239 bool continue_from_exception = Bool::Cast(result).value(); | 254 bool continue_from_exception = Bool::Cast(result).value(); |
240 if (continue_from_exception) { | 255 if (continue_from_exception) { |
241 isolate_->object_store()->clear_sticky_error(); | 256 I->object_store()->clear_sticky_error(); |
242 } | 257 } |
243 return continue_from_exception; | 258 return continue_from_exception; |
244 } | 259 } |
245 | 260 |
246 #if defined(DEBUG) | 261 #if defined(DEBUG) |
247 void IsolateMessageHandler::CheckAccess() { | 262 void IsolateMessageHandler::CheckAccess() { |
248 ASSERT(IsCurrentIsolate()); | 263 ASSERT(IsCurrentIsolate()); |
249 } | 264 } |
250 #endif | 265 #endif |
251 | 266 |
252 | 267 |
253 bool IsolateMessageHandler::IsCurrentIsolate() const { | 268 bool IsolateMessageHandler::IsCurrentIsolate() const { |
254 return (isolate_ == Isolate::Current()); | 269 return (I == Isolate::Current()); |
255 } | 270 } |
256 | 271 |
257 | 272 |
258 bool IsolateMessageHandler::ProcessUnhandledException( | 273 bool IsolateMessageHandler::ProcessUnhandledException( |
259 const Object& message, const Error& result) { | 274 const Object& message, const Error& result) { |
260 if (result.IsUnhandledException()) { | 275 if (result.IsUnhandledException()) { |
261 // Invoke the isolate's uncaught exception handler, if it exists. | 276 // Invoke the isolate's uncaught exception handler, if it exists. |
262 const UnhandledException& error = UnhandledException::Cast(result); | 277 const UnhandledException& error = UnhandledException::Cast(result); |
263 RawInstance* exception = error.exception(); | 278 RawInstance* exception = error.exception(); |
264 if ((exception != isolate_->object_store()->out_of_memory()) && | 279 if ((exception != I->object_store()->out_of_memory()) && |
265 (exception != isolate_->object_store()->stack_overflow())) { | 280 (exception != I->object_store()->stack_overflow())) { |
266 if (UnhandledExceptionCallbackHandler(message, error)) { | 281 if (UnhandledExceptionCallbackHandler(message, error)) { |
267 return true; | 282 return true; |
268 } | 283 } |
269 } | 284 } |
270 } | 285 } |
271 | 286 |
272 // Invoke the isolate's unhandled exception callback if there is one. | 287 // Invoke the isolate's unhandled exception callback if there is one. |
273 if (Isolate::UnhandledExceptionCallback() != NULL) { | 288 if (Isolate::UnhandledExceptionCallback() != NULL) { |
274 Dart_EnterScope(); | 289 Dart_EnterScope(); |
275 Dart_Handle error = Api::NewHandle(isolate_, result.raw()); | 290 Dart_Handle error = Api::NewHandle(I, result.raw()); |
276 (Isolate::UnhandledExceptionCallback())(error); | 291 (Isolate::UnhandledExceptionCallback())(error); |
277 Dart_ExitScope(); | 292 Dart_ExitScope(); |
278 } | 293 } |
279 | 294 |
280 isolate_->object_store()->set_sticky_error(result); | 295 I->object_store()->set_sticky_error(result); |
281 return false; | 296 return false; |
282 } | 297 } |
283 | 298 |
284 | 299 |
285 #if defined(DEBUG) | 300 #if defined(DEBUG) |
286 // static | 301 // static |
287 void BaseIsolate::AssertCurrent(BaseIsolate* isolate) { | 302 void BaseIsolate::AssertCurrent(BaseIsolate* isolate) { |
288 ASSERT(isolate == Isolate::Current()); | 303 ASSERT(isolate == Isolate::Current()); |
289 } | 304 } |
290 #endif // defined(DEBUG) | 305 #endif // defined(DEBUG) |
(...skipping 915 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1206 return func.raw(); | 1221 return func.raw(); |
1207 } | 1222 } |
1208 | 1223 |
1209 | 1224 |
1210 void IsolateSpawnState::Cleanup() { | 1225 void IsolateSpawnState::Cleanup() { |
1211 SwitchIsolateScope switch_scope(isolate()); | 1226 SwitchIsolateScope switch_scope(isolate()); |
1212 Dart::ShutdownIsolate(); | 1227 Dart::ShutdownIsolate(); |
1213 } | 1228 } |
1214 | 1229 |
1215 } // namespace dart | 1230 } // namespace dart |
OLD | NEW |