Changeset View
Changeset View
Standalone View
Standalone View
contrib/libcxxrt/exception.cc
Show First 20 Lines • Show All 566 Lines • ▼ Show 20 Lines | if ((e >= emergency_buffer) && | ||||
emergency_malloc_free(e); | emergency_malloc_free(e); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
free(e); | free(e); | ||||
} | } | ||||
} | } | ||||
#ifdef __LP64__ | |||||
/** | /** | ||||
theraven: Please can you add an extra condition in this `#if`, so that we can just fall into the `= 0`… | |||||
* There's an ABI bug in __cxa_exception: unwindHeader requires 16-byte | |||||
* alignment but it was broken by the addition of the referenceCount. | |||||
* The unwindHeader is at offset 0x58 in __cxa_exception. In order to keep | |||||
* compatibility with consumers of the broken __cxa_exception, explicitly add | |||||
* padding on allocation (and account for it on free). | |||||
*/ | |||||
static const int exception_alignment_padding = 8; | |||||
#else | |||||
static const int exception_alignment_padding = 0; | |||||
#endif | |||||
/** | |||||
* Allocates an exception structure. Returns a pointer to the space that can | * Allocates an exception structure. Returns a pointer to the space that can | ||||
* be used to store an object of thrown_size bytes. This function will use an | * be used to store an object of thrown_size bytes. This function will use an | ||||
* emergency buffer if malloc() fails, and may block if there are no such | * emergency buffer if malloc() fails, and may block if there are no such | ||||
* buffers available. | * buffers available. | ||||
*/ | */ | ||||
extern "C" void *__cxa_allocate_exception(size_t thrown_size) | extern "C" void *__cxa_allocate_exception(size_t thrown_size) | ||||
{ | { | ||||
size_t size = exception_alignment_padding + sizeof(__cxa_exception) + | size_t size = thrown_size + sizeof(__cxa_exception); | ||||
thrown_size; | |||||
char *buffer = alloc_or_die(size); | char *buffer = alloc_or_die(size); | ||||
return buffer + exception_alignment_padding + sizeof(__cxa_exception); | return buffer+sizeof(__cxa_exception); | ||||
} | } | ||||
extern "C" void *__cxa_allocate_dependent_exception(void) | extern "C" void *__cxa_allocate_dependent_exception(void) | ||||
{ | { | ||||
size_t size = exception_alignment_padding + | size_t size = sizeof(__cxa_dependent_exception); | ||||
sizeof(__cxa_dependent_exception); | |||||
char *buffer = alloc_or_die(size); | char *buffer = alloc_or_die(size); | ||||
return buffer + exception_alignment_padding + | return buffer+sizeof(__cxa_dependent_exception); | ||||
sizeof(__cxa_dependent_exception); | |||||
} | } | ||||
/** | /** | ||||
* __cxa_free_exception() is called when an exception was thrown in between | * __cxa_free_exception() is called when an exception was thrown in between | ||||
* calling __cxa_allocate_exception() and actually throwing the exception. | * calling __cxa_allocate_exception() and actually throwing the exception. | ||||
* This happens when the object's copy constructor throws an exception. | * This happens when the object's copy constructor throws an exception. | ||||
* | * | ||||
* In this implementation, it is also called by __cxa_end_catch() and during | * In this implementation, it is also called by __cxa_end_catch() and during | ||||
Show All 11 Lines | if (0 != ex->exceptionDestructor) | ||||
} | } | ||||
catch(...) | catch(...) | ||||
{ | { | ||||
// FIXME: Check that this is really what the spec says to do. | // FIXME: Check that this is really what the spec says to do. | ||||
std::terminate(); | std::terminate(); | ||||
} | } | ||||
} | } | ||||
free_exception(reinterpret_cast<char*>(ex) - | free_exception(reinterpret_cast<char*>(ex)); | ||||
exception_alignment_padding); | |||||
} | } | ||||
static void releaseException(__cxa_exception *exception) | static void releaseException(__cxa_exception *exception) | ||||
{ | { | ||||
if (isDependentException(exception->unwindHeader.exception_class)) | if (isDependentException(exception->unwindHeader.exception_class)) | ||||
{ | { | ||||
__cxa_free_dependent_exception(exception+1); | __cxa_free_dependent_exception(exception+1); | ||||
return; | return; | ||||
Show All 10 Lines | |||||
void __cxa_free_dependent_exception(void *thrown_exception) | void __cxa_free_dependent_exception(void *thrown_exception) | ||||
{ | { | ||||
__cxa_dependent_exception *ex = reinterpret_cast<__cxa_dependent_exception*>(thrown_exception) - 1; | __cxa_dependent_exception *ex = reinterpret_cast<__cxa_dependent_exception*>(thrown_exception) - 1; | ||||
assert(isDependentException(ex->unwindHeader.exception_class)); | assert(isDependentException(ex->unwindHeader.exception_class)); | ||||
if (ex->primaryException) | if (ex->primaryException) | ||||
{ | { | ||||
releaseException(realExceptionFromException(reinterpret_cast<__cxa_exception*>(ex))); | releaseException(realExceptionFromException(reinterpret_cast<__cxa_exception*>(ex))); | ||||
} | } | ||||
free_exception(reinterpret_cast<char*>(ex) - | free_exception(reinterpret_cast<char*>(ex)); | ||||
exception_alignment_padding); | |||||
} | } | ||||
/** | /** | ||||
* Callback function used with _Unwind_Backtrace(). | * Callback function used with _Unwind_Backtrace(). | ||||
* | * | ||||
* Prints a stack trace. Used only for debugging help. | * Prints a stack trace. Used only for debugging help. | ||||
* | * | ||||
* Note: As of FreeBSD 8.1, dladd() still doesn't work properly, so this only | * Note: As of FreeBSD 8.1, dladd() still doesn't work properly, so this only | ||||
▲ Show 20 Lines • Show All 918 Lines • Show Last 20 Lines |
Please can you add an extra condition in this #if, so that we can just fall into the = 0 path and not touch the rest of the code?