Skip to content

Commit e04f516

Browse files
author
Howard Hinnant
committed
Added __cxa_increment_exception_refcount, __cxa_decrement_exception_refcount, __cxa_current_primary_exception, __cxa_rethrow_primary_exception
llvm-svn: 147106
1 parent f46669c commit e04f516

File tree

3 files changed

+128
-46
lines changed

3 files changed

+128
-46
lines changed

libcxxabi/include/cxxabi.h

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -155,24 +155,6 @@ extern char* __cxa_demangle(const char* mangled_name,
155155
size_t* length,
156156
int* status);
157157

158-
} // extern "C"
159-
} // namespace __cxxabiv1
160-
namespace abi = __cxxabiv1;
161-
162-
163-
164-
165-
166-
// Below are Apple extensions to support implementing C++ ABI in a seperate dylib
167-
namespace __cxxabiapple {
168-
extern "C" {
169-
170-
// Apple additions to support multiple STL stacks that share common
171-
// terminate, unexpected, and new handlers
172-
extern void (*__cxa_terminate_handler)();
173-
extern void (*__cxa_unexpected_handler)();
174-
extern void (*__cxa_new_handler)();
175-
176158
// Apple additions to support C++ 0x exception_ptr class
177159
// These are primitives to wrap a smart pointer around an exception object
178160
extern void * __cxa_current_primary_exception() throw();
@@ -185,6 +167,7 @@ extern bool __cxa_uncaught_exception() throw();
185167

186168
} // extern "C"
187169
} // namespace __cxxabiv1
170+
namespace abi = __cxxabiv1;
188171

189172
#endif // __cplusplus
190173

libcxxabi/src/cxa_exception.cpp

Lines changed: 106 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,13 +287,7 @@ void __cxa_end_catch() {
287287
}
288288
// Destroy the primary exception only if its referenceCount goes to 0
289289
// (this decrement must be atomic)
290-
if (__sync_sub_and_fetch(&current_exception->referenceCount, size_t(1)) == 0)
291-
{
292-
void* thrown_object = thrown_object_from_exception(current_exception);
293-
if (NULL != current_exception->exceptionDestructor)
294-
current_exception->exceptionDestructor(thrown_object);
295-
__cxa_free_exception(thrown_object);
296-
}
290+
__cxa_decrement_exception_refcount(thrown_object_from_exception(current_exception));
297291
}
298292
}
299293
}
@@ -347,6 +341,111 @@ extern LIBCXXABI_NORETURN void __cxa_rethrow() {
347341
failed_throw(exception);
348342
}
349343

