svn commit: r250241 - stable/9/contrib/libcxxrt

Dimitry Andric dim at FreeBSD.org
Sat May 4 15:43:10 UTC 2013


Author: dim
Date: Sat May  4 15:43:09 2013
New Revision: 250241
URL: http://svnweb.freebsd.org/changeset/base/250241

Log:
  MFC r245304 (by theraven):
  
    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.
  
  MFC r245327 (by theraven):
  
    Fix libcxxrt / libc++ build with the clang in head.
  
    Pointy hat to:	theraven
  
  MFC r245745 (by theraven):
  
    Import new fix from libcxxrt.  This fixes the case where you attempt
    to rethrow an exception when you haven't caught one.  This is largely
    a cosmetic fix, as (unless you have a very unusual terminate handler
    installed) it will print a nice error and then abort, rather than
    just aborting.
  
  MFC r246462 (by theraven):
  
    Fix a copy-and-paste error in libcxxrt.
  
  MFC r249993:
  
    Merge libcxxrt c812a07cd2f95c1403baf0bbe0366e7618d1d6d3:
  
    * Don't call the _fast version of the TLS accessor in terminate() or
      unexpected().
      1) TLS may not have been set up yet.
      2) When we're in one of these functions, Really Bad Stuff has
         happened and potentially saving a few cycles really isn't
         important.
    * Merge in fixes from FreeBSD trunk to make atomics work with recent
      clang.

Added:
  stable/9/contrib/libcxxrt/atomic.h
     - copied, changed from r245304, head/contrib/libcxxrt/atomic.h
Modified:
  stable/9/contrib/libcxxrt/exception.cc
  stable/9/contrib/libcxxrt/memory.cc
  stable/9/contrib/libcxxrt/typeinfo.h
Directory Properties:
  stable/9/contrib/libcxxrt/   (props changed)

Copied and modified: stable/9/contrib/libcxxrt/atomic.h (from r245304, head/contrib/libcxxrt/atomic.h)
==============================================================================
--- head/contrib/libcxxrt/atomic.h	Fri Jan 11 15:05:55 2013	(r245304, copy source)
+++ stable/9/contrib/libcxxrt/atomic.h	Sat May  4 15:43:09 2013	(r250241)
@@ -9,9 +9,9 @@
  * Swap macro that enforces a happens-before relationship with a corresponding
  * ATOMIC_LOAD.
  */
-#if __has_feature(cxx_atomic)
+#if __has_builtin(__c11_atomic_exchange)
 #define ATOMIC_SWAP(addr, val)\
-	__atomic_exchange(addr, val, __ATOMIC_ACQ_REL)
+	__c11_atomic_exchange((_Atomic(__typeof__(val))*)addr, val, __ATOMIC_ACQ_REL)
 #elif __has_builtin(__sync_swap)
 #define ATOMIC_SWAP(addr, val)\
 	__sync_swap(addr, val)
@@ -20,9 +20,9 @@
 	__sync_lock_test_and_set(addr, val)
 #endif
 
-#if __has_feature(cxx_atomic)
+#if __has_builtin(__c11_atomic_load)
 #define ATOMIC_LOAD(addr)\
-	__atomic_load(addr, __ATOMIC_ACQUIRE)
+	__c11_atomic_load((_Atomic(__typeof__(*addr))*)addr, __ATOMIC_ACQUIRE)
 #else
 #define ATOMIC_LOAD(addr)\
 	(__sync_synchronize(), *addr)

Modified: stable/9/contrib/libcxxrt/exception.cc
==============================================================================
--- stable/9/contrib/libcxxrt/exception.cc	Sat May  4 15:42:55 2013	(r250240)
+++ stable/9/contrib/libcxxrt/exception.cc	Sat May  4 15:43:09 2013	(r250241)
@@ -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();
+	__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(&unexpectedHandler, 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
@@ -1344,7 +1404,7 @@ namespace std
 	 */
 	void terminate()
 	{
-		static __cxa_thread_info *info = thread_info_fast();
+		static __cxa_thread_info *info = thread_info();
 		if (0 != info && 0 != info->terminateHandler)
 		{
 			info->terminateHandler();
@@ -1361,7 +1421,7 @@ namespace std
 	 */
 	void unexpected()
 	{
-		static __cxa_thread_info *info = thread_info_fast();
+		static __cxa_thread_info *info = thread_info();
 		if (0 != info && 0 != info->unexpectedHandler)
 		{
 			info->unexpectedHandler();
@@ -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: stable/9/contrib/libcxxrt/memory.cc
==============================================================================
--- stable/9/contrib/libcxxrt/memory.cc	Sat May  4 15:42:55 2013	(r250240)
+++ stable/9/contrib/libcxxrt/memory.cc	Sat May  4 15:43:09 2013	(r250241)
@@ -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: stable/9/contrib/libcxxrt/typeinfo.h
==============================================================================
--- stable/9/contrib/libcxxrt/typeinfo.h	Sat May  4 15:42:55 2013	(r250240)
+++ stable/9/contrib/libcxxrt/typeinfo.h	Sat May  4 15:43:09 2013	(r250241)
@@ -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; }
 	};
 
 	/**


More information about the svn-src-stable-9 mailing list