|
12 | 12 | #include "lib/stacktrace.h" |
13 | 13 |
|
14 | 14 | #include "vm/dart_api_impl.h" |
| 15 | +#include "vm/dart_api_state.h" |
15 | 16 | #include "vm/dart_entry.h" |
16 | 17 | #include "vm/datastream.h" |
17 | 18 | #include "vm/debugger.h" |
@@ -538,24 +539,6 @@ CatchEntryMoves* CatchEntryMovesMapReader::ReadCompressedCatchEntryMovesSuffix( |
538 | 539 | return moves; |
539 | 540 | } |
540 | 541 |
|
541 | | -static void FindErrorHandler(uword* handler_pc, |
542 | | - uword* handler_sp, |
543 | | - uword* handler_fp) { |
544 | | - StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, |
545 | | - Thread::Current(), |
546 | | - StackFrameIterator::kNoCrossThreadIteration); |
547 | | - StackFrame* frame = frames.NextFrame(); |
548 | | - ASSERT(frame != nullptr); |
549 | | - while (!frame->IsEntryFrame()) { |
550 | | - frame = frames.NextFrame(); |
551 | | - ASSERT(frame != nullptr); |
552 | | - } |
553 | | - ASSERT(frame->IsEntryFrame()); |
554 | | - *handler_pc = frame->pc(); |
555 | | - *handler_sp = frame->sp(); |
556 | | - *handler_fp = frame->fp(); |
557 | | -} |
558 | | - |
559 | 542 | static void ClearLazyDeopts(Thread* thread, uword frame_pointer) { |
560 | 543 | if (thread->pending_deopts().HasPendingDeopts()) { |
561 | 544 | // We may be jumping over frames scheduled for lazy deopt. Remove these |
@@ -590,19 +573,40 @@ static void ClearLazyDeopts(Thread* thread, uword frame_pointer) { |
590 | 573 | } |
591 | 574 | } |
592 | 575 |
|
| 576 | +enum ExceptionType { kPassObject, kPassHandle, kPassUnboxed }; |
| 577 | + |
593 | 578 | static void JumpToExceptionHandler(Thread* thread, |
594 | 579 | uword program_counter, |
595 | 580 | uword stack_pointer, |
596 | 581 | uword frame_pointer, |
597 | 582 | const Object& exception_object, |
598 | | - const Object& stacktrace_object) { |
| 583 | + const Object& stacktrace_object, |
| 584 | + ExceptionType type = kPassObject) { |
599 | 585 | bool clear_deopt = false; |
600 | 586 | uword remapped_pc = thread->pending_deopts().RemapExceptionPCForDeopt( |
601 | 587 | program_counter, frame_pointer, &clear_deopt); |
602 | | - thread->set_active_exception(exception_object); |
| 588 | + uword run_exception_pc = StubCode::RunExceptionHandler().EntryPoint(); |
| 589 | + switch (type) { |
| 590 | + case kPassObject: |
| 591 | + thread->set_active_exception(exception_object); |
| 592 | + break; |
| 593 | + case kPassHandle: { |
| 594 | + LocalHandle* handle = |
| 595 | + thread->api_top_scope()->local_handles()->AllocateHandle(); |
| 596 | + handle->set_ptr(exception_object.ptr()); |
| 597 | + thread->set_active_exception(handle); |
| 598 | + break; |
| 599 | + } |
| 600 | + case kPassUnboxed: { |
| 601 | + thread->set_active_exception(exception_object); |
| 602 | + run_exception_pc = StubCode::RunExceptionHandlerUnbox().EntryPoint(); |
| 603 | + break; |
| 604 | + } |
| 605 | + default: |
| 606 | + UNREACHABLE(); |
| 607 | + } |
603 | 608 | thread->set_active_stacktrace(stacktrace_object); |
604 | 609 | thread->set_resume_pc(remapped_pc); |
605 | | - uword run_exception_pc = StubCode::RunExceptionHandler().EntryPoint(); |
606 | 610 | Exceptions::JumpToFrame(thread, run_exception_pc, stack_pointer, |
607 | 611 | frame_pointer, clear_deopt); |
608 | 612 | } |
@@ -1012,36 +1016,43 @@ void Exceptions::PropagateError(const Error& error) { |
1012 | 1016 | const Instance& stk = Instance::Handle(zone, uhe.stacktrace()); |
1013 | 1017 | Exceptions::ReThrow(thread, exc, stk); |
1014 | 1018 | } else { |
| 1019 | + const Instance& stk = StackTrace::Handle(zone); // Null stacktrace. |
1015 | 1020 | // Return to the invocation stub and return this error object. The |
1016 | 1021 | // C++ code which invoked this dart sequence can check and do the |
1017 | 1022 | // appropriate thing. |
1018 | | - uword handler_pc = 0; |
1019 | | - uword handler_sp = 0; |
1020 | | - uword handler_fp = 0; |
1021 | | - FindErrorHandler(&handler_pc, &handler_sp, &handler_fp); |
1022 | | - JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, error, |
1023 | | - StackTrace::Handle(zone)); // Null stacktrace. |
1024 | | - } |
1025 | | - UNREACHABLE(); |
1026 | | -} |
1027 | | - |
1028 | | -void Exceptions::PropagateToEntry(const Error& error) { |
1029 | | - Thread* thread = Thread::Current(); |
1030 | | - Zone* zone = thread->zone(); |
1031 | | - ASSERT(thread->top_exit_frame_info() != 0); |
1032 | | - Instance& stacktrace = Instance::Handle(zone); |
1033 | | - if (error.IsUnhandledException()) { |
1034 | | - const UnhandledException& uhe = UnhandledException::Cast(error); |
1035 | | - stacktrace = uhe.stacktrace(); |
1036 | | - } else { |
1037 | | - stacktrace = Exceptions::CurrentStackTrace(); |
| 1023 | + StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread, |
| 1024 | + StackFrameIterator::kNoCrossThreadIteration); |
| 1025 | + StackFrame* frame = frames.NextFrame(); |
| 1026 | + StackFrame* prev = frame; |
| 1027 | + ASSERT(frame != nullptr); |
| 1028 | + while (!frame->IsEntryFrame()) { |
| 1029 | + prev = frame; |
| 1030 | + frame = frames.NextFrame(); |
| 1031 | + ASSERT(frame != nullptr); |
| 1032 | + } |
| 1033 | + if (frame->pc() == StubCode::InvokeDartCode().EntryPoint()) { |
| 1034 | + // This is an FFI callback using the invocation stub as a marker. Real use |
| 1035 | + // of invocation stub would be in the middle, not the entry point. Use the |
| 1036 | + // callback's exceptional return value instead of the error unless the |
| 1037 | + // return type is Dart_Handle. |
| 1038 | + ASSERT(prev->IsDartFrame()); |
| 1039 | + frame = prev; |
| 1040 | + const Function& func = |
| 1041 | + Function::Handle(zone, frame->LookupDartFunction()); |
| 1042 | + ASSERT(func.IsFfiCallbackTrampoline()); |
| 1043 | + if (func.FfiCSignatureReturnsHandle()) { |
| 1044 | + JumpToExceptionHandler(thread, frame->pc(), frame->sp(), frame->fp(), |
| 1045 | + error, stk, kPassHandle); |
| 1046 | + } else { |
| 1047 | + const Instance& val = |
| 1048 | + Instance::Handle(zone, func.FfiCallbackExceptionalReturn()); |
| 1049 | + JumpToExceptionHandler(thread, frame->pc(), frame->sp(), frame->fp(), |
| 1050 | + val, stk, kPassUnboxed); |
| 1051 | + } |
| 1052 | + } |
| 1053 | + JumpToExceptionHandler(thread, frame->pc(), frame->sp(), frame->fp(), error, |
| 1054 | + stk); |
1038 | 1055 | } |
1039 | | - uword handler_pc = 0; |
1040 | | - uword handler_sp = 0; |
1041 | | - uword handler_fp = 0; |
1042 | | - FindErrorHandler(&handler_pc, &handler_sp, &handler_fp); |
1043 | | - JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, error, |
1044 | | - stacktrace); |
1045 | 1056 | UNREACHABLE(); |
1046 | 1057 | } |
1047 | 1058 |
|
|
0 commit comments