This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [PATCHv2] do not throw in std::make_exception_ptr
- From: Gleb Natapov <gleb at scylladb dot com>
- To: gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Cc: Jonathan Wakely <jwakely at redhat dot com>
- Date: Sun, 21 Aug 2016 15:20:30 +0300
- Subject: Re: [PATCHv2] do not throw in std::make_exception_ptr
- Authentication-results: sourceware.org; auth=none
- References: <20160805044923.GX17903@scylladb.com>
Jonathan,
Is this version OK with you?
On Fri, Aug 05, 2016 at 07:49:24AM +0300, Gleb Natapov wrote:
> Instead of throwing an exception allocate its memory and initialize it
> explicitly. Makes std::make_exception_ptr more efficient since no stack
> unwinding is needed.
>
> v1->v2:
> - fix indentation
> - drop static from __dest_thunk
> - use static_cast instead of reinterpret_cast
>
> * libsupc++/exception (std::exception): Move...
> * libsupc++/exception.h: ...here; New.
> * libsupc++/cxxabi.h (__cxa_allocate_exception): Move...
> * libsupc++/cxxabi_init_exception.h: ...here and add
> __cxa_init_primary_exception; New.
> * config/abi/pre/gnu-versioned-namespace.ver: add
> __cxa_init_primary_exception and std::exception_ptr(void*)
> * config/abi/pre/gnu.ver (CXXABI_1.3.11) : add
> __cxa_init_primary_exception and std::exception_ptr(void*)
> (CXXABI_1.3.11): New.
> * include/Makefile.am: add exception.h and cxxabi_init_exception.h
> * include/Makefile.in: Likewise.
> * libsupc++/Makefile.am: add exception.h and cxxabi_init_exception.h
> * libsupc++/Makefile.in: Likewise.
> * libsupc++/eh_throw.cc(__cxa_throw): add __cxa_init_primary_exception
> and use it
> * libsupc++/exception_ptr.h(std::make_exception_ptr): use
> __cxa_allocate_exception and __cxa_init_primary_exception to create
> exception pointer
> * libsupc++/typeinfo: include bits/exception.h instead of exception
>
>
> diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
> index 8304dee..65866a3 100644
> --- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
> +++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
> @@ -179,6 +179,7 @@ CXXABI_2.0 {
> __cxa_free_exception;
> __cxa_free_dependent_exception;
> __cxa_get_exception_ptr;
> + __cxa_init_primary_exception;
> __cxa_get_globals;
> __cxa_get_globals_fast;
> __cxa_guard_abort;
> @@ -205,6 +206,7 @@ CXXABI_2.0 {
> # std::exception_ptr
> _ZNSt15__exception_ptr13exception_ptrC1Ev;
> _ZNSt15__exception_ptr13exception_ptrC2Ev;
> + _ZNSt15__exception_ptr13exception_ptrC1EPv;
> _ZNSt15__exception_ptr13exception_ptrC1ERKS0_;
> _ZNSt15__exception_ptr13exception_ptrC2ERKS0_;
> _ZNSt15__exception_ptr13exception_ptrC1EMS0_FvvE;
> diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
> index b7f54e2..f51c6f9 100644
> --- a/libstdc++-v3/config/abi/pre/gnu.ver
> +++ b/libstdc++-v3/config/abi/pre/gnu.ver
> @@ -2164,6 +2164,13 @@ CXXABI_1.3.10 {
>
> } CXXABI_1.3.9;
>
> +CXXABI_1.3.11 {
> +
> + __cxa_init_primary_exception;
> + _ZNSt15__exception_ptr13exception_ptrC1EPv;
> +
> +} CXXABI_1.3.10;
> +
> # Symbols in the support library (libsupc++) supporting transactional memory.
> CXXABI_TM_1 {
>
> diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
> index e2c4f63..b91453f 100644
> --- a/libstdc++-v3/include/Makefile.am
> +++ b/libstdc++-v3/include/Makefile.am
> @@ -205,6 +205,8 @@ bits_sup_headers = \
> ${bits_sup_srcdir}/cxxabi_forced.h \
> ${bits_sup_srcdir}/exception_defines.h \
> ${bits_sup_srcdir}/exception_ptr.h \
> + ${bits_sup_srcdir}/exception.h \
> + ${bits_sup_srcdir}/cxxabi_init_exception.h \
> ${bits_sup_srcdir}/hash_bytes.h \
> ${bits_sup_srcdir}/nested_exception.h
>
> diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
> index 882ff14..1259ad4 100644
> --- a/libstdc++-v3/include/Makefile.in
> +++ b/libstdc++-v3/include/Makefile.in
> @@ -495,6 +495,8 @@ bits_sup_headers = \
> ${bits_sup_srcdir}/cxxabi_forced.h \
> ${bits_sup_srcdir}/exception_defines.h \
> ${bits_sup_srcdir}/exception_ptr.h \
> + ${bits_sup_srcdir}/exception.h \
> + ${bits_sup_srcdir}/cxxabi_init_exception.h \
> ${bits_sup_srcdir}/hash_bytes.h \
> ${bits_sup_srcdir}/nested_exception.h
>
> diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am
> index b45b5ae..ba4eac1 100644
> --- a/libstdc++-v3/libsupc++/Makefile.am
> +++ b/libstdc++-v3/libsupc++/Makefile.am
> @@ -35,7 +35,7 @@ std_HEADERS = \
>
> bits_HEADERS = \
> atomic_lockfree_defines.h cxxabi_forced.h \
> - exception_defines.h exception_ptr.h hash_bytes.h nested_exception.h
> + exception_defines.h exception_ptr.h hash_bytes.h nested_exception.h exception.h cxxabi_init_exception.h
>
> headers = $(std_HEADERS) $(bits_HEADERS)
>
> diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in
> index f3648ac..3fb9d16 100644
> --- a/libstdc++-v3/libsupc++/Makefile.in
> +++ b/libstdc++-v3/libsupc++/Makefile.in
> @@ -395,7 +395,7 @@ std_HEADERS = \
>
> bits_HEADERS = \
> atomic_lockfree_defines.h cxxabi_forced.h \
> - exception_defines.h exception_ptr.h hash_bytes.h nested_exception.h
> + exception_defines.h exception_ptr.h hash_bytes.h nested_exception.h exception.h cxxabi_init_exception.h
>
> headers = $(std_HEADERS) $(bits_HEADERS)
> @GLIBCXX_HOSTED_TRUE@c_sources = \
> diff --git a/libstdc++-v3/libsupc++/cxxabi.h b/libstdc++-v3/libsupc++/cxxabi.h
> index 11ff9e5..f4b8f75 100644
> --- a/libstdc++-v3/libsupc++/cxxabi.h
> +++ b/libstdc++-v3/libsupc++/cxxabi.h
> @@ -49,10 +49,7 @@
> #include <bits/c++config.h>
> #include <bits/cxxabi_tweaks.h>
> #include <bits/cxxabi_forced.h>
> -
> -#ifndef _GLIBCXX_CDTOR_CALLABI
> -#define _GLIBCXX_CDTOR_CALLABI
> -#endif
> +#include <bits/cxxabi_init_exception.h>
>
> #ifdef __cplusplus
> namespace __cxxabiv1
> @@ -608,10 +605,6 @@ namespace __cxxabiv1
> __cxa_eh_globals*
> __cxa_get_globals_fast() _GLIBCXX_NOTHROW __attribute__ ((__const__));
>
> - // Allocate memory for the primary exception plus the thrown object.
> - void*
> - __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW;
> -
> // Free the space allocated for the primary exception.
> void
> __cxa_free_exception(void*) _GLIBCXX_NOTHROW;
> diff --git a/libstdc++-v3/libsupc++/cxxabi_init_exception.h b/libstdc++-v3/libsupc++/cxxabi_init_exception.h
> new file mode 100644
> index 0000000..9af7625
> --- /dev/null
> +++ b/libstdc++-v3/libsupc++/cxxabi_init_exception.h
> @@ -0,0 +1,77 @@
> +// ABI Support -*- C++ -*-
> +
> +// Copyright (C) 2016 Free Software Foundation, Inc.
> +//
> +// This file is part of GCC.
> +//
> +// GCC is free software; you can redistribute it and/or modify
> +// it under the terms of the GNU General Public License as published by
> +// the Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +//
> +// GCC is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +// GNU General Public License for more details.
> +//
> +// Under Section 7 of GPL version 3, you are granted additional
> +// permissions described in the GCC Runtime Library Exception, version
> +// 3.1, as published by the Free Software Foundation.
> +
> +// You should have received a copy of the GNU General Public License and
> +// a copy of the GCC Runtime Library Exception along with this program;
> +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
> +// <http://www.gnu.org/licenses/>.
> +
> +/** @file bits/cxxabi_init_exception.h
> + * This is an internal header file, included by other library headers.
> + * Do not attempt to use it directly.
> + */
> +
> +#ifndef _CXXABI_INIT_EXCEPTION_H
> +#define _CXXABI_INIT_EXCEPTION_H 1
> +
> +#pragma GCC system_header
> +
> +#pragma GCC visibility push(default)
> +
> +#include <stddef.h>
> +#include <bits/c++config.h>
> +
> +#ifndef _GLIBCXX_CDTOR_CALLABI
> +#define _GLIBCXX_CDTOR_CALLABI
> +#define _GLIBCXX_HAVE_CDTOR_CALLABI 0
> +#else
> +#define _GLIBCXX_HAVE_CDTOR_CALLABI 1
> +#endif
> +
> +#ifdef __cplusplus
> +
> +namespace std
> +{
> + class type_info;
> +}
> +
> +namespace __cxxabiv1
> +{
> + struct __cxa_refcounted_exception;
> +
> + extern "C"
> + {
> + // Allocate memory for the primary exception plus the thrown object.
> + void*
> + __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW;
> +
> + // Initialize exception (this is a GNU extension)
> + __cxa_refcounted_exception*
> + __cxa_init_primary_exception(void *object, std::type_info *tinfo,
> + void (_GLIBCXX_CDTOR_CALLABI *dest) (void *)) _GLIBCXX_NOTHROW;
> +
> + }
> +} // namespace __cxxabiv1
> +
> +#endif
> +
> +#pragma GCC visibility pop
> +
> +#endif // _CXXABI_INIT_EXCEPTION_H
> diff --git a/libstdc++-v3/libsupc++/eh_throw.cc b/libstdc++-v3/libsupc++/eh_throw.cc
> index 9aac218..a05f4eb 100644
> --- a/libstdc++-v3/libsupc++/eh_throw.cc
> +++ b/libstdc++-v3/libsupc++/eh_throw.cc
> @@ -55,6 +55,22 @@ __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
> #endif
> }
>
> +extern "C" __cxa_refcounted_exception*
> +__cxxabiv1::__cxa_init_primary_exception(void *obj, std::type_info *tinfo,
> + void (_GLIBCXX_CDTOR_CALLABI *dest) (void *))
> +{
> + __cxa_refcounted_exception *header
> + = __get_refcounted_exception_header_from_obj (obj);
> + header->referenceCount = 0;
> + header->exc.exceptionType = tinfo;
> + header->exc.exceptionDestructor = dest;
> + header->exc.unexpectedHandler = std::get_unexpected ();
> + header->exc.terminateHandler = std::get_terminate ();
> + __GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->exc.unwindHeader.exception_class);
> + header->exc.unwindHeader.exception_cleanup = __gxx_exception_cleanup;
> +
> + return header;
> +}
>
> extern "C" void
> __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
> @@ -64,17 +80,10 @@ __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
>
> __cxa_eh_globals *globals = __cxa_get_globals ();
> globals->uncaughtExceptions += 1;
> -
> // Definitely a primary.
> - __cxa_refcounted_exception *header
> - = __get_refcounted_exception_header_from_obj (obj);
> + __cxa_refcounted_exception *header =
> + __cxa_init_primary_exception(obj, tinfo, dest);
> header->referenceCount = 1;
> - header->exc.exceptionType = tinfo;
> - header->exc.exceptionDestructor = dest;
> - header->exc.unexpectedHandler = std::get_unexpected ();
> - header->exc.terminateHandler = std::get_terminate ();
> - __GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->exc.unwindHeader.exception_class);
> - header->exc.unwindHeader.exception_cleanup = __gxx_exception_cleanup;
>
> #ifdef __USING_SJLJ_EXCEPTIONS__
> _Unwind_SjLj_RaiseException (&header->exc.unwindHeader);
> diff --git a/libstdc++-v3/libsupc++/exception b/libstdc++-v3/libsupc++/exception
> index 63631f6..8be903b 100644
> --- a/libstdc++-v3/libsupc++/exception
> +++ b/libstdc++-v3/libsupc++/exception
> @@ -36,39 +36,12 @@
>
> #include <bits/c++config.h>
> #include <bits/atomic_lockfree_defines.h>
> +#include <bits/exception.h>
>
> extern "C++" {
>
> namespace std
> {
> - /**
> - * @defgroup exceptions Exceptions
> - * @ingroup diagnostics
> - *
> - * Classes and functions for reporting errors via exception classes.
> - * @{
> - */
> -
> - /**
> - * @brief Base class for all library exceptions.
> - *
> - * This is the base class for all exceptions thrown by the standard
> - * library, and by certain language expressions. You are free to derive
> - * your own %exception classes, or use a different hierarchy, or to
> - * throw non-class data (e.g., fundamental types).
> - */
> - class exception
> - {
> - public:
> - exception() _GLIBCXX_USE_NOEXCEPT { }
> - virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
> -
> - /** Returns a C-style character string describing the general cause
> - * of the current error. */
> - virtual const char*
> - what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
> - };
> -
> /** If an %exception is thrown which is not listed in a function's
> * %exception specification, one of these may be thrown. */
> class bad_exception : public exception
> diff --git a/libstdc++-v3/libsupc++/exception.h b/libstdc++-v3/libsupc++/exception.h
> new file mode 100644
> index 0000000..09ac4e0
> --- /dev/null
> +++ b/libstdc++-v3/libsupc++/exception.h
> @@ -0,0 +1,78 @@
> +// Exception Handling support header for -*- C++ -*-
> +
> +// Copyright (C) 2016 Free Software Foundation, Inc.
> +//
> +// This file is part of GCC.
> +//
> +// GCC is free software; you can redistribute it and/or modify
> +// it under the terms of the GNU General Public License as published by
> +// the Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +//
> +// GCC is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +// GNU General Public License for more details.
> +//
> +// Under Section 7 of GPL version 3, you are granted additional
> +// permissions described in the GCC Runtime Library Exception, version
> +// 3.1, as published by the Free Software Foundation.
> +
> +// You should have received a copy of the GNU General Public License and
> +// a copy of the GCC Runtime Library Exception along with this program;
> +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
> +// <http://www.gnu.org/licenses/>.
> +
> +/** @file bits/exception.h
> + * This is an internal header file, included by other library headers.
> + * Do not attempt to use it directly.
> + */
> +
> +#ifndef __EXCEPTION_H
> +#define __EXCEPTION_H 1
> +
> +#pragma GCC system_header
> +
> +#pragma GCC visibility push(default)
> +
> +#include <bits/c++config.h>
> +
> +extern "C++" {
> +
> +namespace std
> +{
> + /**
> + * @defgroup exceptions Exceptions
> + * @ingroup diagnostics
> + *
> + * Classes and functions for reporting errors via exception classes.
> + * @{
> + */
> +
> + /**
> + * @brief Base class for all library exceptions.
> + *
> + * This is the base class for all exceptions thrown by the standard
> + * library, and by certain language expressions. You are free to derive
> + * your own %exception classes, or use a different hierarchy, or to
> + * throw non-class data (e.g., fundamental types).
> + */
> + class exception
> + {
> + public:
> + exception() _GLIBCXX_USE_NOEXCEPT { }
> + virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
> +
> + /** Returns a C-style character string describing the general cause
> + * of the current error. */
> + virtual const char*
> + what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
> + };
> +
> +} // namespace std
> +
> +}
> +
> +#pragma GCC visibility pop
> +
> +#endif
> diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h
> index 783e539..37b2966 100644
> --- a/libstdc++-v3/libsupc++/exception_ptr.h
> +++ b/libstdc++-v3/libsupc++/exception_ptr.h
> @@ -35,6 +35,9 @@
>
> #include <bits/c++config.h>
> #include <bits/exception_defines.h>
> +#include <bits/cxxabi_init_exception.h>
> +#include <typeinfo>
> +#include <new>
>
> #if ATOMIC_INT_LOCK_FREE < 2
> # error This platform does not support exception propagation.
> @@ -62,6 +65,8 @@ namespace std
> * value.
> */
> exception_ptr current_exception() _GLIBCXX_USE_NOEXCEPT;
> + template<typename _Ex>
> + exception_ptr make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
>
> /// Throw the object pointed to by the exception_ptr.
> void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
> @@ -87,6 +92,8 @@ namespace std
>
> friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT;
> friend void std::rethrow_exception(exception_ptr);
> + template<typename _Ex>
> + friend exception_ptr std::make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
>
> public:
> exception_ptr() _GLIBCXX_USE_NOEXCEPT;
> @@ -162,8 +169,12 @@ namespace std
> swap(exception_ptr& __lhs, exception_ptr& __rhs)
> { __lhs.swap(__rhs); }
>
> - } // namespace __exception_ptr
> + template<typename _Ex>
> + inline void
> + __dest_thunk(void* x)
> + { static_cast<_Ex*>(x)->~_Ex(); }
>
> + } // namespace __exception_ptr
>
> /// Obtain an exception_ptr pointing to a copy of the supplied object.
> template<typename _Ex>
> @@ -173,7 +184,16 @@ namespace std
> #if __cpp_exceptions
> try
> {
> - throw __ex;
> +#if __cpp_rtti && !_GLIBCXX_HAVE_CDTOR_CALLABI
> + void *__e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
> + (void)__cxxabiv1::__cxa_init_primary_exception(__e,
> + const_cast<std::type_info*>(&typeid(__ex)),
> + __exception_ptr::__dest_thunk<_Ex>);
> + new (__e) _Ex(__ex);
> + return exception_ptr(__e);
> +#else
> + throw __ex;
> +#endif
> }
> catch(...)
> {
> diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo
> index baedf01..1c5ccc5 100644
> --- a/libstdc++-v3/libsupc++/typeinfo
> +++ b/libstdc++-v3/libsupc++/typeinfo
> @@ -31,7 +31,7 @@
>
> #pragma GCC system_header
>
> -#include <exception>
> +#include <bits/exception.h>
> #if __cplusplus >= 201103L
> #include <bits/hash_bytes.h>
> #endif
> --
> Gleb.
--
Gleb.