344+
/*
345+
If p is not null, atomically increment the referenceCount field of the
346+
__cxa_exception header associated with the thrown object referred to by p.
347+
*/
348+
void
349+
__cxa_increment_exception_refcount(void* p) throw()
350+
{
351+
if (p != NULL )
352+
{
353+
__cxa_exception* header = exception_from_thrown_object(p);
354+
__sync_add_and_fetch(&header->referenceCount, 1);
355+
}
356+
}
357+
358+
/*
359+
If p is not null, atomically decrement the referenceCount field of the
360+
__cxa_exception header associated with the thrown object referred to by p.
361+
If the referenceCount drops to zero, destroy and deallocate the exception.
362+
*/
363+
void
364+
__cxa_decrement_exception_refcount(void* thrown_object) throw()
365+
{
366+
if (thrown_object != NULL )
367+
{
368+
__cxa_exception* header = exception_from_thrown_object(thrown_object);
369+
if (__sync_sub_and_fetch(&header->referenceCount, size_t(1)) == 0)
370+
{
371+
if (NULL != header->exceptionDestructor)
372+
header->exceptionDestructor(thrown_object);
373+
__cxa_free_exception(thrown_object);
374+
}
375+
}
376+
}
377+
378+
/*
379+
Returns a pointer to the thrown object (if any) at the top of the
380+
caughtExceptions stack. Atommically increment the exception's referenceCount.
381+
If there is no such thrown object, returns null.
382+
*/
383+
void*
384+
__cxa_current_primary_exception() throw()
385+
{
386+
// get the current exception
387+
__cxa_eh_globals* globals = __cxa_get_globals();
388+
__cxa_exception* current_exception = globals->caughtExceptions;
389+
if (NULL == current_exception)
390+
return NULL; // No current exception
391+
if (isDependentException(&current_exception->unwindHeader)) {
392+
__cxa_dependent_exception* deh =
393+
reinterpret_cast<__cxa_dependent_exception*>(current_exception + 1) - 1;
394+
current_exception = static_cast<__cxa_exception*>(deh->primaryException) - 1;
395+
}
396+
void* thrown_object = thrown_object_from_exception(current_exception);
397+
__cxa_increment_exception_refcount(thrown_object);
398+
return thrown_object;
399+
}
400+
401+
/*
402+
If reason isn't _URC_FOREIGN_EXCEPTION_CAUGHT, then the terminateHandler
403+
stored in exc is called. Otherwise the referenceCount stored in the
404+
primary exception is decremented, destroying the primary if necessary.
405+
Finally the dependent exception is destroyed.
406+
*/
407+
static
408+
void
409+
dependent_exception_cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc)
410+
{
411+
__cxa_dependent_exception* deh =
412+
reinterpret_cast<__cxa_dependent_exception*>(exc + 1) - 1;
413+
if (_URC_FOREIGN_EXCEPTION_CAUGHT != reason)
414+
std::__terminate(deh->terminateHandler);
415+
__cxa_decrement_exception_refcount(deh->primaryException);
416+
__cxa_free_dependent_exception(deh);
417+
}
418+
419+
/*
420+
If thrown_object is not null, allocate, initialize and thow a dependent
421+
exception.
422+
*/
423+
void
424+
__cxa_rethrow_primary_exception(void* thrown_object)
425+
{
426+
if ( thrown_object != NULL )
427+
{
428+
__cxa_exception* header = exception_from_thrown_object(thrown_object);
429+
__cxa_dependent_exception* deh =
430+
(__cxa_dependent_exception*)__cxa_allocate_dependent_exception();
431+
deh->primaryException = thrown_object;
432+
__cxa_increment_exception_refcount(thrown_object);
433+
deh->exceptionType = header->exceptionType;
434+
deh->unexpectedHandler = std::get_unexpected();
435+
deh->terminateHandler = std::get_terminate();
436+
setDependentExceptionClass(&deh->unwindHeader);
437+
deh->unwindHeader.exception_cleanup = dependent_exception_cleanup;
438+
#if __arm__
439+
_Unwind_SjLj_RaiseException(&deh->unwindHeader);
440+
#else
441+
_Unwind_RaiseException(&deh->unwindHeader);
442+
#endif
443+
// Some sort of unwinding error. Note that terminate is a handler.
444+
__cxa_begin_catch(&deh->unwindHeader);
445+
}
446+
// If we return client will call terminate()
447+
}
448+
350449
} // extern "C"
351450

352451
} // abi

libcxxabi/www/spec.html

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,9 @@
248248
</p>
249249
</blockquote>
250250
</td>
251-
<td></td>
252-
<td></td>
253-
<td></td>
251+
<td>&#10003;</td>
252+
<td>&#10003;</td>
253+
<td>&#10003;</td>
254254
</tr>
255255

256256
<tr>
@@ -265,9 +265,9 @@
265265
</p>
266266
</blockquote>
267267
</td>
268-
<td></td>
269-
<td></td>
270-
<td></td>
268+
<td>&#10003;</td>
269+
<td>&#10003;</td>
270+
<td>&#10003;</td>
271271
</tr>
272272

273273
<tr>
@@ -319,9 +319,9 @@
319319
</p>
320320
</blockquote>
321321
</td>
322-
<td></td>
323-
<td></td>
324-
<td></td>
322+
<td>&#10003;</td>
323+
<td>&#10003;</td>
324+
<td>&#10003;</td>
325325
</tr>
326326

327327
<tr>
@@ -335,9 +335,9 @@
335335
</p>
336336
</blockquote>
337337
</td>
338-
<td></td>
339-
<td></td>
340-
<td></td>
338+
<td>&#10003;</td>
339+
<td>&#10003;</td>
340+
<td>&#10003;</td>
341341
</tr>
342342

343343
<tr>
@@ -675,9 +675,9 @@
675675
</p>
676676
</blockquote>
677677
</td>
678-
<td></td>
679-
<td></td>
680-
<td></td>
678+
<td>&#10003;</td>
679+
<td>&#10003;</td>
680+
<td>&#10003;</td>
681681
</tr>
682682

683683
<tr>
@@ -691,9 +691,9 @@
691691
</p>
692692
</blockquote>
693693
</td>
694-
<td></td>
695-
<td></td>
696-
<td></td>
694+
<td>&#10003;</td>
695+
<td>&#10003;</td>
696+
<td>&#10003;</td>
697697
</tr>
698698

699699
<tr>
@@ -707,9 +707,9 @@
707707
</p>
708708
</blockquote>
709709
</td>
710-
<td></td>
711-
<td></td>
712-
<td></td>
710+
<td>&#10003;</td>
711+
<td>&#10003;</td>
712+
<td>&#10003;</td>
713713
</tr>
714714

715715

0 commit comments

Comments
 (0)