Author: theraven
Date: Fri Jan 11 15:05:55 2013
New Revision: 245304
URL: http://svnweb.freebsd.org/changeset/base/245304

Log:
  Merge new version of libcxxrt.  This brings in three fixes:
  
  - Don't treat pointers to members as pointers in catch blocks (they're usually
    fat pointers).
  
  - Correctly catch foreign exceptions in catchalls.
  
  - Ensure that a happens-before relationship is established when setting
    terminate handlers in one thread and calling them in another.

Added:
  head/contrib/libcxxrt/atomic.h
     - copied unchanged from r245303, vendor/libcxxrt/dist/atomic.h
Modified:
  head/contrib/libcxxrt/exception.cc
  head/contrib/libcxxrt/memory.cc
  head/contrib/libcxxrt/typeinfo.h
Directory Properties:
  head/contrib/libcxxrt/   (props changed)

Copied: head/contrib/libcxxrt/atomic.h (from r245303, 
vendor/libcxxrt/dist/atomic.h)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/contrib/libcxxrt/atomic.h      Fri Jan 11 15:05:55 2013        
(r245304, copy of r245303, vendor/libcxxrt/dist/atomic.h)
@@ -0,0 +1,29 @@
+
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+/**
+ * Swap macro that enforces a happens-before relationship with a corresponding
+ * ATOMIC_LOAD.
+ */
+#if __has_feature(cxx_atomic)
+#define ATOMIC_SWAP(addr, val)\
+       __atomic_exchange(addr, val, __ATOMIC_ACQ_REL)
+#elif __has_builtin(__sync_swap)
+#define ATOMIC_SWAP(addr, val)\
+       __sync_swap(addr, val)
+#else
+#define ATOMIC_SWAP(addr, val)\
+       __sync_lock_test_and_set(addr, val)
+#endif
+
+#if __has_feature(cxx_atomic)
+#define ATOMIC_LOAD(addr)\
+       __atomic_load(addr, __ATOMIC_ACQUIRE)
+#else
+#define ATOMIC_LOAD(addr)\
+       (__sync_synchronize(), *addr)
+#endif

Modified: head/contrib/libcxxrt/exception.cc
==============================================================================
--- head/contrib/libcxxrt/exception.cc  Fri Jan 11 15:01:43 2013        
(r245303)
+++ head/contrib/libcxxrt/exception.cc  Fri Jan 11 15:05:55 2013        
(r245304)
@@ -32,6 +32,7 @@
 #include <pthread.h>
 #include "typeinfo.h"
 #include "dwarf_eh.h"
+#include "atomic.h"
 #include "cxxabi.h"
 
 #pragma weak pthread_key_create
@@ -155,6 +156,17 @@ struct __cxa_thread_info
         */
        _Unwind_Exception *currentCleanup;
        /**
+        * Our state with respect to foreign exceptions.  Usually none, set to
+        * caught if we have just caught an exception and rethrown if we are
+        * rethrowing it.
+        */
+       enum 
+       {
+               none,
+               caught,
+               rethrown
+       } foreign_exception_state;
+       /**
         * The public part of this structure, accessible from outside of this
         * module.
         */
@@ -308,7 +320,16 @@ static void thread_cleanup(void* thread_
        __cxa_thread_info *info = (__cxa_thread_info*)thread_info;
        if (info->globals.caughtExceptions)
        {
-               free_exception_list(info->globals.caughtExceptions);
+               // If this is a foreign exception, ask it to clean itself up.
+               if (info->foreign_exception_state != __cxa_thread_info::none)
+               {
+                       _Unwind_Exception *e = 
(_Unwind_Exception*)info->globals.caughtExceptions;
+                       e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e);
+               }
+               else
+               {
+                       free_exception_list(info->globals.caughtExceptions);
+               }
        }
        free(thread_info);
 }
@@ -780,7 +801,8 @@ extern "C" void __cxa_decrement_exceptio
  */
 extern "C" void __cxa_rethrow()
 {
-       __cxa_eh_globals *globals = __cxa_get_globals();
+       __cxa_thread_info *ti = thread_info_fast();
+       __cxa_eh_globals *globals = &ti->globals;
        // Note: We don't remove this from the caught list here, because
        // __cxa_end_catch will be called when we unwind out of the try block.  
We
        // could probably make this faster by providing an alternative rethrow
@@ -795,6 +817,15 @@ extern "C" void __cxa_rethrow()
                std::terminate();
        }
 
