Added __cxa_increment_exception_refcount, __cxa_decrement_exception_refcount, __cxa_current_primary_exception, __cxa_rethrow_primary_exception

llvm-svn: 147106
This commit is contained in:
Howard Hinnant 2011-12-21 23:32:11 +00:00
parent f46669c828
commit e04f51662c
3 changed files with 128 additions and 46 deletions

View File

@ -155,24 +155,6 @@ extern char* __cxa_demangle(const char* mangled_name,
size_t* length,
int* status);
} // extern "C"
} // namespace __cxxabiv1
namespace abi = __cxxabiv1;
// Below are Apple extensions to support implementing C++ ABI in a seperate dylib
namespace __cxxabiapple {
extern "C" {
// Apple additions to support multiple STL stacks that share common
// terminate, unexpected, and new handlers
extern void (*__cxa_terminate_handler)();
extern void (*__cxa_unexpected_handler)();
extern void (*__cxa_new_handler)();
// Apple additions to support C++ 0x exception_ptr class
// These are primitives to wrap a smart pointer around an exception object
extern void * __cxa_current_primary_exception() throw();
@ -185,6 +167,7 @@ extern bool __cxa_uncaught_exception() throw();
} // extern "C"
} // namespace __cxxabiv1
namespace abi = __cxxabiv1;
#endif // __cplusplus

View File

@ -287,13 +287,7 @@ void __cxa_end_catch() {
}
// Destroy the primary exception only if its referenceCount goes to 0
// (this decrement must be atomic)
if (__sync_sub_and_fetch(&current_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);
}
__cxa_decrement_exception_refcount(thrown_object_from_exception(current_exception));
}
}
}
@ -347,6 +341,111 @@ extern LIBCXXABI_NORETURN void __cxa_rethrow() {
failed_throw(exception);
}
/*
If p is not null, atomically increment the referenceCount field of the
__cxa_exception header associated with the thrown object referred to by p.
*/
void
__cxa_increment_exception_refcount(void* p) throw()
{
if (p != NULL )
{
__cxa_exception* header = exception_from_thrown_object(p);
__sync_add_and_fetch(&header->referenceCount, 1);
}
}
/*
If p is not null, atomically decrement the referenceCount field of the
__cxa_exception header associated with the thrown object referred to by p.
If the referenceCount drops to zero, destroy and deallocate the exception.
*/
void
__cxa_decrement_exception_refcount(void* thrown_object) throw()
{
if (thrown_object != NULL )
{
__cxa_exception* header = exception_from_thrown_object(thrown_object);
if (__sync_sub_and_fetch(&header->referenceCount, size_t(1)) == 0)
{
if (NULL != header->exceptionDestructor)
header->exceptionDestructor(thrown_object);
__cxa_free_exception(thrown_object);
}
}
}
/*
Returns a pointer to the thrown object (if any) at the top of the
caughtExceptions stack. Atommically increment the exception's referenceCount.
If there is no such thrown object, returns null.
*/
void*
__cxa_current_primary_exception() throw()
{
// get the current exception
__cxa_eh_globals* globals = __cxa_get_globals();
__cxa_exception* current_exception = globals->caughtExceptions;
if (NULL == current_exception)
return NULL; // No current exception
if (isDependentException(&current_exception->unwindHeader)) {
__cxa_dependent_exception* deh =
reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1;
current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1;
}
void* thrown_object = thrown_object_from_exception(current_exception);
__cxa_increment_exception_refcount(thrown_object);
return thrown_object;
}
/*
If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
stored in exc is called. Otherwise the referenceCount stored in the
primary exception is decremented, destroying the primary if necessary.
Finally the dependent exception is destroyed.
*/
static
void
dependent_exception_cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc)
{
__cxa_dependent_exception* deh =
reinterpret_cast<__cxa_dependent_exception*>(exc + 1) - 1;
if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
std::__terminate(deh->terminateHandler);
__cxa_decrement_exception_refcount(deh->primaryException);
__cxa_free_dependent_exception(deh);
}
/*
If thrown_object is not null, allocate, initialize and thow a dependent
exception.
*/
void
__cxa_rethrow_primary_exception(void* thrown_object)
{
if ( thrown_object != NULL )
{
__cxa_exception* header = exception_from_thrown_object(thrown_object);
__cxa_dependent_exception* deh =
(__cxa_dependent_exception*)__cxa_allocate_dependent_exception();
deh->primaryException = thrown_object;
__cxa_increment_exception_refcount(thrown_object);
deh->exceptionType = header->exceptionType;
deh->unexpectedHandler = std::get_unexpected();
deh->terminateHandler = std::get_terminate();
setDependentExceptionClass(&deh->unwindHeader);
deh->unwindHeader.exception_cleanup = dependent_exception_cleanup;
#if __arm__
_Unwind_SjLj_RaiseException(&deh->unwindHeader);
#else
_Unwind_RaiseException(&deh->unwindHeader);
#endif
// Some sort of unwinding error. Note that terminate is a handler.
__cxa_begin_catch(&deh->unwindHeader);
}
// If we return client will call terminate()
}
} // extern "C"
} // abi

View File

@ -248,9 +248,9 @@ are no caught exceptions.
</p>
</blockquote>
</td>
<td></td>
<td></td>
<td></td>
<td>&#10003;</td>
<td>&#10003;</td>
<td>&#10003;</td>
</tr>
<tr>
@ -265,9 +265,9 @@ zero calls <tt>_Unwind_DeleteException</tt> with the exception object.
</p>
</blockquote>
</td>
<td></td>
<td></td>
<td></td>
<td>&#10003;</td>
<td>&#10003;</td>
<td>&#10003;</td>
</tr>
<tr>
@ -319,9 +319,9 @@ thread.
</p>
</blockquote>
</td>
<td></td>
<td></td>
<td></td>
<td>&#10003;</td>
<td>&#10003;</td>
<td>&#10003;</td>
</tr>
<tr>
@ -335,9 +335,9 @@ thread.
</p>
</blockquote>
</td>
<td></td>
<td></td>
<td></td>
<td>&#10003;</td>
<td>&#10003;</td>
<td>&#10003;</td>
</tr>
<tr>
@ -675,9 +675,9 @@ The currently installed new handler.
</p>
</blockquote>
</td>
<td></td>
<td></td>
<td></td>
<td>&#10003;</td>
<td>&#10003;</td>
<td>&#10003;</td>
</tr>
<tr>
@ -691,9 +691,9 @@ The currently installed terminate handler.
</p>
</blockquote>
</td>
<td></td>
<td></td>
<td></td>
<td>&#10003;</td>
<td>&#10003;</td>
<td>&#10003;</td>
</tr>
<tr>
@ -707,9 +707,9 @@ The currently installed terminate handler.
</p>
</blockquote>
</td>
<td></td>
<td></td>
<td></td>
<td>&#10003;</td>
<td>&#10003;</td>
<td>&#10003;</td>
</tr>