@@ -65,14 +65,14 @@ static bool isDependentException(_Unwind_Exception *unwind) throw() {
65
65
return (unwind->exception_class & 0xFF ) == 0x01 ;
66
66
}
67
67
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 ;
71
71
}
72
72
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 ;
76
76
}
77
77
78
78
#include " fallback_malloc.cpp"
@@ -192,7 +192,7 @@ LIBCXXABI_NORETURN void
192
192
__cxa_throw (void * thrown_exception, std::type_info * tinfo, void (*dest)(void *)) {
193
193
__cxa_eh_globals *globals = __cxa_get_globals ();
194
194
__cxa_exception *exception = exception_from_thrown_object (thrown_exception);
195
-
195
+
196
196
exception->unexpectedHandler = std::get_unexpected ();
197
197
exception->terminateHandler = std::get_terminate ();
198
198
exception->exceptionType = tinfo;
@@ -202,8 +202,11 @@ __cxa_throw(void * thrown_exception, std::type_info * tinfo, void (*dest)(void *
202
202
globals->uncaughtExceptions += 1 ; // Not atomically, since globals are thread-local
203
203
204
204
exception->unwindHeader .exception_cleanup = exception_cleanup_func;
205
+ #if __arm__
206
+ _Unwind_SjLj_RaiseException (&exception->unwindHeader );
207
+ #else
205
208
_Unwind_RaiseException (&exception->unwindHeader );
206
-
209
+ # endif
207
210
// If we get here, some kind of unwinding error has occurred.
208
211
failed_throw (exception);
209
212
}
@@ -227,6 +230,8 @@ void * __cxa_begin_catch(void * exceptionObject) throw() {
227
230
__cxa_eh_globals *globals = __cxa_get_globals ();
228
231
__cxa_exception *exception = exception_from_exception_object (exceptionObject);
229
232
233
+ // TODO: Handle foreign exceptions? How?
234
+
230
235
// Increment the handler count, removing the flag about being rethrown
231
236
exception->handlerCount = exception->handlerCount < 0 ?
232
237
-exception->handlerCount + 1 : exception->handlerCount + 1 ;
@@ -249,28 +254,44 @@ Upon exit for any reason, a handler must call:
249
254
This routine:
250
255
* Locates the most recently caught exception and decrements its handler count.
251
256
* 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.
253
262
*/
254
263
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
256
265
__cxa_exception *current_exception = globals->caughtExceptions ;
257
266
258
267
if (NULL != current_exception) {
259
268
if (current_exception->handlerCount < 0 ) {
260
269
// The exception has been rethrown
261
270
if (0 == incrementHandlerCount (current_exception)) {
271
+ // Remove from the chain of uncaught exceptions
262
272
globals->caughtExceptions = current_exception->nextException ;
263
- // Howard says: If the exception has been rethrown, don't destroy.
264
- }
273
+ // but don't destroy
274
+ }
265
275
}
266
- else {
276
+ else { // The exception has not been rethrown
267
277
if (0 == decrementHandlerCount (current_exception)) {
268
- // Remove from the chain of uncaught exceptions
278
+ // Remove from the chain of uncaught exceptions
269
279
globals->caughtExceptions = current_exception->nextException ;
270
- if (!isDependentException (¤t_exception->unwindHeader ))
271
- _Unwind_DeleteException (¤t_exception->unwindHeader );
272
- else {
273
- // TODO: deal with a dependent exception
280
+ if (isDependentException (¤t_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 (¤t_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);
274
295
}
275
296
}
276
297
}
@@ -306,7 +327,7 @@ extern LIBCXXABI_NORETURN void __cxa_rethrow() {
306
327
std::terminate ();
307
328
308
329
// Mark the exception as being rethrown
309
- exception->handlerCount = -exception->handlerCount ; // TODO: Atomic
330
+ exception->handlerCount = -exception->handlerCount ; // TODO: Atomic
310
331
311
332
#if __arm__
312
333
(void ) _Unwind_SjLj_Resume_or_Rethrow (&exception->unwindHeader );
0 commit comments