+       if (ti->foreign_exception_state != __cxa_thread_info::none)
+       {
+               ti->foreign_exception_state = __cxa_thread_info::rethrown;
+               _Unwind_Exception *e = (_Unwind_Exception*)ex;
+               _Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(e);
+               report_failure(err, ex);
+               return;
+       }
+
        assert(ex->handlerCount > 0 && "Rethrowing uncaught exception!");
 
        // ex->handlerCount will be decremented in __cxa_end_catch in enclosing
@@ -848,9 +879,9 @@ static bool check_type_signature(__cxa_e
                                  void *&adjustedPtr)
 {
        void *exception_ptr = (void*)(ex+1);
-       const std::type_info *ex_type = ex->exceptionType;
+       const std::type_info *ex_type = ex ? ex->exceptionType : 0;
 
-       bool is_ptr = ex_type->__is_pointer_p();
+       bool is_ptr = ex ? ex_type->__is_pointer_p() : false;
        if (is_ptr)
        {
                exception_ptr = *(void**)exception_ptr;
@@ -911,8 +942,8 @@ static handler_type check_action_record(
                action_record = displacement ? 
                        action_record_offset_base + displacement : 0;
                // We only check handler types for C++ exceptions - foreign 
exceptions
-               // are only allowed for cleanup.
-               if (filter > 0 && 0 != ex)
+               // are only allowed for cleanups and catchalls.
+               if (filter > 0)
                {
                        std::type_info *handler_type = 
get_type_info_entry(context, lsda, filter);
                        if (check_type_signature(ex, handler_type, adjustedPtr))
@@ -1133,8 +1164,10 @@ extern "C" void *__cxa_begin_catch(void 
 extern "C" void *__cxa_begin_catch(void *e)
 #endif
 {
-       // Decrement the uncaught exceptions count
-       __cxa_eh_globals *globals = __cxa_get_globals();
+       // We can't call the fast version here, because if the first exception 
that
+       // we see is a foreign exception then we won't have called it yet.
+       __cxa_thread_info *ti = thread_info();
+       __cxa_eh_globals *globals = &ti->globals;
        globals->uncaughtExceptions--;
        _Unwind_Exception *exceptionObject = (_Unwind_Exception*)e;
 
@@ -1177,9 +1210,22 @@ extern "C" void *__cxa_begin_catch(void 
                {
                        ex->handlerCount++;
                }
+               ti->foreign_exception_state = __cxa_thread_info::none;
                
                return ex->adjustedPtr;
        }
+       else
+       {
+               // If this is a foreign exception, then we need to be able to
+               // store it.  We can't chain foreign exceptions, so we give up
+               // if there are already some outstanding ones.
+               if (globals->caughtExceptions != 0)
+               {
+                       std::terminate();
+               }
+               globals->caughtExceptions = (__cxa_exception*)exceptionObject;
+               ti->foreign_exception_state = __cxa_thread_info::caught;
+       }
        // exceptionObject is the pointer to the _Unwind_Exception within the
        // __cxa_exception.  The throw object is after this
        return ((char*)exceptionObject + sizeof(_Unwind_Exception));
@@ -1195,10 +1241,23 @@ extern "C" void __cxa_end_catch()
 {
        // We can call the fast version here because the slow version is called 
in
        // __cxa_throw(), which must have been called before we end a catch 
block
-       __cxa_eh_globals *globals = __cxa_get_globals_fast();
+       __cxa_thread_info *ti = thread_info_fast();
+       __cxa_eh_globals *globals = &ti->globals;
        __cxa_exception *ex = globals->caughtExceptions;
 
        assert(0 != ex && "Ending catch when no exception is on the stack!");
+       
+       if (ti->foreign_exception_state != __cxa_thread_info::none)
+       {
+               globals->caughtExceptions = 0;
+               if (ti->foreign_exception_state != __cxa_thread_info::rethrown)
+               {
+                       _Unwind_Exception *e = 
(_Unwind_Exception*)ti->globals.caughtExceptions;
+                       e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e);
+               }
+               ti->foreign_exception_state = __cxa_thread_info::none;
+               return;
+       }
 
        bool deleteException = true;
 
@@ -1328,7 +1387,7 @@ namespace std
        {
                if (thread_local_handlers) { return 
pathscale::set_unexpected(f); }
 
-               return __sync_lock_test_and_set(&unexpectedHandler, f);
+               return ATOMIC_SWAP(&terminateHandler, f);
        }
        /**
         * Sets the function that is called to terminate the program.
@@ -1336,7 +1395,8 @@ namespace std
        terminate_handler set_terminate(terminate_handler f) throw()
        {
                if (thread_local_handlers) { return 
pathscale::set_terminate(f); }
-               return __sync_lock_test_and_set(&terminateHandler, f);
+
+               return ATOMIC_SWAP(&terminateHandler, f);
        }
        /**
         * Terminates the program, calling a custom terminate implementation if
@@ -1390,7 +1450,7 @@ namespace std
                {
                        return info->unexpectedHandler;
                }
-               return unexpectedHandler;
+               return ATOMIC_LOAD(&unexpectedHandler);
        }
        /**
         * Returns the current terminate handler.
@@ -1402,7 +1462,7 @@ namespace std
                {
                        return info->terminateHandler;
                }
-               return terminateHandler;
+               return ATOMIC_LOAD(&terminateHandler);
        }
 }
 #ifdef __arm__

Modified: head/contrib/libcxxrt/memory.cc
==============================================================================
--- head/contrib/libcxxrt/memory.cc     Fri Jan 11 15:01:43 2013        
(r245303)
+++ head/contrib/libcxxrt/memory.cc     Fri Jan 11 15:05:55 2013        
(r245304)
@@ -36,14 +36,8 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include "stdexcept.h"
+#include "atomic.h"
 
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#if !__has_builtin(__sync_swap)
-#define __sync_swap __sync_lock_test_and_set
-#endif
 
 namespace std
 {
@@ -67,7 +61,12 @@ namespace std
        __attribute__((weak))
        new_handler set_new_handler(new_handler handler)
        {
-               return __sync_swap(&new_handl, handler);
+               return ATOMIC_SWAP(&new_handl, handler);
+       }
+       __attribute__((weak))
+       new_handler get_new_handler(void)
+       {
+               return ATOMIC_LOAD(&new_handl);
        }
 }
 
@@ -75,12 +74,17 @@ namespace std
 __attribute__((weak))
 void* operator new(size_t size)
 {
+       if (0 == size)
+       {
+               size = 1;
+       }
        void * mem = malloc(size);
        while (0 == mem)
        {
-               if (0 != new_handl)
+               new_handler h = std::get_new_handler();
+               if (0 != h)
                {
-                       new_handl();
+                       h();
                }
                else
                {
@@ -95,14 +99,19 @@ void* operator new(size_t size)
 __attribute__((weak))
 void* operator new(size_t size, const std::nothrow_t &) throw()
 {
+       if (0 == size)
+       {
+               size = 1;
+       }
        void *mem = malloc(size);
        while (0 == mem)
        {
-               if (0 != new_handl)
+               new_handler h = std::get_new_handler();
+               if (0 != h)
                {
                        try
                        {
-                               new_handl();
+                               h();
                        }
                        catch (...)
                        {

Modified: head/contrib/libcxxrt/typeinfo.h
==============================================================================
--- head/contrib/libcxxrt/typeinfo.h    Fri Jan 11 15:01:43 2013        
(r245303)
+++ head/contrib/libcxxrt/typeinfo.h    Fri Jan 11 15:05:55 2013        
(r245304)
@@ -70,6 +70,14 @@ namespace std
                 */
                public:
                /**
+                * Returns true if this is some pointer type, false otherwise.
+                */
+               virtual bool __is_pointer_p() const { return false; }
+               /**
+                * Returns true if this is some function type, false otherwise.
+                */
+               virtual bool __is_function_p() const { return false; }
+               /**
                 * Catch function.  Allows external libraries to implement
                 * their own basic types.  This is used, for example, in the
                 * GNUstep Objective-C runtime to allow Objective-C types to be
@@ -95,14 +103,6 @@ namespace std
                {
                        return false;
                }
-               /**
-                * Returns true if this is some pointer type, false otherwise.
-                */
-               virtual bool __is_pointer_p() const { return false; }
-               /**
-                * Returns true if this is some function type, false otherwise.
-                */
-               virtual bool __is_function_p() const { return false; }
        };
 }
 
@@ -284,7 +284,6 @@ namespace ABI_NAMESPACE
                        /** Pointer is a pointer to a member of an incomplete 
class. */
                        __incomplete_class_mask = 0x10
                };
-               virtual bool __is_pointer_p() const { return true; }
                virtual bool __do_catch(const type_info *thrown_type,
                                        void **thrown_object,
                                        unsigned outer) const;
@@ -296,6 +295,7 @@ namespace ABI_NAMESPACE
        struct __pointer_type_info : public __pbase_type_info
        {
                virtual ~__pointer_type_info();
+               virtual bool __is_pointer_p() const { return true; }
        };
 
        /**
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to