diff options
author | itrofimow <i.trofimow@yandex.ru> | 2024-01-22 19:12:41 +0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-22 10:12:41 -0500 |
commit | 51e91b64d0deb6a743861c2a0fba84865250036e (patch) | |
tree | 1863c3766d4d40d4f4aad9528efdfbfbe0d867c6 /libcxxabi | |
parent | 6ba62f4f251763745d39194ecd33ebaf7a739059 (diff) | |
download | llvm-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.h | 6 | ||||
-rw-r--r-- | libcxxabi/lib/exceptions.exp | 1 | ||||
-rw-r--r-- | libcxxabi/src/cxa_exception.cpp | 32 |
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__ |