| 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 |