summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cxxabi.h19
-rw-r--r--src/cxa_exception.cpp113
-rw-r--r--www/spec.html42
3 files changed, 128 insertions, 46 deletions
diff --git a/include/cxxabi.h b/include/cxxabi.h
index 933ff21..6d04555 100644
--- a/include/cxxabi.h
+++ b/include/cxxabi.h
@@ -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
diff --git a/src/cxa_exception.cpp b/src/cxa_exception.cpp
index e717bc7..9df0564 100644
--- a/src/cxa_exception.cpp
+++ b/src/cxa_exception.cpp
@@ -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
diff --git a/www/spec.html b/www/spec.html
index 8d7a127..f0a10dc 100644
--- a/www/spec.html
+++ b/www/spec.html
@@ -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>