From 6ccae15ef0b96b1b4db642020a249bb9cff204df Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Thu, 8 Dec 2011 19:35:18 +0000 Subject: [PATCH] Modified __cxa_end_catch to handle dependent exceptions. llvm-svn: 146172 --- libcxxabi/src/cxa_exception.cpp | 59 ++++++++++++++++++++++----------- libcxxabi/src/cxa_exception.hpp | 2 ++ libcxxabi/www/spec.html | 2 +- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp index 90e9032d7cbf..6022740f4c49 100644 --- a/libcxxabi/src/cxa_exception.cpp +++ b/libcxxabi/src/cxa_exception.cpp @@ -65,14 +65,14 @@ static bool isDependentException(_Unwind_Exception *unwind) throw() { return (unwind->exception_class & 0xFF) == 0x01; } -// TODO: This needs to be atomic -static int incrementHandlerCount(__cxa_exception *exception) throw() { - return ++exception->handlerCount; +// This does not need to be atomic +static inline int incrementHandlerCount(__cxa_exception *exception) throw() { + return ++exception->handlerCount; } -// TODO: This needs to be atomic -static int decrementHandlerCount(__cxa_exception *exception) throw() { - return --exception->handlerCount; +// This does not need to be atomic +static inline int decrementHandlerCount(__cxa_exception *exception) throw() { + return --exception->handlerCount; } #include "fallback_malloc.cpp" @@ -192,7 +192,7 @@ LIBCXXABI_NORETURN void __cxa_throw(void * thrown_exception, std::type_info * tinfo, void (*dest)(void *)) { __cxa_eh_globals *globals = __cxa_get_globals(); __cxa_exception *exception = exception_from_thrown_object(thrown_exception); - + exception->unexpectedHandler = std::get_unexpected(); exception->terminateHandler = std::get_terminate(); exception->exceptionType = tinfo; @@ -202,8 +202,11 @@ __cxa_throw(void * thrown_exception, std::type_info * tinfo, void (*dest)(void * globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local exception->unwindHeader.exception_cleanup = exception_cleanup_func; +#if __arm__ + _Unwind_SjLj_RaiseException(&exception->unwindHeader); +#else _Unwind_RaiseException(&exception->unwindHeader); - +#endif // If we get here, some kind of unwinding error has occurred. failed_throw(exception); } @@ -227,6 +230,8 @@ void * __cxa_begin_catch(void * exceptionObject) throw() { __cxa_eh_globals *globals = __cxa_get_globals(); __cxa_exception *exception = exception_from_exception_object(exceptionObject); +// TODO: Handle foreign exceptions? How? + // Increment the handler count, removing the flag about being rethrown exception->handlerCount = exception->handlerCount < 0 ? -exception->handlerCount + 1 : exception->handlerCount + 1; @@ -249,28 +254,44 @@ Upon exit for any reason, a handler must call: This routine: * Locates the most recently caught exception and decrements its handler count. * Removes the exception from the caught exception stack, if the handler count goes to zero. -* Destroys the exception if the handler count goes to zero, and the exception was not re-thrown by throw. +* If the handler count goes down to zero, and the exception was not re-thrown + by throw, it locates the primary exception (which may be the same as the one + it's handling) and decrements its reference count. If that reference count + goes to zero, the function destroys the exception. In any case, if the current + exception is a dependent exception, it destroys that. */ void __cxa_end_catch() { - __cxa_eh_globals *globals = __cxa_get_globals(); + __cxa_eh_globals *globals = __cxa_get_globals_fast(); // __cxa_get_globals called in __cxa_begin_catch __cxa_exception *current_exception = globals->caughtExceptions; if (NULL != current_exception) { if (current_exception->handlerCount < 0) { // The exception has been rethrown if (0 == incrementHandlerCount(current_exception)) { + // Remove from the chain of uncaught exceptions globals->caughtExceptions = current_exception->nextException; - // Howard says: If the exception has been rethrown, don't destroy. - } + // but don't destroy + } } - else { + else { // The exception has not been rethrown if (0 == decrementHandlerCount(current_exception)) { - // Remove from the chain of uncaught exceptions + // Remove from the chain of uncaught exceptions globals->caughtExceptions = current_exception->nextException; - if (!isDependentException(¤t_exception->unwindHeader)) - _Unwind_DeleteException(¤t_exception->unwindHeader); - else { - // TODO: deal with a dependent exception + if (isDependentException(¤t_exception->unwindHeader)) { + // Reset current_exception to primaryException and deallocate the dependent exception + __cxa_dependent_exception* deh = + reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1; + current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1; + __cxa_free_dependent_exception(deh); + } + // Destroy the primary exception only if its referenceCount goes to 0 + // (this decrement must be atomic) + if (__sync_sub_and_fetch(¤t_exception->referenceCount, size_t(1)) == 0) + { + void* thrown_object = thrown_object_from_exception(current_exception); + if (NULL != current_exception->exceptionDestructor) + current_exception->exceptionDestructor(thrown_object); + __cxa_free_exception(thrown_object); } } } @@ -306,7 +327,7 @@ extern LIBCXXABI_NORETURN void __cxa_rethrow() { std::terminate (); // Mark the exception as being rethrown - exception->handlerCount = -exception->handlerCount ; // TODO: Atomic + exception->handlerCount = -exception->handlerCount ; // TODO: Atomic #if __arm__ (void) _Unwind_SjLj_Resume_or_Rethrow(&exception->unwindHeader); diff --git a/libcxxabi/src/cxa_exception.hpp b/libcxxabi/src/cxa_exception.hpp index 9681298a6068..8f795f0d1004 100644 --- a/libcxxabi/src/cxa_exception.hpp +++ b/libcxxabi/src/cxa_exception.hpp @@ -56,6 +56,8 @@ namespace __cxxabiv1 { _Unwind_Exception unwindHeader; }; + +// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html struct __cxa_dependent_exception { #if __LP64__ diff --git a/libcxxabi/www/spec.html b/libcxxabi/www/spec.html index 63c325c416ce..a391a8dbeca1 100644 --- a/libcxxabi/www/spec.html +++ b/libcxxabi/www/spec.html @@ -114,7 +114,7 @@ additional memory to hold private data. If memory can not be allocated, call ✓ ✓ - +✓