Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -282,10 +282,14 @@ AC_CHECK_FUNC(objc_enumerationMutation, [ AC_DEFINE(HAVE_OBJC_ENUMERATIONMUTATION, 1, [Whether we have objc_enumerationMutation]) ]) + +AC_CHECK_FUNC(objc_autoreleasePoolPush, [], [ + AC_SUBST(AUTORELEASE_M, "autorelease.m") +]) case "$host_os" in darwin*) AC_SUBST(LDFLAGS_REEXPORT, ["-Wl,-reexport-lobjfw"]) AS_IF([test x"$objc_runtime" = x"Apple runtime"], [ Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -3,10 +3,11 @@ OBJFW_LIB_MAJOR = 6 OBJFW_LIB_MINOR = 0 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} ASPRINTF_M = @ASPRINTF_M@ +AUTORELEASE_M = @AUTORELEASE_M@ ATOMIC_H = @ATOMIC_H@ BIN_PREFIX = @BIN_PREFIX@ EXCEPTIONS_A = @EXCEPTIONS_A@ EXCEPTIONS_EXCEPTIONS_A = @EXCEPTIONS_EXCEPTIONS_A@ EXCEPTIONS_EXCEPTIONS_LIB_A = @EXCEPTIONS_EXCEPTIONS_LIB_A@ Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -92,10 +92,11 @@ ${OFSTREAMOBSERVER_POLL_M} \ ${OFSTREAMOBSERVER_SELECT_M} \ OFString_UTF8.m \ OFTCPSocket+SOCKS5.m \ ${ASPRINTF_M} \ + ${AUTORELEASE_M} \ ${FOUNDATION_COMPAT_M} \ iso_8859_15.m \ windows_1252.m OBJS_EXTRA = ${EXCEPTIONS_EXCEPTIONS_A} ${RUNTIME_RUNTIME_A} ADDED src/autorelease.m Index: src/autorelease.m ================================================================== --- src/autorelease.m +++ src/autorelease.m @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include +#include + +#import "OFObject.h" + +#ifndef OF_COMPILER_TLS +# import "threading.h" +#endif +#import "macros.h" + +#ifdef OF_COMPILER_TLS +static __thread id *objects = NULL; +static __thread id *top = NULL; +static __thread size_t size = 0; +#else +static of_tlskey_t objectsKey, topKey, sizeKey; + +static void __attribute__((constructor)) +init(void) +{ + OF_ENSURE(of_tlskey_new(&objectsKey)); + OF_ENSURE(of_tlskey_new(&sizeKey)); + OF_ENSURE(of_tlskey_new(&topKey)); +} +#endif + +id +objc_autorelease(id object) +{ + return [object autorelease]; +} + +void* +objc_autoreleasePoolPush() +{ +#ifndef OF_COMPILER_TLS + id *top = of_tlskey_get(topKey); + id *objects = of_tlskey_get(objectsKey); +#endif + ptrdiff_t offset = top - objects; + + return (void*)offset; +} + +void +objc_autoreleasePoolPop(void *offset) +{ +#ifndef OF_COMPILER_TLS + id *top = of_tlskey_get(topKey); + id *objects = of_tlskey_get(objectsKey); +#endif + id *pool = objects + (ptrdiff_t)offset; + id *iter; + + for (iter = pool; iter < top; iter++) + [*iter release]; + + top = pool; + + if (top == objects) { + free(objects); + + objects = NULL; + top = NULL; + } + +#ifndef OF_COMPILER_TLS + OF_ENSURE(of_tlskey_set(objectsKey, objects)); + OF_ENSURE(of_tlskey_set(topKey, top)); +#endif +} + +id +_objc_rootAutorelease(id object) +{ +#ifndef OF_COMPILER_TLS + id *top = of_tlskey_get(topKey); + id *objects = of_tlskey_get(objectsKey); + size_t size = (size_t)(uintptr_t)of_tlskey_get(sizeKey); +#endif + + if (objects == NULL) { + OF_ENSURE((objects = malloc(of_pagesize)) != NULL); + +#ifndef OF_COMPILER_TLS + OF_ENSURE(of_tlskey_set(objectsKey, objects)); + OF_ENSURE(of_tlskey_set(sizeKey, + (void*)(uintptr_t)of_pagesize)); +#endif + + top = objects; + size = of_pagesize; + } + + if ((uintptr_t)top >= (uintptr_t)objects + size) { + ptrdiff_t diff = top - objects; + + size += of_pagesize; + OF_ENSURE((objects = realloc(objects, size)) != NULL); + +#ifndef OF_COMPILER_TLS + OF_ENSURE(of_tlskey_set(objectsKey, objects)); + OF_ENSURE(of_tlskey_set(sizeKey, (void*)(uintptr_t)size)); +#endif + + top = objects + diff; + } + + *top = object; + top++; + +#ifndef OF_COMPILER_TLS + OF_ENSURE(of_tlskey_set(topKey, objects)); +#endif + + return object; +} Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -1,12 +1,11 @@ include ../../extra.mk STATIC_PIC_LIB_NOINST = ${RUNTIME_LIB_A} STATIC_LIB_NOINST = ${RUNTIME_A} -SRCS = autorelease.m \ - category.m \ +SRCS = category.m \ class.m \ exception.m \ hashtable.m \ init.m \ lookup.m \ DELETED src/runtime/autorelease.m Index: src/runtime/autorelease.m ================================================================== --- src/runtime/autorelease.m +++ src/runtime/autorelease.m @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include -#include - -#import "runtime.h" -#import "runtime-private.h" - -#import "OFObject.h" - -#ifndef OF_COMPILER_TLS -# import "threading.h" -#endif -#import "macros.h" - -#ifdef OF_COMPILER_TLS -static __thread id *objects = NULL; -static __thread id *top = NULL; -static __thread size_t size = 0; -#else -static of_tlskey_t objectsKey, topKey, sizeKey; - -static void __attribute__((constructor)) -init(void) -{ - if (!of_tlskey_new(&objectsKey) || !of_tlskey_new(&sizeKey) || - !of_tlskey_new(&topKey)) - OBJC_ERROR("Unable to create TLS key for autorelease pools!") -} -#endif - -id -objc_autorelease(id object) -{ - return [object autorelease]; -} - -void* -objc_autoreleasePoolPush() -{ -#ifndef OF_COMPILER_TLS - id *top = of_tlskey_get(topKey); - id *objects = of_tlskey_get(objectsKey); -#endif - ptrdiff_t offset = top - objects; - - return (void*)offset; -} - -void -objc_autoreleasePoolPop(void *offset) -{ -#ifndef OF_COMPILER_TLS - id *top = of_tlskey_get(topKey); - id *objects = of_tlskey_get(objectsKey); -#endif - id *pool = objects + (ptrdiff_t)offset; - id *iter; - - for (iter = pool; iter < top; iter++) - [*iter release]; - - top = pool; - - if (top == objects) { - free(objects); - - objects = NULL; - top = NULL; - } - -#ifndef OF_COMPILER_TLS - if (!of_tlskey_set(objectsKey, objects) ||!of_tlskey_set(topKey, top)) - OBJC_ERROR("Failed to set TLS key!") -#endif -} - -id -_objc_rootAutorelease(id object) -{ -#ifndef OF_COMPILER_TLS - id *top = of_tlskey_get(topKey); - id *objects = of_tlskey_get(objectsKey); - size_t size = (size_t)(uintptr_t)of_tlskey_get(sizeKey); -#endif - - if (objects == NULL) { - if ((objects = malloc(of_pagesize)) == NULL) - OBJC_ERROR("Out of memory for autorelease pools!") - -#ifndef OF_COMPILER_TLS - if (!of_tlskey_set(objectsKey, objects)) - OBJC_ERROR("Failed to set TLS key!") - if (!of_tlskey_set(sizeKey, (void*)(uintptr_t)of_pagesize)) - OBJC_ERROR("Failed to set TLS key!") -#endif - - top = objects; - size = of_pagesize; - } - - if ((uintptr_t)top >= (uintptr_t)objects + size) { - ptrdiff_t diff = top - objects; - - size += of_pagesize; - if ((objects = realloc(objects, size)) == NULL) - OBJC_ERROR("Out of memory for autorelease pools!") - -#ifndef OF_COMPILER_TLS - if (!of_tlskey_set(objectsKey, objects)) - OBJC_ERROR("Failed to set TLS key!") - if (!of_tlskey_set(sizeKey, (void*)(uintptr_t)size)) - OBJC_ERROR("Failed to set TLS key!") -#endif - - top = objects + diff; - } - - *top = object; - top++; - -#ifndef OF_COMPILER_TLS - if (!of_tlskey_set(topKey, objects)) - OBJC_ERROR("Failed to set TLS key!") -#endif - - return object; -}