You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit optimizes the performance for `std::exception_ptr`
for an empty exception objects.
To do so, we use 3 high-level approaches:
1. Moving the implementation from the libc++ library into the libc++
headers, thereby allowing the compiler to inline the function bodies.
2. Adding fast paths to the (now inlineable) bodies, checking for the
empty case.
3. Adding move constuctor, assignment and `swap`
Those optimizations were implemented for the libc++abi, libsupc++ and
libstdc++ ABIs.
Fixes #XXX
Performance
-----------
With this change, the compiler can now completely constant-fold
https://godbolt.org/z/NaNKe5. Also in cases where the compiler cannot
statically prove that exception_ptr is empty, it can at least generate a
fast-path check if the exception_ptr is empty, without calling into the
library.
ABI compatibility
-----------------
We use a new visibility macro `_LIBCPP_EXPORTED_FROM_ABI_INLINEABLE` to
ensure that the functions which are now declared in the header are still
exported by the library. See the description in `VisibilityMacros.rst`
for details. This approach was originally proposed by Nikolas Klauser
in https://reviews.llvm.org/D122536
Moving implementations to the header
------------------------------------
To move the implementation to the header, we must know the selected
LIBCXX_CXX_ABI also in the headers. For that purpose, the LIBCXX_CXX_ABI
configuration is now exposed via `__config_site`.
While the Microsoft ABI and the "unimplemented" APIs do not benefit
from this optimizations, I also moved their implementation to the
headers for more uniformity. Mid-term, we probably have to expose all
implementations in the header, anyway, because P3068R6 mandates all
methods of `exception_ptr` to be constexpr.
Unifying libc++abi, libsupc++ and `none`
-----------------------------------------------
Both libc++abi and libsupc++ are reference-counted. The primary
difference is the function called for ref-counting:
* libc++api uses `__cxa_{in,de}crement_exception_refcount`
* libsupc++ uses `__exception_ptr::_M_{addref,release}`
This commit factors out the common reference-counting logic into a
shared header.
Our libsupc++ implementation so far did not take advantage of
`_M_addref`/`_M_release`. For the performance benefits of this PR it was
necessary to start using them.
The same reference-counted approach is also reused for the
`none`/`unimplemented` implementation. This has the side effect, that
users can now use empty `exception_ptr`s even in the `none` ABI. The
abort is only triggered for non-empty `exception_ptr`s. Given this
simplifies the code, I think change is acceptable.
Unifying nested_exception
-------------------------
The implementation for `nested_exception` was effectively identical
across all ABIs. For most ABIs, the source code was literally identical.
There were only two deviations:
* For libsupc++ or libstdc++, we did not use define the
`~nested_exception` destructor.
* The abort in `nested_exception::rethrow_nested` was unnecessary as the
same abort is also present in the `rethrow_exception` implementation.
As such, we were able to simply remove that special casing.
The implementation is now unified directly in the `__nested_exception.h`
header.
Standard conformance
--------------------
The available constructors, operators and methods of `exception_ptr` is
not specified by the standard. As such, adding the move constructor and
the assignment operator are standard conformant. libstdc++ made the same
decision and also provides those headers.
0 commit comments