aboutsummaryrefslogtreecommitdiff
path: root/libcxxabi
diff options
context:
space:
mode:
authoritrofimow <i.trofimow@yandex.ru>2024-01-22 19:12:41 +0400
committerGitHub <noreply@github.com>2024-01-22 10:12:41 -0500
commit51e91b64d0deb6a743861c2a0fba84865250036e (patch)
tree1863c3766d4d40d4f4aad9528efdfbfbe0d867c6 /libcxxabi
parent6ba62f4f251763745d39194ecd33ebaf7a739059 (diff)
downloadllvm-51e91b64d0deb6a743861c2a0fba84865250036e.zip
llvm-51e91b64d0deb6a743861c2a0fba84865250036e.tar.gz
llvm-51e91b64d0deb6a743861c2a0fba84865250036e.tar.bz2
[libc++abi] Implement __cxa_init_primary_exception and use it to optimize std::make_exception_ptr (#65534)
This patch implements __cxa_init_primary_exception, an extension to the Itanium C++ ABI. This extension is already present in both libsupc++ and libcxxrt. This patch also starts making use of this function in std::make_exception_ptr: instead of going through a full throw/catch cycle, we are now able to initialize an exception directly, thus making std::make_exception_ptr around 30x faster.
Diffstat (limited to 'libcxxabi')
-rw-r--r--libcxxabi/include/cxxabi.h6
-rw-r--r--libcxxabi/lib/exceptions.exp1
-rw-r--r--libcxxabi/src/cxa_exception.cpp32
3 files changed, 26 insertions, 13 deletions
diff --git a/libcxxabi/include/cxxabi.h b/libcxxabi/include/cxxabi.h
index 6f4f823..d070118 100644
--- a/libcxxabi/include/cxxabi.h
+++ b/libcxxabi/include/cxxabi.h
@@ -36,6 +36,9 @@ class type_info; // forward declaration
// runtime routines use C calling conventions, but are in __cxxabiv1 namespace
namespace __cxxabiv1 {
+
+struct __cxa_exception;
+
extern "C" {
// 2.4.2 Allocating the Exception Object
@@ -43,6 +46,9 @@ extern _LIBCXXABI_FUNC_VIS void *
__cxa_allocate_exception(size_t thrown_size) throw();
extern _LIBCXXABI_FUNC_VIS void
__cxa_free_exception(void *thrown_exception) throw();
+// This function is an LLVM extension, which mirrors the same extension in libsupc++ and libcxxrt
+extern _LIBCXXABI_FUNC_VIS __cxa_exception*
+__cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw();
// 2.4.3 Throwing the Exception Object
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
diff --git a/libcxxabi/lib/exceptions.exp b/libcxxabi/lib/exceptions.exp
index c3780d2..9dcfbdb 100644
--- a/libcxxabi/lib/exceptions.exp
+++ b/libcxxabi/lib/exceptions.exp
@@ -7,5 +7,6 @@ ___cxa_end_catch
___cxa_free_dependent_exception
___cxa_free_exception
___cxa_get_exception_ptr
+___cxa_init_primary_exception
___cxa_rethrow
___cxa_throw
diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp
index f723ece..65e9f45 100644
--- a/libcxxabi/src/cxa_exception.cpp
+++ b/libcxxabi/src/cxa_exception.cpp
@@ -206,6 +206,19 @@ void __cxa_free_exception(void *thrown_object) throw() {
__aligned_free_with_fallback((void *)raw_buffer);
}
+__cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo,
+ void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() {
+ __cxa_exception* exception_header = cxa_exception_from_thrown_object(object);
+ exception_header->referenceCount = 0;
+ exception_header->unexpectedHandler = std::get_unexpected();
+ exception_header->terminateHandler = std::get_terminate();
+ exception_header->exceptionType = tinfo;
+ exception_header->exceptionDestructor = dest;
+ setOurExceptionClass(&exception_header->unwindHeader);
+ exception_header->unwindHeader.exception_cleanup = exception_cleanup_func;
+
+ return exception_header;
+}
// This function shall allocate a __cxa_dependent_exception and
// return a pointer to it. (Really to the object, not past its' end).
@@ -260,22 +273,15 @@ __cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_F
#else
__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
#endif
- __cxa_eh_globals *globals = __cxa_get_globals();
- __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
-
- exception_header->unexpectedHandler = std::get_unexpected();
- exception_header->terminateHandler = std::get_terminate();
- exception_header->exceptionType = tinfo;
- exception_header->exceptionDestructor = dest;
- setOurExceptionClass(&exception_header->unwindHeader);
- exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety.
- globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
+ __cxa_eh_globals* globals = __cxa_get_globals();
+ globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
- exception_header->unwindHeader.exception_cleanup = exception_cleanup_func;
+ __cxa_exception* exception_header = __cxa_init_primary_exception(thrown_object, tinfo, dest);
+ exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety.
#if __has_feature(address_sanitizer)
- // Inform the ASan runtime that now might be a good time to clean stuff up.
- __asan_handle_no_return();
+ // Inform the ASan runtime that now might be a good time to clean stuff up.
+ __asan_handle_no_return();
#endif
#ifdef __USING_SJLJ_EXCEPTIONS__