Skip to content

Commit 6ccae15

Browse files
author
Howard Hinnant
committed
Modified __cxa_end_catch to handle dependent exceptions.
llvm-svn: 146172
1 parent 0b9b9da commit 6ccae15

File tree

3 files changed

+43
-20
lines changed

3 files changed

+43
-20
lines changed

libcxxabi/src/cxa_exception.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,14 @@ static bool isDependentException(_Unwind_Exception *unwind) throw() {
6565
return (unwind->exception_class & 0xFF) == 0x01;
6666
}
6767

68-
// TODO: This needs to be atomic
69-
static int incrementHandlerCount(__cxa_exception *exception) throw() {
70-
return ++exception->handlerCount;
68+
// This does not need to be atomic
69+
static inline int incrementHandlerCount(__cxa_exception *exception) throw() {
70+
return ++exception->handlerCount;
7171
}
7272

73-
// TODO: This needs to be atomic
74-
static int decrementHandlerCount(__cxa_exception *exception) throw() {
75-
return --exception->handlerCount;
73+
// This does not need to be atomic
74+
static inline int decrementHandlerCount(__cxa_exception *exception) throw() {
75+
return --exception->handlerCount;
7676
}
7777

7878
#include "fallback_malloc.cpp"
@@ -192,7 +192,7 @@ LIBCXXABI_NORETURN void
192192
__cxa_throw(void * thrown_exception, std::type_info * tinfo, void (*dest)(void *)) {
193193
__cxa_eh_globals *globals = __cxa_get_globals();
194194
__cxa_exception *exception = exception_from_thrown_object(thrown_exception);
195-
195+
196196
exception->unexpectedHandler = std::get_unexpected();
197197
exception->terminateHandler = std::get_terminate();
198198
exception->exceptionType = tinfo;
@@ -202,8 +202,11 @@ __cxa_throw(void * thrown_exception, std::type_info * tinfo, void (*dest)(void *
202202
globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
203203

204204
exception->unwindHeader.exception_cleanup = exception_cleanup_func;
205+
#if __arm__
206+
_Unwind_SjLj_RaiseException(&exception->unwindHeader);
207+
#else
205208
_Unwind_RaiseException(&exception->unwindHeader);
206-
209+
#endif
207210
// If we get here, some kind of unwinding error has occurred.
208211
failed_throw(exception);
209212
}
@@ -227,6 +230,8 @@ void * __cxa_begin_catch(void * exceptionObject) throw() {
227230
__cxa_eh_globals *globals = __cxa_get_globals();
228231
__cxa_exception *exception = exception_from_exception_object(exceptionObject);
229232

233+
// TODO: Handle foreign exceptions? How?
234+
230235
// Increment the handler count, removing the flag about being rethrown
231236
exception->handlerCount = exception->handlerCount < 0 ?
232237
-exception->handlerCount + 1 : exception->handlerCount + 1;
@@ -249,28 +254,44 @@ Upon exit for any reason, a handler must call:
249254
This routine:
250255
* Locates the most recently caught exception and decrements its handler count.
251256
* Removes the exception from the caught exception stack, if the handler count goes to zero.
252-
* Destroys the exception if the handler count goes to zero, and the exception was not re-thrown by throw.
257+
* If the handler count goes down to zero, and the exception was not re-thrown
258+
by throw, it locates the primary exception (which may be the same as the one
259+
it's handling) and decrements its reference count. If that reference count
260+
goes to zero, the function destroys the exception. In any case, if the current
261+
exception is a dependent exception, it destroys that.
253262
*/
254263
void __cxa_end_catch() {
255-
__cxa_eh_globals *globals = __cxa_get_globals();
264+
__cxa_eh_globals *globals = __cxa_get_globals_fast(); // __cxa_get_globals called in __cxa_begin_catch
256265
__cxa_exception *current_exception = globals->caughtExceptions;
257266

258267
if (NULL != current_exception) {
259268
if (current_exception->handlerCount < 0) {
260269
// The exception has been rethrown
261270
if (0 == incrementHandlerCount(current_exception)) {
271+
// Remove from the chain of uncaught exceptions
262272
globals->caughtExceptions = current_exception->nextException;
263-
// Howard says: If the exception has been rethrown, don't destroy.
264-
}
273+
// but don't destroy
274+
}
265275
}
266-
else {
276+
else { // The exception has not been rethrown
267277
if (0 == decrementHandlerCount(current_exception)) {
268-
// Remove from the chain of uncaught exceptions
278+
// Remove from the chain of uncaught exceptions
269279
globals->caughtExceptions = current_exception->nextException;
270-
if (!isDependentException(&current_exception->unwindHeader))
271-
_Unwind_DeleteException(&current_exception->unwindHeader);
272-
else {
273-
// TODO: deal with a dependent exception
280+
if (isDependentException(&current_exception->unwindHeader)) {
281+
// Reset current_exception to primaryException and deallocate the dependent exception
282+
__cxa_dependent_exception* deh =
283+
reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1;
284+
current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1;
285+
__cxa_free_dependent_exception(deh);
286+
}
287+
// Destroy the primary exception only if its referenceCount goes to 0
288+
// (this decrement must be atomic)
289+
if (__sync_sub_and_fetch(&current_exception->referenceCount, size_t(1)) == 0)
290+
{
291+
void* thrown_object = thrown_object_from_exception(current_exception);
292+
if (NULL != current_exception->exceptionDestructor)
293+
current_exception->exceptionDestructor(thrown_object);
294+
__cxa_free_exception(thrown_object);
274295
}
275296
}
276297
}
@@ -306,7 +327,7 @@ extern LIBCXXABI_NORETURN void __cxa_rethrow() {
306327
std::terminate ();
307328

308329
// Mark the exception as being rethrown
309-
exception->handlerCount = -exception->handlerCount ; // TODO: Atomic
330+
exception->handlerCount = -exception->handlerCount ; // TODO: Atomic
310331

311332
#if __arm__
312333
(void) _Unwind_SjLj_Resume_or_Rethrow(&exception->unwindHeader);

libcxxabi/src/cxa_exception.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ namespace __cxxabiv1 {
5656

5757
_Unwind_Exception unwindHeader;
5858
};
59+
60+
// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
5961

6062
struct __cxa_dependent_exception {
6163
#if __LP64__

libcxxabi/www/spec.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
</td>
115115
<td>&#10003;</td>
116116
<td>&#10003;</td>
117-
<td></td>
117+
<td>&#10003;</td>
118118
</tr>
119119

120120
<tr>

0 commit comments

Comments
 (0)