-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[libc++] Inline fast path forexception_ptr copy constructor & destructor
#165909
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d332adc
29751a3
6631aba
7684774
da474b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -30,6 +30,28 @@ _LIBCPP_PUSH_MACROS | |||||||||
|
|
||||||||||
| #ifndef _LIBCPP_ABI_MICROSOFT | ||||||||||
|
|
||||||||||
| // Previously, parts of exception_ptr were defined out-of-line, which prevented | ||||||||||
| // useful compiler optimizations. Changing the out-of-line definitions to inline | ||||||||||
| // definitions is an ABI break, however. To prevent this, we have to make sure | ||||||||||
| // the symbols remain available in the libc++ library, in addition to being | ||||||||||
| // defined inline here in this header. | ||||||||||
| // To this end, we use _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE macro: | ||||||||||
| // The macro is defined as empty for src/exception.cpp, forcing the definitions of | ||||||||||
| // the functions to be emitted and included in the library. When users of libc++ | ||||||||||
| // compile their code, the __gnu_inline__ attribute will suppress generation of | ||||||||||
| // these functions while making their definitions available for inlining. | ||||||||||
| # ifdef _LIBCPP_EMIT_CODE_FOR_EXCEPTION_PTR | ||||||||||
| # define _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE _LIBCPP_EXPORTED_FROM_ABI | ||||||||||
| # else | ||||||||||
| # if !__has_cpp_attribute(__gnu__::__gnu_inline__) | ||||||||||
| # error "GNU inline attribute is not supported" | ||||||||||
| # endif | ||||||||||
| # define _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE [[__gnu__::__gnu_inline__]] inline | ||||||||||
| # endif | ||||||||||
|
|
||||||||||
| _LIBCPP_DIAGNOSTIC_PUSH | ||||||||||
| _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wgnu-inline-cpp-without-extern") | ||||||||||
|
|
||||||||||
| # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION | ||||||||||
|
|
||||||||||
| namespace __cxxabiv1 { | ||||||||||
|
|
@@ -67,6 +89,17 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _ | |||||||||
| class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { | ||||||||||
| void* __ptr_; | ||||||||||
|
|
||||||||||
| static void __do_increment_refcount(void* __ptr) _NOEXCEPT; | ||||||||||
| static void __do_decrement_refcount(void* __ptr) _NOEXCEPT; | ||||||||||
|
Comment on lines
+92
to
+93
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| _LIBCPP_HIDE_FROM_ABI static void __increment_refcount(void* __ptr) _NOEXCEPT { | ||||||||||
| if (__ptr) | ||||||||||
| __do_increment_refcount(__ptr); | ||||||||||
| } | ||||||||||
| _LIBCPP_HIDE_FROM_ABI static void __decrement_refcount(void* __ptr) _NOEXCEPT { | ||||||||||
| if (__ptr) | ||||||||||
| __do_decrement_refcount(__ptr); | ||||||||||
| } | ||||||||||
|
Comment on lines
+94
to
+101
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like these names are rather poor. It'd either inline these relatively simple functions or rename them so it's obvious they might inc/decrement the refcount. |
||||||||||
|
|
||||||||||
| static exception_ptr __from_native_exception_pointer(void*) _NOEXCEPT; | ||||||||||
|
|
||||||||||
| template <class _Ep> | ||||||||||
|
|
@@ -81,17 +114,18 @@ 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_() {} | ||||||||||
|
|
||||||||||
| exception_ptr(const exception_ptr&) _NOEXCEPT; | ||||||||||
| _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr(const exception_ptr&) _NOEXCEPT; | ||||||||||
| _LIBCPP_HIDE_FROM_ABI exception_ptr(exception_ptr&& __other) _NOEXCEPT : __ptr_(__other.__ptr_) { | ||||||||||
| __other.__ptr_ = nullptr; | ||||||||||
| } | ||||||||||
| exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; | ||||||||||
| _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE 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); | ||||||||||
| __decrement_refcount(__ptr_); | ||||||||||
| __ptr_ = __other.__ptr_; | ||||||||||
| __other.__ptr_ = nullptr; | ||||||||||
| return *this; | ||||||||||
| } | ||||||||||
| ~exception_ptr() _NOEXCEPT; | ||||||||||
| _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE ~exception_ptr() _NOEXCEPT; | ||||||||||
|
|
||||||||||
| _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; } | ||||||||||
|
|
||||||||||
|
|
@@ -109,6 +143,25 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { | |||||||||
| friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| // Must be defined outside the class definition due to _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE | ||||||||||
| _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr::exception_ptr(const exception_ptr& __other) _NOEXCEPT | ||||||||||
| : __ptr_(__other.__ptr_) { | ||||||||||
| __increment_refcount(__ptr_); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Must be defined outside the class definition due to _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE | ||||||||||
| _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE 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; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Must be defined outside the class definition due to _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE | ||||||||||
| _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr::~exception_ptr() _NOEXCEPT { __decrement_refcount(__ptr_); } | ||||||||||
|
|
||||||||||
| inline _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT { | ||||||||||
| std::swap(__x.__ptr_, __y.__ptr_); | ||||||||||
| } | ||||||||||
|
|
@@ -178,6 +231,8 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT { | |||||||||
| } | ||||||||||
| # endif // _LIBCPP_HAS_EXCEPTIONS | ||||||||||
|
|
||||||||||
| _LIBCPP_DIAGNOSTIC_POP | ||||||||||
|
|
||||||||||
| #else // _LIBCPP_ABI_MICROSOFT | ||||||||||
|
|
||||||||||
| class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can drop this entire thing and instead just have an
#ifdef _LIBCPP_BUILDING_LIBRARY, in which case we provide the old declarations, and otherwise provide inline functions. The inline functions get different mangling anyways, so I don't think there is much of a problem. I have actually no idea why I suggested this convoluted workaround before.