Chromium Code Reviews| Index: runtime/vm/isolate.cc |
| =================================================================== |
| --- runtime/vm/isolate.cc (revision 16063) |
| +++ runtime/vm/isolate.cc (working copy) |
| @@ -48,10 +48,12 @@ |
| #endif |
| bool IsCurrentIsolate() const; |
| virtual Isolate* GetIsolate() const { return isolate_; } |
| + bool UnhandledExceptionCallbackHandler(const Object& message, |
| + const UnhandledException& error); |
| private: |
| - bool ProcessUnhandledException(const Object& result); |
| - |
| + bool ProcessUnhandledException(const Object& message, const Error& result); |
| + RawObject* ResolveCallbackFunction(); |
| Isolate* isolate_; |
| }; |
| @@ -93,7 +95,7 @@ |
| const Object& msg_obj = Object::Handle(reader.ReadObject()); |
| if (msg_obj.IsError()) { |
| // An error occurred while reading the message. |
| - return ProcessUnhandledException(msg_obj); |
| + return ProcessUnhandledException(Instance::Handle(), Error::Cast(msg_obj)); |
| } |
| if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { |
| // TODO(turnidge): We need to decide what an isolate does with |
| @@ -107,24 +109,108 @@ |
| Instance& msg = Instance::Handle(); |
| msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null. |
| + bool success = true; |
| if (message->IsOOB()) { |
| // For now the only OOB messages are Mirrors messages. |
| HandleMirrorsMessage(isolate_, message->reply_port(), msg); |
| - delete message; |
| } else { |
| const Object& result = Object::Handle( |
| DartLibraryCalls::HandleMessage( |
| message->dest_port(), message->reply_port(), msg)); |
| - delete message; |
| if (result.IsError()) { |
| - return ProcessUnhandledException(result); |
| + success = ProcessUnhandledException(msg, Error::Cast(result)); |
| + } else { |
| + ASSERT(result.IsNull()); |
| } |
| - ASSERT(result.IsNull()); |
| } |
| - return true; |
| + delete message; |
| + return success; |
| } |
| +RawObject* IsolateMessageHandler::ResolveCallbackFunction() { |
| + ASSERT(isolate_->object_store()->unhandled_exception_handler() != NULL); |
| + Library& lib = Library::Handle(); |
| + RawString* raw_uri = isolate_->object_store()->isolate_library_uri(); |
| + if (raw_uri != String::null()) { |
| + String& uri = String::Handle(isolate_, raw_uri); |
| + lib = Library::LookupLibrary(uri); |
| + if (lib.IsNull() || lib.IsError()) { |
| + const String& msg = String::Handle(String::NewFormatted( |
| + "Unable to find library '%s'.", uri.ToCString())); |
| + return LanguageError::New(msg); |
| + } |
| + } else { |
| + lib = isolate_->object_store()->root_library(); |
| + raw_uri = lib.url(); |
| + } |
| + ASSERT(!lib.IsNull()); |
| + // Resolve the unhandled exceptions callback function. |
| + const String& callback_name = |
| + String::Handle(isolate_, |
| + isolate_->object_store()->unhandled_exception_handler()); |
| + const Function& func = |
| + Function::Handle(isolate_, lib.LookupLocalFunction(callback_name)); |
| + if (func.IsNull()) { |
| + String& library_uri = String::Handle(isolate_, raw_uri); |
| + const String& msg = String::Handle(isolate_, String::NewFormatted( |
| + "Unable to resolve function '%s' in library '%s'.", |
| + callback_name.ToCString(), library_uri.ToCString())); |
| + return LanguageError::New(msg); |
| + } |
| + return func.raw(); |
| +} |
| + |
| + |
| +bool IsolateMessageHandler::UnhandledExceptionCallbackHandler( |
| + const Object& message, const UnhandledException& error) { |
| + const Instance& cause = Instance::Handle(isolate_, error.exception()); |
| + const Instance& stacktrace = |
| + Instance::Handle(isolate_, error.stacktrace()); |
| + |
| + // Wrap these args into an IsolateUncaughtException object. |
| + GrowableArray<const Object*> exception_args(3); |
| + exception_args.Add(&message); |
| + exception_args.Add(&cause); |
| + exception_args.Add(&stacktrace); |
| + Object& exception = Object::Handle(); |
| + exception = Exceptions::Create(Exceptions::kIsolateUnhandledException, |
| + exception_args); |
| + if (exception.IsError()) { |
| + return false; |
| + } |
| + ASSERT(exception.IsInstance()); |
| + |
| + // Invoke script's callback function. |
| + GrowableArray<const Object*> callback_args(0); |
| + callback_args.Add(&exception); |
| + const Array& kNoArgumentNames = Array::Handle(isolate_); |
| + Object& function = Object::Handle(isolate_, ResolveCallbackFunction()); |
| + if (function.IsError()) { |
| + const Error& err = Error::Cast(function); |
| + OS::PrintErr("failed resolving unhandled exception callback: %s\n", |
| + err.ToErrorCString()); |
| + return false; |
| + } |
| + RawObject* response = DartEntry::InvokeStatic(Function::Cast(function), |
| + callback_args, |
| + kNoArgumentNames); |
| + const Object& result = Object::Handle(response); |
|
siva
2012/12/13 18:30:38
We try not to keep these raw pointers in local var
|
| + if (result.IsError()) { |
| + const Error& err = Error::Cast(result); |
| + OS::PrintErr("failed calling unhandled exception callback: %s\n", |
| + err.ToErrorCString()); |
| + return false; |
| + } |
| + |
| + ASSERT(result.IsBool()); |
| + bool continue_from_exception = (response == Bool::True()); |
|
siva
2012/12/13 18:30:38
bool continue_from_exception = result.value();
|
| + if (continue_from_exception) { |
| + isolate_->object_store()->clear_sticky_error(); |
| + } |
| + return continue_from_exception; |
| +} |
| + |
| #if defined(DEBUG) |
| void IsolateMessageHandler::CheckAccess() { |
| ASSERT(IsCurrentIsolate()); |
| @@ -137,15 +223,29 @@ |
| } |
| -bool IsolateMessageHandler::ProcessUnhandledException(const Object& result) { |
| - isolate_->object_store()->set_sticky_error(Error::Cast(result)); |
| - // Invoke the dart unhandled exception callback if there is one. |
| +bool IsolateMessageHandler::ProcessUnhandledException( |
| + const Object& message, const Error& result) { |
| + if (result.IsUnhandledException()) { |
| + // Invoke the isolate's uncaught exception handler, if it exists. |
| + const UnhandledException& error = UnhandledException::Cast(result); |
| + RawInstance* exception = error.exception(); |
| + if ((exception != isolate_->object_store()->out_of_memory()) && |
| + (exception != isolate_->object_store()->stack_overflow())) { |
| + if (UnhandledExceptionCallbackHandler(message, error)) { |
| + return true; |
| + } |
| + } |
| + } |
| + |
| + // Invoke the isolate's unhandled exception callback if there is one. |
| if (Isolate::UnhandledExceptionCallback() != NULL) { |
| Dart_EnterScope(); |
| Dart_Handle error = Api::NewHandle(isolate_, result.raw()); |
| (Isolate::UnhandledExceptionCallback())(error); |
| Dart_ExitScope(); |
| } |
| + |
| + isolate_->object_store()->set_sticky_error(result); |
| return false; |
| } |