diff mbox

[PATCHv2] do not throw in std::make_exception_ptr

Message ID 20160805044923.GX17903@scylladb.com
State New
Headers show

Commit Message

Gleb Natapov Aug. 5, 2016, 4:49 a.m. UTC
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


--
			Gleb.

Comments

Daniel Krügler Aug. 5, 2016, 5:56 a.m. UTC | #1
2016-08-05 6:49 GMT+02:00 Gleb Natapov <gleb@scylladb.com>:
> 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.

[..]

> +#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

>    /// 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

Please take this question was a grain of salt: Is it really correct
that the more efficient approach is used, when

!_GLIBCXX_HAVE_CDTOR_CALLABI

instead of

_GLIBCXX_HAVE_CDTOR_CALLABI

?

To me _GLIBCXX_HAVE_CDTOR_CALLABI sounds like a feature but with that
logic it sounds more like it would be constraint, is that correct?

Thanks,

- Daniel
Gleb Natapov Aug. 5, 2016, 7:21 a.m. UTC | #2
On Fri, Aug 05, 2016 at 07:56:02AM +0200, Daniel Krügler wrote:
> 2016-08-05 6:49 GMT+02:00 Gleb Natapov <gleb@scylladb.com>:
> > 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.
> 
> [..]
> 
> > +#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
> 
> >    /// 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
> 
> Please take this question was a grain of salt: Is it really correct
> that the more efficient approach is used, when
> 
> !_GLIBCXX_HAVE_CDTOR_CALLABI
> 
> instead of
> 
> _GLIBCXX_HAVE_CDTOR_CALLABI
> 
> ?
> 
> To me _GLIBCXX_HAVE_CDTOR_CALLABI sounds like a feature but with that
> logic it sounds more like it would be constraint, is that correct?
> 
_GLIBCXX_HAVE_CDTOR_CALLABI means that a platform has special calling
convention for class members. It is not a feature just a platform quirk.
On such platform __dest_thunk will not work.

--
			Gleb.
Gleb Natapov Aug. 21, 2016, 12:20 p.m. UTC | #3
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.
diff mbox

Patch

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