Index: libcxx/include/__config =================================================================== --- libcxx/include/__config +++ libcxx/include/__config @@ -114,6 +114,12 @@ # define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON // Remove vector base class # define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON +# if !defined(__GLIBCXX__) +// Add a move constructor and move assignment operator, and inline parts of the +// definitions of the constructors, assignment operators, and destructor to +// enable optimizing away everything if the exception_ptr is empty. +# define _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR +# endif #elif _LIBCPP_ABI_VERSION == 1 # if !defined(_LIBCPP_OBJECT_FORMAT_COFF) // Enable compiling copies of now inline methods into the dylib to support Index: libcxx/include/exception =================================================================== --- libcxx/include/exception +++ libcxx/include/exception @@ -143,13 +143,59 @@ class _LIBCPP_TYPE_VIS exception_ptr { void* __ptr_; + +#ifdef _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR + void __incr_refcount() _NOEXCEPT; + void __decr_refcount() _NOEXCEPT; +#endif // _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR + public: _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} +#ifndef _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR exception_ptr(const exception_ptr&) _NOEXCEPT; exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; ~exception_ptr() _NOEXCEPT; +#else + exception_ptr(const exception_ptr& __rhs) _NOEXCEPT : __ptr_(__rhs.__ptr_) { + if (__rhs.__ptr_ != nullptr) + __incr_refcount(); + } + exception_ptr(exception_ptr&& __rhs) _NOEXCEPT : __ptr_(__rhs.__ptr_) { + __rhs.__ptr_ = nullptr; + } + + exception_ptr& operator=(const exception_ptr& __rhs) _NOEXCEPT { + if (__ptr_ != __rhs.__ptr_) { + if (__ptr_ != nullptr) + __decr_refcount(); + __ptr_ = __rhs.__ptr_; + if (__ptr_ != nullptr) + __incr_refcount(); + } + return *this; + } + exception_ptr& operator=(exception_ptr&& __rhs) _NOEXCEPT { + if (__ptr_ != nullptr) + __decr_refcount(); + __ptr_ = __rhs.__ptr_; + __rhs.__ptr_ = nullptr; + return *this; + } + + ~exception_ptr() _NOEXCEPT { + if (__ptr_ != nullptr) + __decr_refcount(); + } + + _LIBCPP_INLINE_VISIBILITY + void swap(exception_ptr& __rhs) _NOEXCEPT { + void *__tmp = __ptr_; + __ptr_ = __rhs.__ptr_; + __rhs.__ptr_ = __tmp; + } +#endif // _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT {return __ptr_ != nullptr;} @@ -166,6 +212,12 @@ friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); }; +#ifdef _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR +inline _LIBCPP_INLINE_VISIBILITY void +swap(exception_ptr& __lhs, exception_ptr& __rhs) _NOEXCEPT +{ __lhs.swap(__rhs); } +#endif // _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR + template _LIBCPP_INLINE_VISIBILITY exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT Index: libcxx/src/support/runtime/exception_pointer_cxxabi.ipp =================================================================== --- libcxx/src/support/runtime/exception_pointer_cxxabi.ipp +++ libcxx/src/support/runtime/exception_pointer_cxxabi.ipp @@ -13,16 +13,25 @@ namespace std { +#ifndef _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR exception_ptr::~exception_ptr() noexcept { +#else +void exception_ptr::__decr_refcount() noexcept { +#endif // _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR __cxa_decrement_exception_refcount(__ptr_); } +#ifndef _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) +#else +void exception_ptr::__incr_refcount() noexcept +#endif // _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR { __cxa_increment_exception_refcount(__ptr_); } +#ifndef _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept { if (__ptr_ != other.__ptr_) @@ -33,6 +42,7 @@ } return *this; } +#endif // _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR nested_exception::nested_exception() noexcept : __ptr_(current_exception()) Index: libcxx/src/support/runtime/exception_pointer_unimplemented.ipp =================================================================== --- libcxx/src/support/runtime/exception_pointer_unimplemented.ipp +++ libcxx/src/support/runtime/exception_pointer_unimplemented.ipp @@ -12,27 +12,37 @@ namespace std { +#ifndef _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR exception_ptr::~exception_ptr() noexcept +#else +void exception_ptr::__decr_refcount() noexcept +#endif // _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR { # warning exception_ptr not yet implemented fprintf(stderr, "exception_ptr not yet implemented\n"); ::abort(); } +#ifndef _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) +#else +void exception_ptr::__incr_refcount() noexcept +#endif // _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR { # warning exception_ptr not yet implemented fprintf(stderr, "exception_ptr not yet implemented\n"); ::abort(); } +#ifndef _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept { # warning exception_ptr not yet implemented fprintf(stderr, "exception_ptr not yet implemented\n"); ::abort(); } +#endif // _LIBCPP_ABI_OPTIMIZED_EXCEPTION_PTR nested_exception::nested_exception() noexcept : __ptr_(current_exception())