diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index a6a0ac8670fb5..5734f33e13498 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -82,6 +82,9 @@ Improvements and New Features iterators, resulting in a performance improvement for ``std::deque`` and ``std::join_view>>`` iterators. +- ``std::exception_ptr`` was optimized, allowing the compiler to generate better code especially for empty + ``std::exception_ptr`` values. + Deprecations and Removals ------------------------- diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h index 5433df872fa39..3bbe20b517e97 100644 --- a/libcxx/include/__configuration/availability.h +++ b/libcxx/include/__configuration/availability.h @@ -276,6 +276,12 @@ #define _LIBCPP_AVAILABILITY_HAS_PMR _LIBCPP_INTRODUCED_IN_LLVM_16 #define _LIBCPP_AVAILABILITY_PMR +// This macro controls the availability of exception_ptr::__{inc,dec}rement_refcount +// which are used in the inline implementations of exception_ptr's move constructor, +// assignment operator, and destructor (see libcxx/include/__exception/exception_ptr.h). +#define _LIBCPP_AVAILABILITY_HAS_INCREMENT_DECREMENT_REFCOUNT_EXCEPTION_PTR _LIBCPP_INTRODUCED_IN_LLVM_21 +// No attribute, since we've have a fallback implementation in the headers + // These macros controls the availability of __cxa_init_primary_exception // in the built library, which std::make_exception_ptr might use // (see libcxx/include/__exception/exception_ptr.h). diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index aef036a2c9586..68b3fa47c5314 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -17,8 +17,6 @@ #include <__memory/construct_at.h> #include <__type_traits/decay.h> #include <__type_traits/is_pointer.h> -#include <__utility/move.h> -#include <__utility/swap.h> #include <__verbose_abort> #include @@ -26,9 +24,6 @@ # pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - #ifndef _LIBCPP_ABI_MICROSOFT # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION @@ -63,11 +58,12 @@ _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD #ifndef _LIBCPP_ABI_MICROSOFT -inline _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT; - class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { void* __ptr_; + static void __increment_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void*) _NOEXCEPT; + static void __decrement_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void*) _NOEXCEPT; + static exception_ptr __from_native_exception_pointer(void*) _NOEXCEPT; template @@ -82,17 +78,42 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} +// These symbols are still exported from the library to prevent ABI breakage. +# if defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_INCREMENT_DECREMENT_REFCOUNT_EXCEPTION_PTR exception_ptr(const exception_ptr&) _NOEXCEPT; + exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; + ~exception_ptr() _NOEXCEPT; +# else // defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_INCREMENT_DECREMENT_REFCOUNT_EXCEPTION_PTR + _LIBCPP_HIDE_FROM_ABI exception_ptr(const exception_ptr& __other) _NOEXCEPT : __ptr_(__other.__ptr_) { + if (__ptr_) + __increment_refcount(__ptr_); + } + _LIBCPP_HIDE_FROM_ABI exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT { + if (__ptr_ == __other.__ptr_) + return *this; + if (__other.__ptr_) + __increment_refcount(__other.__ptr_); + if (__ptr_) + __decrement_refcount(__ptr_); + __ptr_ = __other.__ptr_; + return *this; + } + _LIBCPP_HIDE_FROM_ABI ~exception_ptr() _NOEXCEPT { + if (__ptr_) + __decrement_refcount(__ptr_); + } +# endif // defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_INCREMENT_DECREMENT_REFCOUNT_EXCEPTION_PTR + _LIBCPP_HIDE_FROM_ABI exception_ptr(exception_ptr&& __other) _NOEXCEPT : __ptr_(__other.__ptr_) { __other.__ptr_ = nullptr; } - exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI exception_ptr& operator=(exception_ptr&& __other) _NOEXCEPT { - exception_ptr __tmp(std::move(__other)); - std::swap(__tmp, *this); + if (__ptr_) + __decrement_refcount(__ptr_); + __ptr_ = __other.__ptr_; + __other.__ptr_ = nullptr; return *this; } - ~exception_ptr() _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; } @@ -104,16 +125,10 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { return !(__x == __y); } - friend _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT; - friend _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); }; -inline _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT { - std::swap(__x.__ptr_, __y.__ptr_); -} - # if _LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION template @@ -223,6 +238,4 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { #endif // _LIBCPP_ABI_MICROSOFT _LIBCPP_END_UNVERSIONED_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index 3a1d8950c2db0..45664ec108b8a 100644 --- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -858,6 +858,8 @@ {'is_defined': True, 'name': '__ZNSt13bad_exceptionD0Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD1Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr20__decrement_refcountEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist index 313de84df20e8..7cd5befa21322 100644 --- a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -494,6 +494,8 @@ {'is_defined': True, 'name': '_ZNSt13bad_exceptionD0Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13bad_exceptionD1Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13bad_exceptionD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__decrement_refcountEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index 99cde72885cf2..176a2aae773de 100644 --- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -250,6 +250,8 @@ {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr20__decrement_refcountEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index 577d6cf759a77..14362b11bb4f4 100644 --- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -250,6 +250,8 @@ {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr20__decrement_refcountEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index 5173a1a76b81a..f3f1daff162da 100644 --- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -857,6 +857,8 @@ {'is_defined': True, 'name': '__ZNSt13bad_exceptionD0Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD1Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr20__decrement_refcountEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist index 1be7d8a2ac20b..2dc2f470dd6f5 100644 --- a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -494,6 +494,8 @@ {'is_defined': True, 'name': '_ZNSt13bad_exceptionD0Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13bad_exceptionD1Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13bad_exceptionD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__decrement_refcountEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist index 40ae625d3bd69..5c1b4069ab782 100644 --- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -525,6 +525,8 @@ {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__decrement_refcountEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist index 90166073b135f..f58ec13344af2 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -523,6 +523,8 @@ {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__decrement_refcountEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist index 5855c17cf11ed..70d31c5b9f70c 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist @@ -494,6 +494,8 @@ {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__decrement_refcountEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} diff --git a/libcxx/modules/std/exception.inc b/libcxx/modules/std/exception.inc index 3dbc0112c15a0..02b0f80190e5b 100644 --- a/libcxx/modules/std/exception.inc +++ b/libcxx/modules/std/exception.inc @@ -18,7 +18,6 @@ export namespace std { using std::rethrow_exception; using std::rethrow_if_nested; using std::set_terminate; - using std::swap; using std::terminate; using std::terminate_handler; using std::throw_with_nested; diff --git a/libcxx/src/exception.cpp b/libcxx/src/exception.cpp index ac6324cd9fe35..6f24e7dd467b3 100644 --- a/libcxx/src/exception.cpp +++ b/libcxx/src/exception.cpp @@ -25,12 +25,15 @@ using namespace __cxxabiv1; #elif defined(_LIBCPPABI_VERSION) # include "support/runtime/exception_libcxxabi.ipp" # include "support/runtime/exception_pointer_cxxabi.ipp" +# include "support/runtime/exception_pointer_refcounted.ipp" #elif defined(LIBCXXRT) # include "support/runtime/exception_libcxxrt.ipp" # include "support/runtime/exception_pointer_cxxabi.ipp" +# include "support/runtime/exception_pointer_refcounted.ipp" #elif defined(__GLIBCXX__) # include "support/runtime/exception_glibcxx.ipp" # include "support/runtime/exception_pointer_glibcxx.ipp" +# include "support/runtime/exception_pointer_refcounted.ipp" #else # include "include/atomic_support.h" # include "support/runtime/exception_fallback.ipp" diff --git a/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp b/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp index 8f5c2060bb06c..1464082c8a098 100644 --- a/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp +++ b/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp @@ -13,27 +13,12 @@ namespace std { -exception_ptr::~exception_ptr() noexcept { __cxa_decrement_exception_refcount(__ptr_); } - -exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) { - __cxa_increment_exception_refcount(__ptr_); -} - -exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept { - if (__ptr_ != other.__ptr_) { - __cxa_increment_exception_refcount(other.__ptr_); - __cxa_decrement_exception_refcount(__ptr_); - __ptr_ = other.__ptr_; - } - return *this; +void exception_ptr::__increment_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept { + __cxa_increment_exception_refcount(__ptr); } -exception_ptr exception_ptr::__from_native_exception_pointer(void* __e) noexcept { - exception_ptr ptr; - ptr.__ptr_ = __e; - __cxa_increment_exception_refcount(ptr.__ptr_); - - return ptr; +void exception_ptr::__decrement_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept { + __cxa_decrement_exception_refcount(__ptr); } nested_exception::nested_exception() noexcept : __ptr_(current_exception()) {} diff --git a/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp b/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp index 174b44ce0e6f7..abf1f66b146ed 100644 --- a/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp +++ b/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp @@ -11,10 +11,9 @@ // it uses to implement std::exception_ptr (which it declares as an alias of // std::__exception_ptr::exception_ptr) is not directly exported to clients. So // we have little choice but to hijack std::__exception_ptr::exception_ptr's -// (which fortunately has the same layout as our std::exception_ptr) copy -// constructor, assignment operator and destructor (which are part of its -// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr) -// function. +// _M_addref and _M_release and its rethrow_exception function. Fortunately, +// glibcxx's exception_ptr has the same layout as our exception_ptr and we can +// reinterpret_cast between the two. namespace std { @@ -23,34 +22,20 @@ namespace __exception_ptr { struct exception_ptr { void* __ptr_; - explicit exception_ptr(void*) noexcept; - exception_ptr(const exception_ptr&) noexcept; - exception_ptr& operator=(const exception_ptr&) noexcept; - ~exception_ptr() noexcept; + void _M_addref() noexcept; + void _M_release() noexcept; }; } // namespace __exception_ptr [[noreturn]] void rethrow_exception(__exception_ptr::exception_ptr); -exception_ptr::~exception_ptr() noexcept { reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); } - -exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) { - new (reinterpret_cast(this)) - __exception_ptr::exception_ptr(reinterpret_cast(other)); -} - -exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept { - *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = - reinterpret_cast(other); - return *this; +void exception_ptr::__increment_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept { + reinterpret_cast<__exception_ptr::exception_ptr*>(this)->_M_addref(); } -exception_ptr exception_ptr::__from_native_exception_pointer(void* __e) noexcept { - exception_ptr ptr{}; - new (reinterpret_cast(&ptr)) __exception_ptr::exception_ptr(__e); - - return ptr; +void exception_ptr::__decrement_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept { + reinterpret_cast<__exception_ptr::exception_ptr*>(this)->_M_release(); } nested_exception::nested_exception() noexcept : __ptr_(current_exception()) {} diff --git a/libcxx/src/support/runtime/exception_pointer_refcounted.ipp b/libcxx/src/support/runtime/exception_pointer_refcounted.ipp new file mode 100644 index 0000000000000..0b71e52cb2423 --- /dev/null +++ b/libcxx/src/support/runtime/exception_pointer_refcounted.ipp @@ -0,0 +1,37 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Provides the common functionality shared between cxxabi and glibcxx. + +namespace std { + +exception_ptr exception_ptr::__from_native_exception_pointer(void* __e) noexcept { + exception_ptr ptr; + ptr.__ptr_ = __e; + __increment_refcount(ptr.__ptr_); + + return ptr; +} + +exception_ptr::~exception_ptr() noexcept { __decrement_refcount(__ptr_); } + +exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) { + __increment_refcount(__ptr_); +} + +exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept { + if (__ptr_ != other.__ptr_) { + __increment_refcount(other.__ptr_); + __decrement_refcount(__ptr_); + __ptr_ = other.__ptr_; + } + return *this; +} + +} // namespace std diff --git a/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp b/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp index 05a71ce34e5ac..56d425e7b7c4d 100644 --- a/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp +++ b/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp @@ -11,23 +11,13 @@ namespace std { -exception_ptr::~exception_ptr() noexcept { #warning exception_ptr not yet implemented - __libcpp_verbose_abort("exception_ptr not yet implemented\n"); -} -exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) { -#warning exception_ptr not yet implemented +void exception_ptr::__increment_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept { __libcpp_verbose_abort("exception_ptr not yet implemented\n"); } -exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept { -#warning exception_ptr not yet implemented - __libcpp_verbose_abort("exception_ptr not yet implemented\n"); -} - -exception_ptr exception_ptr::__from_native_exception_pointer(void *__e) noexcept { -#warning exception_ptr not yet implemented +void exception_ptr::__decrement_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept { __libcpp_verbose_abort("exception_ptr not yet implemented\n"); } @@ -40,7 +30,6 @@ nested_exception::~nested_exception() noexcept {} #endif [[noreturn]] void nested_exception::rethrow_nested() const { -#warning exception_ptr not yet implemented __libcpp_verbose_abort("exception_ptr not yet implemented\n"); #if 0 if (__ptr_ == nullptr) @@ -50,12 +39,10 @@ nested_exception::~nested_exception() noexcept {} } exception_ptr current_exception() noexcept { -#warning exception_ptr not yet implemented __libcpp_verbose_abort("exception_ptr not yet implemented\n"); } [[noreturn]] void rethrow_exception(exception_ptr p) { -#warning exception_ptr not yet implemented __libcpp_verbose_abort("exception_ptr not yet implemented\n"); }