[Substrate-commits] SF.net SVN: substrate: [282] trunk
Brought to you by:
landonf
|
From: <la...@us...> - 2006-08-31 22:26:40
|
Revision: 282
http://svn.sourceforge.net/substrate/?rev=282&view=rev
Author: landonf
Date: 2006-08-31 15:26:28 -0700 (Thu, 31 Aug 2006)
Log Message:
-----------
r5713@zadder: landonf | 2006-08-31 15:25:21 -0700
Clean up LF_PRIVATE usage (should be used for implementation, not header declaration)
Finish work on exception stack handling for gcc <4.0
Modified Paths:
--------------
trunk/Foundation/LFHash.h
trunk/Foundation/LFObjCRuntime.h.in
trunk/Foundation/Makefile.in
trunk/Foundation/NSConcreteData.m
trunk/Foundation/NSException.h
trunk/Foundation/NSException.m
trunk/Foundation/port.h
trunk/Mk/autoconf.mk.in
trunk/aclocal.m4
trunk/configure.ac
Added Paths:
-----------
trunk/Foundation/LFGNUException.m
trunk/Foundation/LFStackException.m
Removed Paths:
-------------
trunk/Foundation/LFObjCExceptionStack.m
trunk/Foundation/LFObjCGNUException.m
Property Changed:
----------------
trunk/
Property changes on: trunk
___________________________________________________________________
Name: svk:merge
- 11572a18-12fc-0310-9209-f8edcc8181a7:/local/substrate/trunk:5712
+ 11572a18-12fc-0310-9209-f8edcc8181a7:/local/substrate/trunk:5713
Added: trunk/Foundation/LFGNUException.m
===================================================================
--- trunk/Foundation/LFGNUException.m (rev 0)
+++ trunk/Foundation/LFGNUException.m 2006-08-31 22:26:28 UTC (rev 282)
@@ -0,0 +1,153 @@
+/*
+ * LFGNUException.m vi:ts=4:sw=4:expandtab:
+ * New-style language exception handling for the GNU Objective-C runtime.
+ *
+ * Copyright (C) 2005 - 2006 Landon Fuller <la...@op...>
+ * All rights reserved.
+ *
+ * Author: Landon Fuller <la...@op...>
+ *
+ * This file is part of libFoundation.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.
+ *
+ * We disclaim all warranties with regard to this software, including all
+ * implied warranties of merchantability and fitness, in no event shall
+ * we be liable for any special, indirect or consequential damages or any
+ * damages whatsoever resulting from loss of use, data or profits, whether in
+ * an action of contract, negligence or other tortious action, arising out of
+ * or in connection with the use or performance of this software.
+ */
+
+/*!
+ * @file
+ * @internal
+ * @brief Support functions for new-style objective-C exception handling in
+ * the GNU runtime.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(GNU_RUNTIME) && defined(OBJC_EXCEPTIONS)
+
+/* This is unfortunately required to use RTLD_NEXT on Linux systems */
+#define _GNU_SOURCE
+
+#include <Foundation/NSZone.h>
+#include <Foundation/NSException.h>
+#include <Foundation/LFRuntime.h>
+#include <Foundation/spin.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+
+# include <dlfcn.h>
+/* GCC's exception handling and stack unwinding routines */
+# include <unwind.h>
+
+/* Uncaught exception handler */
+static LFUncaughtExceptionHandler *ueh_handler;
+static slock_t ueh_lock;
+
+/*! libgcc's _Unwind_RaiseException()
+ * @internal */
+static _Unwind_Reason_Code (*_real_Unwind_RaiseException)(struct _Unwind_Exception *e);
+
+/*!
+ * Set Objective-C Uncaught Exception Handler.
+ * @internal
+ */
+LF_PRIVATE void LFSetUncaughtExceptionHandler (LFUncaughtExceptionHandler *handler) {
+ SpinLockAcquire(&ueh_lock);
+ ueh_handler = handler;
+ SpinLockRelease(&ueh_lock);
+}
+
+/*!
+ * Get Objective-C Uncaught Exception Handler.
+ * @internal
+ */
+LF_PRIVATE LFUncaughtExceptionHandler *LFGetUncaughtExceptionHandler (void) {
+ LFUncaughtExceptionHandler *handler;
+ SpinLockAcquire(&ueh_lock);
+ handler = ueh_handler;
+ SpinLockRelease(&ueh_lock);
+
+ return handler;
+}
+
+/*!
+ * Initialize the Objective-C Exception Handler.
+ * @internal
+ */
+LF_PRIVATE void LFInitExceptionHandler (LFUncaughtExceptionHandler *handler) {
+ /* Initialize the lock */
+ SpinLockInit(&ueh_lock);
+ ueh_handler = handler;
+
+#ifdef RTLD_NEXT
+ /* Locate the _Unwind_RaiseException symbol */
+ _real_Unwind_RaiseException = dlsym(RTLD_NEXT, "_Unwind_RaiseException");
+#endif /* RTLD_NEXT */
+
+}
+
+/******************************************************************************
+ * XXX: Temporary Hack.
+ *
+ * When using the GNU Objective-C runtime, support for a default
+ * Objective-C exception handler is implemented by overriding gcc's
+ * _Unwind_RaiseException, calling the true _Unwind_RaiseException,
+ * and checking for _URC_END_OF_STACK, which signals that no exception
+ * handler was found.
+ *
+ * This is wrong, wrong, wrong, (really wrong!), but there is currently
+ * no other way to implement this functionality.
+ *
+ * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27466 for my libobjc
+ * enhancement request.
+ ******************************************************************************/
+
+/*! Our _Unwind_RaiseException()
+ * @internal */
+_Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *uwe) {
+ _Unwind_Reason_Code err;
+
+ err = _real_Unwind_RaiseException(uwe);
+ if (err == _URC_END_OF_STACK) {
+ LFUncaughtExceptionHandler *handler;
+
+ /* Acquire a lock and get the current ueh_handler */
+ SpinLockAcquire(&ueh_lock);
+ handler = ueh_handler;
+ SpinLockRelease(&ueh_lock);
+
+ /* If a handler is available, call it.
+ * We manually re-raise the _Unwind_Exception so that we can get
+ * access to the thrown Objective-C object without digging
+ * into the private libobjc structures */
+ @try {
+ _real_Unwind_RaiseException(uwe);
+ }
+ @catch (id exc) {
+ ueh_handler(exc);
+ }
+ }
+
+ /* Fire SIGTRAP */
+ kill(getpid(), SIGTRAP);
+
+ /* We're going to return objc_exception_throw(), where abort() will be
+ * called immediately. Unless someone caught SIGTRAP, this should
+ * be unreachable */
+ return err;
+}
+
+#endif /* GNU_RUNTIME && OBJC_EXCEPTIONS */
Property changes on: trunk/Foundation/LFGNUException.m
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/Foundation/LFHash.h
===================================================================
--- trunk/Foundation/LFHash.h 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Foundation/LFHash.h 2006-08-31 22:26:28 UTC (rev 282)
@@ -35,7 +35,7 @@
-------------------------------------------------------------------------------
*/
-LF_PRIVATE uint32_t LFHashWord(const uint32_t *k, size_t length, uint32_t initval);
-LF_PRIVATE uint32_t LFHashLittle(const void *key, size_t length, uint32_t initval);
-LF_PRIVATE void LFHashLittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb);
-LF_PRIVATE uint32_t LFHashBig(const void *key, size_t length, uint32_t initval);
+uint32_t LFHashWord(const uint32_t *k, size_t length, uint32_t initval);
+uint32_t LFHashLittle(const void *key, size_t length, uint32_t initval);
+void LFHashLittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb);
+uint32_t LFHashBig(const void *key, size_t length, uint32_t initval);
Deleted: trunk/Foundation/LFObjCExceptionStack.m
===================================================================
--- trunk/Foundation/LFObjCExceptionStack.m 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Foundation/LFObjCExceptionStack.m 2006-08-31 22:26:28 UTC (rev 282)
@@ -1,310 +0,0 @@
-/*
- * LFObjCExceptionStack.m vi:ts=4:sw=4:expandtab:
- *
- * Generic Exception Stack Implementation.
- * Compatible with both new-style language exceptions as implemented by
- * the Apple runtime, and old-style NS_DURING exceptions in both runtimes.
- *
- * Copyright (C) 2005 - 2006 Landon Fuller <la...@op...>
- * All rights reserved.
- *
- * Author: Landon Fuller <la...@op...>
- *
- * This file is part of libFoundation.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation.
- *
- * We disclaim all warranties with regard to this software, including all
- * implied warranties of merchantability and fitness, in no event shall
- * we be liable for any special, indirect or consequential damages or any
- * damages whatsoever resulting from loss of use, data or profits, whether in
- * an action of contract, negligence or other tortious action, arising out of
- * or in connection with the use or performance of this software.
- */
-
-/*!
- * @file
- * @internal
- * @brief LFObjCRuntime
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(APPLE_RUNTIME) || (defined(GNU_RUNTIME) && !defined(OBJC_EXCEPTIONS))
-
-/******************************************************************************
- * This code implementions binary-compatible exception handling for both
- * new and old-style exceptions in the Apple Objective-C runtime.
- *
- * It also implements non-binary compatible exception handling support for
- * old-style exceptions in GNU's Objective-C runtime.
- *
- * We maintain a per-thread stack of exception handlers. Handlers are pushed
- * and popped off the stack at the beginning and end of every try/catch block,
- * via a runtime function call. When an exception occurs, our
- * LFObjC_ExceptionThrow() function is called, and we need to longjmp to the
- * current exception handler at the top of the per-thread handler stack.
- *
- * The push/pop runtime function calls are handled automatically by the
- * new-style exception support in Apple's runtime. With old-style exceptions,
- * we manually implement the equivalent using preprocessor macros.
- *****************************************************************************/
-
-#include <Foundation/NSZone.h>
-#include <Foundation/NSException.h>
-#include <Foundation/LFObjCRuntime.h>
-#include <Foundation/spin.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <setjmp.h>
-
-/* Number of exception handlers to store in each bucket.
- * Selected arbitrarily. */
-#define EHS_BUCKET_SIZE 16
-
-/* Forward declarations */
-static void LFObjC_ExceptionThrow (id);
-static void LFObjC_ExceptionTryEnter (void *);
-static void LFObjC_ExceptionTryExit (void *);
-static id LFObjC_ExceptionExtract (void *);
-static int LFObjC_ExceptionMatch (Class, id);
-static void free_exception_handler_stack_tls (void *);
-
-/* Per-thread stack of exception handler buckets, each bucket
- * holds EHS_BUCKET_SIZE handlers */
-typedef struct LFExceptionHandlerBucket {
- int count;
- LFObjCLocalExceptionData *excData[EHS_BUCKET_SIZE];
- struct LFExceptionHandlerBucket *next;
-} LFExceptionHandlerBucket;
-
-/* We modify the pointer in this structure so that we don't
- * have to call pthread_setspecific() repeatedly */
-typedef struct LFExceptionHandler_TLS {
- LFExceptionHandlerBucket *bucket;
-} LFExceptionHandler_TLS;
-
-/* Per-thread EH stack key */
-static pthread_key_t LFExceptionHandlerStack_key;
-
-/* Uncaught exception handler */
-static LFUncaughtExceptionHandler *ueh_handler;
-static slock_t ueh_lock;
-
-/* Expose our exception stack functions */
-#if defined APPLE_RUNTIME
-/*!
- * Exception handling functions for the Apple Objective-C runtime.
- * @internal
- */
-objc_exception_functions_t objc_exc_funcs = {
- 0,
- LFObjC_ExceptionThrow,
- LFObjC_ExceptionTryEnter,
- LFObjC_ExceptionTryExit,
- LFObjC_ExceptionExtract,
- LFObjC_ExceptionMatch
-};
-#endif /* APPLE_RUNTIME */
-
-void _NSAddHandler (LFObjCLocalExceptionData *excData) {
- LFObjC_ExceptionTryEnter(excData);
-}
-
-void _NSRemoveHandler (LFObjCLocalExceptionData *excData) {
- LFObjC_ExceptionTryExit(excData);
-}
-
-NSException *_NSExceptionFromHandler (LFObjCLocalExceptionData *excData) {
- return LFObjC_ExceptionExtract(excData);
-}
-
-/*!
- * Set Objective-C Uncaught Exception Handler.
- * @internal
- */
-LF_PRIVATE void LFObjCSetUncaughtExceptionHandler (LFUncaughtExceptionHandler *handler) {
- SpinLockAcquire(&ueh_lock);
- ueh_handler = handler;
- SpinLockRelease(&ueh_lock);
-}
-
-/*!
- * Get Objective-C Uncaught Exception Handler.
- * @internal
- */
-LF_PRIVATE LFUncaughtExceptionHandler *LFObjCGetUncaughtExceptionHandler (void) {
- LFUncaughtExceptionHandler *handler;
- SpinLockAcquire(&ueh_lock);
- handler = ueh_handler;
- SpinLockRelease(&ueh_lock);
-
- return handler;
-}
-
-/*!
- * Initialize the Objective-C Exception Handler.
- * @internal
- */
-LF_PRIVATE void LFObjCInitExceptionHandler (LFUncaughtExceptionHandler *handler) {
- /* Initialize the lock */
- SpinLockInit(&ueh_lock);
- ueh_handler = handler;
-
- /* Initialize our pthread key */
- pthread_key_create(&LFExceptionHandlerStack_key, free_exception_handler_stack_tls);
-
-#if defined(APPLE_RUNTIME) && defined(OBJC_EXCEPTIONS)
- /* Set up exception handling functions for the Apple runtime */
- objc_exception_set_functions((objc_exception_functions_t *) &objc_exc_funcs);
-#endif
-}
-
-/*!
- * Throw an exception.
- * @internal
- */
-LF_PRIVATE void LFObjC_ExceptionThrow (id exception) {
- LFExceptionHandler_TLS *ehsTLS;
- LFObjCLocalExceptionData *lfexcData;
- LFExceptionHandlerBucket *bucket;
-
- /* Grab the stack */
- ehsTLS = (LFExceptionHandler_TLS *) pthread_getspecific(LFExceptionHandlerStack_key);
-
- /* If the stack is NULL or the bucket is empty, someone forgot to catch
- * the exception. Call the uncaught exception handler and fire SIGTRAP */
- if (!ehsTLS || !ehsTLS->bucket || ehsTLS->bucket->count == 0) {
- LFUncaughtExceptionHandler *handler;
-
- /* Acquire a lock and get the current ueh_handler */
- SpinLockAcquire(&ueh_lock);
- handler = ueh_handler;
- SpinLockRelease(&ueh_lock);
-
- /* Call and then fire SIGTRAP */
- handler(exception);
- kill(getpid(), SIGTRAP);
- }
-
- /* Pop our exception data */
- bucket = ehsTLS->bucket;
- assert(bucket);
- lfexcData = bucket->excData[bucket->count - 1];
- assert(lfexcData);
- bucket->count--;
-
- /* Store the exception in the first pointer */
- lfexcData->pointers[0] = (void *) exception;
-
- /* On my mark. */
- _longjmp(lfexcData->buf, 1);
-}
-
-/*!
- * Enter a @try/@catch block.
- * @internal
- */
-static void LFObjC_ExceptionTryEnter (void *excData) {
- LFExceptionHandler_TLS *ehsTLS;
- LFExceptionHandlerBucket *new, *bucket;
-
- /* Grab the stack */
- ehsTLS = (LFExceptionHandler_TLS *) pthread_getspecific(LFExceptionHandlerStack_key);
-
- /* Allocate and initialize the stack TLS holder if needed */
- if (!ehsTLS) {
- ehsTLS = NSZoneMalloc(NULL, sizeof(LFExceptionHandler_TLS));
- ehsTLS->bucket = NULL;
- pthread_setspecific(LFExceptionHandlerStack_key, ehsTLS);
- }
-
- /* Allocate and initialize a bucket if needed */
- if (!ehsTLS->bucket || ehsTLS->bucket->count == EHS_BUCKET_SIZE) {
- new = NSZoneMalloc(NULL, sizeof(LFExceptionHandlerBucket));
-
- /* Will either get set to NULL or the next bucket */
- new->next = ehsTLS->bucket;
- new->count = 0;
-
- ehsTLS->bucket = new;
- }
-
- /* Add our data to the bucket */
- bucket = ehsTLS->bucket;
- bucket->excData[bucket->count] = excData;
- bucket->count++;
-
- return;
-}
-
-/*!
- * Exit a @try/@catch block.
- * @internal
- */
-static void LFObjC_ExceptionTryExit (void *excData) {
- LFExceptionHandler_TLS *ehsTLS;
- LFExceptionHandlerBucket *bucket;
-
- /* Grab the stack */
- ehsTLS = (LFExceptionHandler_TLS *) pthread_getspecific(LFExceptionHandlerStack_key);
- assert(ehsTLS);
-
- /* Decrease the bucket count (ie, pop the excData) */
- bucket = ehsTLS->bucket;
- assert(bucket->excData[bucket->count - 1] == excData);
- bucket->count--;
-
- /* If the bucket is empty, and this isn't the last bucket available,
- * free the current bucket. */
- if (bucket->count == 0 && bucket->next != NULL) {
- ehsTLS->bucket = bucket->next;
- NSZoneFree(NULL, bucket);
- }
-
- return;
-}
-
-/*!
- * Extract the Objective-C object from the local exception data.
- * @internal
- */
-static id LFObjC_ExceptionExtract (void *excData) {
- LFObjCLocalExceptionData *lfexcData = (LFObjCLocalExceptionData *) excData;
- /* We stored the exception in the first pointer */
- return (id) lfexcData->pointers[0];
-}
-
-/*!
- * Match a given exception against the supplied class.
- * @internal
- */
-static int LFObjC_ExceptionMatch (Class excClass, id exception) {
- return [exception isKindOfClass: excClass];
-}
-
-/*!
- * Deallocate the exception stack TLS.
- * @internal
- */
-static void free_exception_handler_stack_tls (void *keyData) {
- LFExceptionHandler_TLS *ehsTLS = (LFExceptionHandler_TLS *) keyData;
-
- /* There will only ever be one bucket left behind by LFObjC_ExceptionTryExit() */
- if (ehsTLS->bucket)
- NSZoneFree(NULL, ehsTLS->bucket);
-
- NSZoneFree(NULL, ehsTLS);
-}
-
-#endif /* APPLE_RUNTIME || (GNU_RUNTIME && !OBJC_EXCEPTIONS) */
Deleted: trunk/Foundation/LFObjCGNUException.m
===================================================================
--- trunk/Foundation/LFObjCGNUException.m 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Foundation/LFObjCGNUException.m 2006-08-31 22:26:28 UTC (rev 282)
@@ -1,160 +0,0 @@
-/*
- * LFObjCGNUException.m vi:ts=4:sw=4:expandtab:
- * New-style language exception handling for the GNU Objective-C runtime.
- *
- * Copyright (C) 2005 - 2006 Landon Fuller <la...@op...>
- * All rights reserved.
- *
- * Author: Landon Fuller <la...@op...>
- *
- * This file is part of libFoundation.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation.
- *
- * We disclaim all warranties with regard to this software, including all
- * implied warranties of merchantability and fitness, in no event shall
- * we be liable for any special, indirect or consequential damages or any
- * damages whatsoever resulting from loss of use, data or profits, whether in
- * an action of contract, negligence or other tortious action, arising out of
- * or in connection with the use or performance of this software.
- */
-
-/*!
- * @file
- * @internal
- * @brief LFObjCRuntime
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(GNU_RUNTIME) && defined(LF_OBJC_LANGUAGE_EXCEPTIONS)
-
-/* This is unfortunately required to use RTLD_NEXT on Linux systems */
-#define _GNU_SOURCE
-
-#include <Foundation/NSZone.h>
-#include <Foundation/NSException.h>
-#include <Foundation/LFObjCRuntime.h>
-#include <Foundation/spin.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <signal.h>
-
-# include <dlfcn.h>
-/* GCC's exception handling and stack unwinding routines */
-# include <unwind.h>
-
-/* Uncaught exception handler */
-static LFUncaughtExceptionHandler *ueh_handler;
-static slock_t ueh_lock;
-
-/*! libgcc's _Unwind_RaiseException()
- * @internal */
-static _Unwind_Reason_Code (*_real_Unwind_RaiseException)(struct _Unwind_Exception *e);
-
-/*!
- * Set Objective-C Uncaught Exception Handler.
- * @internal
- */
-LF_PRIVATE void LFObjCSetUncaughtExceptionHandler (LFUncaughtExceptionHandler *handler) {
- SpinLockAcquire(&ueh_lock);
- ueh_handler = handler;
- SpinLockRelease(&ueh_lock);
-}
-
-/*!
- * Get Objective-C Uncaught Exception Handler.
- * @internal
- */
-LF_PRIVATE LFUncaughtExceptionHandler *LFObjCGetUncaughtExceptionHandler (void) {
- LFUncaughtExceptionHandler *handler;
- SpinLockAcquire(&ueh_lock);
- handler = ueh_handler;
- SpinLockRelease(&ueh_lock);
-
- return handler;
-}
-
-/*!
- * Initialize the Objective-C Exception Handler.
- * @internal
- */
-LF_PRIVATE void LFObjCInitExceptionHandler (LFUncaughtExceptionHandler *handler) {
- /* Initialize the lock */
- SpinLockInit(&ueh_lock);
- ueh_handler = handler;
-
-#ifdef RTLD_NEXT
- /* Locate the _Unwind_RaiseException symbol */
- _real_Unwind_RaiseException = dlsym(RTLD_NEXT, "_Unwind_RaiseException");
-#endif /* RTLD_NEXT */
-
-}
-
-/*!
- * Throw an exception.
- * @internal
- */
-LF_PRIVATE void LFObjC_ExceptionThrow (id exception) {
- @throw exception;
-}
-
-/******************************************************************************
- * XXX: Temporary Hack.
- *
- * When using the GNU Objective-C runtime, support for a default
- * Objective-C exception handler is implemented by overriding gcc's
- * _Unwind_RaiseException, calling the true _Unwind_RaiseException,
- * and checking for _URC_END_OF_STACK, which signals that no exception
- * handler was found.
- *
- * This is wrong, wrong, wrong, (really wrong!), but there is currently
- * no other way to implement this functionality.
- *
- * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27466 for my libobjc
- * enhancement request.
- ******************************************************************************/
-
-/*! Our _Unwind_RaiseException()
- * @internal */
-_Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *uwe) {
- _Unwind_Reason_Code err;
-
- err = _real_Unwind_RaiseException(uwe);
- if (err == _URC_END_OF_STACK) {
- LFUncaughtExceptionHandler *handler;
-
- /* Acquire a lock and get the current ueh_handler */
- SpinLockAcquire(&ueh_lock);
- handler = ueh_handler;
- SpinLockRelease(&ueh_lock);
-
- /* If a handler is available, call it.
- * We manually re-raise the _Unwind_Exception so that we can get
- * access to the thrown Objective-C object without digging
- * into the private libobjc structures */
- @try {
- _real_Unwind_RaiseException(uwe);
- }
- @catch (id exc) {
- ueh_handler(exc);
- }
- }
-
- /* Fire SIGTRAP */
- kill(getpid(), SIGTRAP);
-
- /* We're going to return objc_exception_throw(), where abort() will be
- * called immediately. Unless someone caught SIGTRAP, this should
- * be unreachable */
- return err;
-}
-
-#endif /* GNU_RUNTIME && LF_OBJC_LANGUAGE_EXCEPTIONS */
Modified: trunk/Foundation/LFObjCRuntime.h.in
===================================================================
--- trunk/Foundation/LFObjCRuntime.h.in 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Foundation/LFObjCRuntime.h.in 2006-08-31 22:26:28 UTC (rev 282)
@@ -89,6 +89,10 @@
#ifdef LF_SPI
+/*
+ * Runtime-specific Exception Handling
+ */
+
/*!
* Uncaught exception handler function type.
* Mirrors NSUncaughtExceptionHandler.
@@ -114,12 +118,6 @@
*/
LF_PRIVATE LFUncaughtExceptionHandler *LFObjCGetUncaughtExceptionHandler (void);
-/*!
- * Throw an exception.
- * @internal
- */
-LF_PRIVATE void LFObjC_ExceptionThrow (id exception);
-
#endif /* LF_SPI */
#if defined(GNU_RUNTIME)
Added: trunk/Foundation/LFStackException.m
===================================================================
--- trunk/Foundation/LFStackException.m (rev 0)
+++ trunk/Foundation/LFStackException.m 2006-08-31 22:26:28 UTC (rev 282)
@@ -0,0 +1,314 @@
+/*
+ * LFObjCExceptionStack.m vi:ts=4:sw=4:expandtab:
+ *
+ * Generic Exception Stack Implementation.
+ * Compatible with both new-style language exceptions as implemented by
+ * the Apple runtime, and old-style NS_DURING exceptions in both runtimes.
+ *
+ * Copyright (C) 2005 - 2006 Landon Fuller <la...@op...>
+ * All rights reserved.
+ *
+ * Author: Landon Fuller <la...@op...>
+ *
+ * This file is part of libFoundation.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.
+ *
+ * We disclaim all warranties with regard to this software, including all
+ * implied warranties of merchantability and fitness, in no event shall
+ * we be liable for any special, indirect or consequential damages or any
+ * damages whatsoever resulting from loss of use, data or profits, whether in
+ * an action of contract, negligence or other tortious action, arising out of
+ * or in connection with the use or performance of this software.
+ */
+
+/*!
+ * @file
+ * @internal
+ * @brief LFObjCRuntime
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(APPLE_RUNTIME) || (defined(GNU_RUNTIME) && !defined(OBJC_EXCEPTIONS))
+
+/******************************************************************************
+ * This code implementions binary-compatible exception handling for both
+ * new and old-style exceptions in the Apple Objective-C runtime.
+ *
+ * It also implements non-binary compatible exception handling support for
+ * old-style exceptions in GNU's Objective-C runtime.
+ *
+ * We maintain a per-thread stack of exception handlers. Handlers are pushed
+ * and popped off the stack at the beginning and end of every try/catch block,
+ * via a runtime function call. When an exception occurs, our
+ * LFObjC_ExceptionThrow() function is called, and we need to longjmp to the
+ * current exception handler at the top of the per-thread handler stack.
+ *
+ * The push/pop runtime function calls are handled automatically by the
+ * new-style exception support in Apple's runtime. With old-style exceptions,
+ * we manually implement the equivalent using preprocessor macros.
+ *****************************************************************************/
+
+#include <Foundation/NSZone.h>
+#include <Foundation/NSException.h>
+#include <Foundation/LFObjCRuntime.h>
+#include <Foundation/spin.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <setjmp.h>
+
+/* Number of exception handlers to store in each bucket.
+ * Selected arbitrarily. */
+#define EHS_BUCKET_SIZE 16
+
+/* Forward declarations */
+static void LFObjC_ExceptionThrow (id);
+static void LFObjC_ExceptionTryEnter (void *);
+static void LFObjC_ExceptionTryExit (void *);
+static id LFObjC_ExceptionExtract (void *);
+static int LFObjC_ExceptionMatch (Class, id);
+static void free_exception_handler_stack_tls (void *);
+
+/* Per-thread stack of exception handler buckets, each bucket
+ * holds EHS_BUCKET_SIZE handlers */
+typedef struct LFExceptionHandlerBucket {
+ int count;
+ LFObjCLocalExceptionData *excData[EHS_BUCKET_SIZE];
+ struct LFExceptionHandlerBucket *next;
+} LFExceptionHandlerBucket;
+
+/* We modify the pointer in this structure so that we don't
+ * have to call pthread_setspecific() repeatedly */
+typedef struct LFExceptionHandler_TLS {
+ LFExceptionHandlerBucket *bucket;
+} LFExceptionHandler_TLS;
+
+/* Per-thread EH stack key */
+static pthread_key_t LFExceptionHandlerStack_key;
+
+/* Uncaught exception handler */
+static LFUncaughtExceptionHandler *ueh_handler;
+static slock_t ueh_lock;
+
+/* Expose our exception stack functions */
+#if defined APPLE_RUNTIME
+/*!
+ * Exception handling functions for the Apple Objective-C runtime.
+ * @internal
+ */
+objc_exception_functions_t objc_exc_funcs = {
+ 0,
+ LFObjC_ExceptionThrow,
+ LFObjC_ExceptionTryEnter,
+ LFObjC_ExceptionTryExit,
+ LFObjC_ExceptionExtract,
+ LFObjC_ExceptionMatch
+};
+#endif /* APPLE_RUNTIME */
+
+void _NSAddHandler (LFObjCLocalExceptionData *excData) {
+ LFObjC_ExceptionTryEnter(excData);
+}
+
+void _NSRemoveHandler (LFObjCLocalExceptionData *excData) {
+ LFObjC_ExceptionTryExit(excData);
+}
+
+NSException *_NSExceptionObjectFromHandler (LFObjCLocalExceptionData *excData) {
+ return LFObjC_ExceptionExtract(excData);
+}
+
+LF_PRIVATE void _NSExceptionThrow (id e) {
+ LFObjC_ExceptionThrow(e);
+}
+
+/*!
+ * Set Objective-C Uncaught Exception Handler.
+ * @internal
+ */
+LF_PRIVATE void LFObjCSetUncaughtExceptionHandler (LFUncaughtExceptionHandler *handler) {
+ SpinLockAcquire(&ueh_lock);
+ ueh_handler = handler;
+ SpinLockRelease(&ueh_lock);
+}
+
+/*!
+ * Get Objective-C Uncaught Exception Handler.
+ * @internal
+ */
+LF_PRIVATE LFUncaughtExceptionHandler *LFObjCGetUncaughtExceptionHandler (void) {
+ LFUncaughtExceptionHandler *handler;
+ SpinLockAcquire(&ueh_lock);
+ handler = ueh_handler;
+ SpinLockRelease(&ueh_lock);
+
+ return handler;
+}
+
+/*!
+ * Initialize the Objective-C Exception Handler.
+ * @internal
+ */
+LF_PRIVATE void LFObjCInitExceptionHandler (LFUncaughtExceptionHandler *handler) {
+ /* Initialize the lock */
+ SpinLockInit(&ueh_lock);
+ ueh_handler = handler;
+
+ /* Initialize our pthread key */
+ pthread_key_create(&LFExceptionHandlerStack_key, free_exception_handler_stack_tls);
+
+#if defined(APPLE_RUNTIME) && defined(OBJC_EXCEPTIONS)
+ /* Set up exception handling functions for the Apple runtime */
+ objc_exception_set_functions((objc_exception_functions_t *) &objc_exc_funcs);
+#endif
+}
+
+/*!
+ * Throw an exception.
+ * @internal
+ */
+LF_PRIVATE void LFObjC_ExceptionThrow (id exception) {
+ LFExceptionHandler_TLS *ehsTLS;
+ LFObjCLocalExceptionData *lfexcData;
+ LFExceptionHandlerBucket *bucket;
+
+ /* Grab the stack */
+ ehsTLS = (LFExceptionHandler_TLS *) pthread_getspecific(LFExceptionHandlerStack_key);
+
+ /* If the stack is NULL or the bucket is empty, someone forgot to catch
+ * the exception. Call the uncaught exception handler and fire SIGTRAP */
+ if (!ehsTLS || !ehsTLS->bucket || ehsTLS->bucket->count == 0) {
+ LFUncaughtExceptionHandler *handler;
+
+ /* Acquire a lock and get the current ueh_handler */
+ SpinLockAcquire(&ueh_lock);
+ handler = ueh_handler;
+ SpinLockRelease(&ueh_lock);
+
+ /* Call and then fire SIGTRAP */
+ handler(exception);
+ kill(getpid(), SIGTRAP);
+ }
+
+ /* Pop our exception data */
+ bucket = ehsTLS->bucket;
+ assert(bucket);
+ lfexcData = bucket->excData[bucket->count - 1];
+ assert(lfexcData);
+ bucket->count--;
+
+ /* Store the exception in the first pointer */
+ lfexcData->pointers[0] = (void *) exception;
+
+ /* On my mark. */
+ _longjmp(lfexcData->buf, 1);
+}
+
+/*!
+ * Enter a @try/@catch block.
+ * @internal
+ */
+static void LFObjC_ExceptionTryEnter (void *excData) {
+ LFExceptionHandler_TLS *ehsTLS;
+ LFExceptionHandlerBucket *new, *bucket;
+
+ /* Grab the stack */
+ ehsTLS = (LFExceptionHandler_TLS *) pthread_getspecific(LFExceptionHandlerStack_key);
+
+ /* Allocate and initialize the stack TLS holder if needed */
+ if (!ehsTLS) {
+ ehsTLS = NSZoneMalloc(NULL, sizeof(LFExceptionHandler_TLS));
+ ehsTLS->bucket = NULL;
+ pthread_setspecific(LFExceptionHandlerStack_key, ehsTLS);
+ }
+
+ /* Allocate and initialize a bucket if needed */
+ if (!ehsTLS->bucket || ehsTLS->bucket->count == EHS_BUCKET_SIZE) {
+ new = NSZoneMalloc(NULL, sizeof(LFExceptionHandlerBucket));
+
+ /* Will either get set to NULL or the next bucket */
+ new->next = ehsTLS->bucket;
+ new->count = 0;
+
+ ehsTLS->bucket = new;
+ }
+
+ /* Add our data to the bucket */
+ bucket = ehsTLS->bucket;
+ bucket->excData[bucket->count] = excData;
+ bucket->count++;
+
+ return;
+}
+
+/*!
+ * Exit a @try/@catch block.
+ * @internal
+ */
+static void LFObjC_ExceptionTryExit (void *excData) {
+ LFExceptionHandler_TLS *ehsTLS;
+ LFExceptionHandlerBucket *bucket;
+
+ /* Grab the stack */
+ ehsTLS = (LFExceptionHandler_TLS *) pthread_getspecific(LFExceptionHandlerStack_key);
+ assert(ehsTLS);
+
+ /* Decrease the bucket count (ie, pop the excData) */
+ bucket = ehsTLS->bucket;
+ assert(bucket->excData[bucket->count - 1] == excData);
+ bucket->count--;
+
+ /* If the bucket is empty, and this isn't the last bucket available,
+ * free the current bucket. */
+ if (bucket->count == 0 && bucket->next != NULL) {
+ ehsTLS->bucket = bucket->next;
+ NSZoneFree(NULL, bucket);
+ }
+
+ return;
+}
+
+/*!
+ * Extract the Objective-C object from the local exception data.
+ * @internal
+ */
+static id LFObjC_ExceptionExtract (void *excData) {
+ LFObjCLocalExceptionData *lfexcData = (LFObjCLocalExceptionData *) excData;
+ /* We stored the exception in the first pointer */
+ return (id) lfexcData->pointers[0];
+}
+
+/*!
+ * Match a given exception against the supplied class.
+ * @internal
+ */
+static int LFObjC_ExceptionMatch (Class excClass, id exception) {
+ return [exception isKindOfClass: excClass];
+}
+
+/*!
+ * Deallocate the exception stack TLS.
+ * @internal
+ */
+static void free_exception_handler_stack_tls (void *keyData) {
+ LFExceptionHandler_TLS *ehsTLS = (LFExceptionHandler_TLS *) keyData;
+
+ /* There will only ever be one bucket left behind by LFObjC_ExceptionTryExit() */
+ if (ehsTLS->bucket)
+ NSZoneFree(NULL, ehsTLS->bucket);
+
+ NSZoneFree(NULL, ehsTLS);
+}
+
+#endif /* APPLE_RUNTIME || (GNU_RUNTIME && !OBJC_EXCEPTIONS) */
Property changes on: trunk/Foundation/LFStackException.m
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/Foundation/Makefile.in
===================================================================
--- trunk/Foundation/Makefile.in 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Foundation/Makefile.in 2006-08-31 22:26:28 UTC (rev 282)
@@ -45,8 +45,8 @@
NSUnicodeString.m \
NSSimpleCString.m \
NSZone.m \
- LFObjCExceptionStack.m \
- LFObjCGNUException.m \
+ LFStackException.m \
+ LFGNUException.m \
LFHash.c \
s_lock.c \
$(TAS_SRC)
@@ -64,8 +64,8 @@
NSUnicodeString.o \
NSSimpleCString.o \
NSZone.o \
- LFObjCExceptionStack.o \
- LFObjCGNUException.o \
+ LFStackException.o \
+ LFGNUException.o \
LFHash.o \
s_lock.o \
$(TAS_OBJS)
Modified: trunk/Foundation/NSConcreteData.m
===================================================================
--- trunk/Foundation/NSConcreteData.m 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Foundation/NSConcreteData.m 2006-08-31 22:26:28 UTC (rev 282)
@@ -89,13 +89,12 @@
/* Try to instantiate new object -- on failure,
* release our malloc'd buffer and rethrow
* the exception */
- @try {
+ NS_DURING
[self getBytes: buffer range: range];
- }
- @catch (id e) {
+ NS_HANDLER
NSZoneFree(NULL, buffer);
- LFObjC_ExceptionThrow(e);
- }
+ [localException raise];
+ NS_ENDHANDLER
/* Instantiated NSData instances will free buffer upon deallocation */
return [NSData dataWithBytesNoCopy: buffer length: range.length];
Modified: trunk/Foundation/NSException.h
===================================================================
--- trunk/Foundation/NSException.h 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Foundation/NSException.h 2006-08-31 22:26:28 UTC (rev 282)
@@ -34,6 +34,7 @@
#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
+#include <Foundation/NSObjCRuntime.h>
#include <stdarg.h>
#include <setjmp.h>
@@ -83,8 +84,8 @@
*/
typedef void NSUncaughtExceptionHandler (NSException *exception);
-void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *handler);
-NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void);
+LF_EXPORT void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *handler);
+LF_EXPORT NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void);
/*
* Exception handling for the Apple runtime, and old-style exceptions
@@ -101,18 +102,20 @@
void *pointers[4]; /* The exception is stored in the first pointer */
} LFObjCLocalExceptionData;
-void _NSAddHandler (LFObjCLocalExceptionData *excData);
-void _NSRemoveHandler (LFObjCLocalExceptionData *excData);
-NSException *_NSExceptionFromHandler (LFObjCLocalExceptionData *excData);
+LF_EXPORT void _NSAddHandler (LFObjCLocalExceptionData *excData);
+LF_EXPORT void _NSRemoveHandler (LFObjCLocalExceptionData *excData);
+LF_EXPORT NSException *_NSExceptionObjectFromHandler (LFObjCLocalExceptionData *excData);
+void _NSExceptionThrow (id e);
-#ifdef LF_OBJC_LANGUAGE_EXCEPTIONS
/* New-style Exception Handling */
+#ifdef OBJC_EXCEPTIONS
# define NS_DURING @try {
# define NS_HANDLER } @catch (NSException *localException) {
# define NS_ENDHANDLER }
# define NS_VALUERETURN(val, type) return (val);
# define NS_VOIDRETURN return;
#else
+
/* Old-style Exception Handling */
# define NS_DURING { \
LFObjCLocalExceptionData _localHandler; \
@@ -122,7 +125,7 @@
#define NS_HANDLER \
_NSRemoveHandler(&_localHandler); \
} else { \
- NSException *localException = _NSExceptionFromHandler(&_localHandler);
+ NSException *localException = _NSExceptionObjectFromHandler(&_localHandler);
#define NS_ENDHANDLER \
localException = nil; /* Avoid compiler warning */ \
@@ -137,7 +140,6 @@
_NSRemoveHandler(&_localHandler); \
return; \
}
+#endif /* !OBJC_EXCEPTIONS */
-#endif /* !LF_OBJC_LANGUAGE_EXCEPTIONS */
-
#endif /* __NSException_h__ */
Modified: trunk/Foundation/NSException.m
===================================================================
--- trunk/Foundation/NSException.m 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Foundation/NSException.m 2006-08-31 22:26:28 UTC (rev 282)
@@ -245,7 +245,11 @@
* Raise the receiver.
*/
- (void) raise {
- LFObjC_ExceptionThrow(self);
+#ifdef OBJC_EXCEPTIONS
+ @throw self;
+#else
+ _NSExceptionThrow(self);
+#endif
}
Modified: trunk/Foundation/port.h
===================================================================
--- trunk/Foundation/port.h 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Foundation/port.h 2006-08-31 22:26:28 UTC (rev 282)
@@ -31,16 +31,16 @@
#endif
#ifndef HAVE_SRANDOM
-LF_PRIVATE void srandom(unsigned int seed);
+void srandom(unsigned int seed);
#endif
#ifndef HAVE_RANDOM
-LF_PRIVATE long random(void);
+long random(void);
#endif
#ifndef HAVE_LRAND48
-LF_PRIVATE long lrand48(void);
-LF_PRIVATE long srand48(long seed);
+long lrand48(void);
+long srand48(long seed);
#endif
#endif /* PORT_H */
Modified: trunk/Mk/autoconf.mk.in
===================================================================
--- trunk/Mk/autoconf.mk.in 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/Mk/autoconf.mk.in 2006-08-31 22:26:28 UTC (rev 282)
@@ -17,6 +17,7 @@
OBJC_LIBS = @OBJC_LIBS@
OBJC_NSCONSTANTSTRING_CFLAGS = @OBJC_NSCONSTANTSTRING_CFLAGS@
OBJC_EXCEPTIONS_CFLAGS = @OBJC_EXCEPTIONS_CFLAGS@
+OBJC_EXCEPTIONS_DEFINE = @OBJC_EXCEPTIONS_DEFINE@
OBJC_NOCFCONSTANTSTRING_CFLAGS = @OBJC_NOCFCONSTANTSTRING_CFLAGS@
ICU_CFLAGS = @ICU_CFLAGS@
Modified: trunk/aclocal.m4
===================================================================
--- trunk/aclocal.m4 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/aclocal.m4 2006-08-31 22:26:28 UTC (rev 282)
@@ -301,7 +301,7 @@
#------------------------------------------------------------------------
# OD_OBJC_EXCEPTIONS --
#
-# Check if -fobjc-exceptions is supported
+# If enabled, use Obj-C exceptions (-fobjc-exceptions)
#
# Arguments:
# None.
@@ -312,13 +312,16 @@
#
# Results:
# Result is cached.
-# If supported, OBJC_EXCEPTIONS_CFLAGS is substituted
+# Substitutes OBJC_EXCEPTIONS_DEFINE and OBJC_EXCEPTIONS_CFLAGS
+# If enabled, OBJC_EXCEPTIONS is defined to 1.
#------------------------------------------------------------------------
AC_DEFUN([OD_OBJC_EXCEPTIONS],[
AC_REQUIRE([AC_PROG_OBJC])
AC_LANG_PUSH([Objective C])
+ AC_ARG_ENABLE([objc-exceptions], AC_HELP_STRING([--enable-objc-exceptions], [Enable runtime support for Objective-C language exceptions. New-style language exceptions are not binary-compatible with old-style exception handling when using the GNU runtime. Defaults to yes.]), [ac_cv_objc_exceptions=$enableval], [ac_cv_objc_exceptions=yes])
+
AC_MSG_CHECKING([if Objective-C compiler supports -fobjc-exceptions])
AC_CACHE_VAL(ac_cv_objc_fobjc_exceptions, [
OBJCFLAGS_OLD="${OBJCFLAGS}"
@@ -335,13 +338,22 @@
])
AC_MSG_RESULT(${ac_cv_objc_fobjc_exceptions})
- if test x"$ac_cv_objc_fobjc_exceptions" = "xyes"; then
+ # Can we even enable exceptions?
+ if test x"$ac_cv_objc_exceptions" = "xyes" && test x"$ac_cv_objc_fobc_exceptions" = "xno"; then
+ AC_MSG_WARN([Objective-C exception support requires gcc 4.0 or later. Using old-style exceptions instead. If you are using the GNU runtime and later upgrade to gcc 4.0, old-style exceptions are NOT binary compatible with new-style Objective-C exceptions.])
+ fi
+
+ # If we can enable exceptions, do we want to?
+ if test x"$ac_cv_objc_exceptions" = "xyes" && test x"$ac_cv_objc_fobjc_exceptions" = "xyes"; then
OBJC_EXCEPTIONS_CFLAGS="-fobjc-exceptions"
+ OBJC_EXCEPTIONS_DEFINE="#define OBJC_EXCEPTIONS 1"
else
- AC_MSG_ERROR([Objective-C exception support is required. You will need to upgrade your GNU Objective-C compiler to 4.0 or later.])
+ OBJC_EXCEPTIONS_CFLAGS=""
+ OBJC_EXCEPTIONS_DEFINE=""
fi
AC_SUBST([OBJC_EXCEPTIONS_CFLAGS])
+ AC_SUBST([OBJC_EXCEPTIONS_DEFINE])
AC_LANG_POP([Objective C])
])
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2006-08-31 22:26:13 UTC (rev 281)
+++ trunk/configure.ac 2006-08-31 22:26:28 UTC (rev 282)
@@ -59,6 +59,11 @@
OD_OBJC_EXCEPTIONS
# Check whether -fno-constant-cfstrings is supported
OD_OBJC_NOCFCONSTANTSTRING
+if test x"$OBJC_EXCEPTIONS_DEFINE" != "x"; then
+ AC_MSG_NOTICE([Objective-C exception handling: @try @catch @throw])
+else
+ AC_MSG_NOTICE([Exception handling: NS_DURING NS_HANDLER])
+fi
AC_CACHE_SAVE
# Headers
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|