Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -176,11 +176,10 @@ OFLocking.h \ OFMessagePackRepresentation.h \ OFSerialization.h \ OFTLSSocket.h \ ObjFW.h \ - autorelease.h \ block.h \ macros.h \ objfw-defs.h \ platform.h \ ${USE_INCLUDES_ATOMIC} @@ -205,11 +204,10 @@ OFRangeCharacterSet.m \ OFRangeValue.m \ OFRectangleValue.m \ OFSubarray.m \ OFUTF8String.m \ - ${AUTORELEASE_M} \ ${LIBBASES_M} SRCS_FILES += OFFileURLHandler.m \ OFINIFileSettings.m SRCS_SOCKETS += OFDNSResolverSettings.m \ OFHTTPURLHandler.m \ Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -28,11 +28,10 @@ #include #include #include #import "macros.h" -#import "autorelease.h" #import "block.h" /* * Some versions of MinGW require to be included before * . Do this here to make sure this is always done in the correct @@ -1275,10 +1274,14 @@ @end #ifdef __cplusplus extern "C" { #endif +#ifdef OF_APPLE_RUNTIME +extern void *_Null_unspecified objc_autoreleasePoolPush(void); +extern void objc_autoreleasePoolPop(void *_Null_unspecified pool); +#endif extern id of_alloc_object(Class class_, size_t extraSize, size_t extraAlignment, void *_Nullable *_Nullable extra); extern void OF_NO_RETURN_FUNC of_method_not_found(id self, SEL _cmd); extern uint32_t of_hash_seed; #ifdef __cplusplus Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -64,10 +64,13 @@ # import "atomic.h" #elif defined(OF_HAVE_THREADS) # import "mutex.h" #endif +#ifdef OF_APPLE_RUNTIME +extern id _Nullable _objc_rootAutorelease(id _Nullable object); +#endif #if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR) extern id of_forward(id, SEL, ...); extern struct stret of_forward_stret(id, SEL, ...); #else # define of_forward of_method_not_found DELETED src/autorelease.h Index: src/autorelease.h ================================================================== --- src/autorelease.h +++ src/autorelease.h @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, - * 2018, 2019, 2020 - * 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. - */ - -#import "macros.h" - -OF_ASSUME_NONNULL_BEGIN - -/*! @file */ - -#ifdef __cplusplus -extern "C" { -#endif -/*! - * @brief Creates a new autorelease pool. - * - * @return An identifier for the created autorelease pool - */ -extern void *objc_autoreleasePoolPush(void); - -/*! - * @brief Drains an autorelease pool. - * - * @param pool An identifier for the pool to drain - */ -extern void objc_autoreleasePoolPop(void *pool); - -/*! - * @brief Autoreleases an object. - * - * @param object The object to autorelease - * @return The autoreleased object - */ -extern id _objc_rootAutorelease(id object); -#ifdef __cplusplus -} -#endif - -OF_ASSUME_NONNULL_END DELETED src/autorelease.m Index: src/autorelease.m ================================================================== --- src/autorelease.m +++ src/autorelease.m @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, - * 2018, 2019, 2020 - * 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" -#import "OFSystemInfo.h" - -#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) -# import "tlskey.h" -#endif - -#if defined(OF_HAVE_COMPILER_TLS) -static thread_local id *objects = NULL; -static thread_local id *top = NULL; -static thread_local size_t size = 0; -#elif defined(OF_HAVE_THREADS) -static of_tlskey_t objectsKey, topKey, sizeKey; -#else -static id *objects = NULL; -static id *top = NULL; -static size_t size = 0; -#endif - -#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) -OF_CONSTRUCTOR() -{ - OF_ENSURE(of_tlskey_new(&objectsKey)); - OF_ENSURE(of_tlskey_new(&topKey)); - OF_ENSURE(of_tlskey_new(&sizeKey)); -} -#endif - -void * -objc_autoreleasePoolPush() -{ -#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - 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) -{ -#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - 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; - } - -#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - OF_ENSURE(of_tlskey_set(topKey, top)); - OF_ENSURE(of_tlskey_set(objectsKey, objects)); -#endif -} - -id -_objc_rootAutorelease(id object) -{ -#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - 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) { - size = [OFSystemInfo pageSize]; - - OF_ENSURE((objects = malloc(size)) != NULL); - - top = objects; - -#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - OF_ENSURE(of_tlskey_set(objectsKey, objects)); - OF_ENSURE(of_tlskey_set(sizeKey, (void *)(uintptr_t)size)); -#endif - } - - if ((uintptr_t)top >= (uintptr_t)objects + size) { - ptrdiff_t diff = top - objects; - - size += [OFSystemInfo pageSize]; - OF_ENSURE((objects = realloc(objects, size)) != NULL); - -#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - OF_ENSURE(of_tlskey_set(objectsKey, objects)); - OF_ENSURE(of_tlskey_set(sizeKey, (void *)(uintptr_t)size)); -#endif - - top = objects + diff; - } - - *top = object; - top++; - -#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) - OF_ENSURE(of_tlskey_set(topKey, top)); -#endif - - return object; -} Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -10,10 +10,11 @@ AMIGA_LIB = ${OBJFWRT_AMIGA_LIB} LIB_MAJOR = ${OBJFWRT_LIB_MAJOR} LIB_MINOR = ${OBJFWRT_LIB_MINOR} SRCS = arc.m \ + autorelease.m \ category.m \ class.m \ dtable.m \ exception.m \ hashtable.m \ Index: src/runtime/ObjFWRT.h ================================================================== --- src/runtime/ObjFWRT.h +++ src/runtime/ObjFWRT.h @@ -149,10 +149,13 @@ extern void objc_setEnumerationMutationHandler( objc_enumeration_mutation_handler_t _Nullable handler); extern id _Nullable objc_constructInstance(Class _Nullable class_, void *_Nullable bytes); extern void *_Nullable objc_destructInstance(id _Nullable object); +extern void *_Null_unspecified objc_autoreleasePoolPush(void); +extern void objc_autoreleasePoolPop(void *_Null_unspecified pool); +extern id _Nullable _objc_rootAutorelease(id _Nullable object); /* * Used by the compiler, but can also be called manually. * * These declarations are also required to prevent Clang's implicit Index: src/runtime/amiga-glue.m ================================================================== --- src/runtime/amiga-glue.m +++ src/runtime/amiga-glue.m @@ -725,5 +725,27 @@ { M68K_ARG(id, object, a0) return objc_destructInstance(object); } + +void *__saveds +glue_objc_autoreleasePoolPush(void) +{ + return objc_autoreleasePoolPush(); +} + +void __saveds +glue_objc_autoreleasePoolPop PPC_PARAMS(void *pool) +{ + M68K_ARG(void *, pool, a0) + + objc_autoreleasePoolPop(pool); +} + +id __saveds +glue__objc_rootAutorelease PPC_PARAMS(id object) +{ + M68K_ARG(id, object, a0) + + return _objc_rootAutorelease(object); +} Index: src/runtime/amiga-library.m ================================================================== --- src/runtime/amiga-library.m +++ src/runtime/amiga-library.m @@ -137,10 +137,13 @@ extern const char *glue_method_getTypeEncoding(void); extern objc_property_t *glue_class_copyPropertyList(void); extern const char *glue_property_getName(void); extern char *glue_property_copyAttributeValue(void); extern void *glue_objc_destructInstance(void); +extern void *glue_objc_autoreleasePoolPush(void); +extern void glue_objc_autoreleasePoolPop(void); +extern id glue__objc_rootAutorelease(void); #ifdef OF_MORPHOS const ULONG __abox__ = 1; #endif struct ExecBase *SysBase; @@ -655,10 +658,13 @@ (CONST_APTR)glue_method_getTypeEncoding, (CONST_APTR)glue_class_copyPropertyList, (CONST_APTR)glue_property_getName, (CONST_APTR)glue_property_copyAttributeValue, (CONST_APTR)glue_objc_destructInstance, + (CONST_APTR)glue_objc_autoreleasePoolPush, + (CONST_APTR)glue_objc_autoreleasePoolPop, + (CONST_APTR)glue__objc_rootAutorelease, (CONST_APTR)-1, #ifdef OF_MORPHOS (CONST_APTR)FUNCARRAY_END #endif }; Index: src/runtime/amigaos3.sfd ================================================================== --- src/runtime/amigaos3.sfd +++ src/runtime/amigaos3.sfd @@ -80,6 +80,9 @@ const char *_Nullable glue_method_getTypeEncoding(Method _Nonnull method)(a0) objc_property_t _Nullable *_Nullable glue_class_copyPropertyList(Class _Nullable class_, unsigned int *_Nullable outCount)(a0,a1) const char *_Nonnull glue_property_getName(objc_property_t _Nonnull property)(a0) char *_Nullable glue_property_copyAttributeValue(objc_property_t _Nonnull property, const char *_Nonnull name)(a0,a1) void *_Nullable glue_objc_destructInstance(id _Nullable object)(a0) +void *_Null_unspecified glue_objc_autoreleasePoolPush(void)() +void glue_objc_autoreleasePoolPop(void *_Null_unspecified pool)(a0) +id _Nullable glue__objc_rootAutorelease(id _Nullable object)(a0) ==end Index: src/runtime/arc.m ================================================================== --- src/runtime/arc.m +++ src/runtime/arc.m @@ -18,13 +18,10 @@ #include "config.h" #import "ObjFWRT.h" #import "private.h" -#import "OFObject.h" -#import "OFBlock.h" - #ifdef OF_HAVE_THREADS # import "mutex.h" #endif struct weak_ref { ADDED src/runtime/autorelease.m Index: src/runtime/autorelease.m ================================================================== --- src/runtime/autorelease.m +++ src/runtime/autorelease.m @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * 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 "ObjFWRT.h" +#import "private.h" + +#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) +# import "tlskey.h" +#endif + +#if defined(OF_HAVE_COMPILER_TLS) +static thread_local id *objects = NULL; +static thread_local id *top = NULL; +static thread_local size_t size = 0; +#elif defined(OF_HAVE_THREADS) +static of_tlskey_t objectsKey, topKey, sizeKey; +#else +static id *objects = NULL; +static id *top = NULL; +static size_t size = 0; +#endif + +#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) +OF_CONSTRUCTOR() +{ + OF_ENSURE(of_tlskey_new(&objectsKey)); + OF_ENSURE(of_tlskey_new(&topKey)); + OF_ENSURE(of_tlskey_new(&sizeKey)); +} +#endif + +void * +objc_autoreleasePoolPush() +{ +#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) + 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) +{ +#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) + 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; + } + +#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) + OF_ENSURE(of_tlskey_set(topKey, top)); + OF_ENSURE(of_tlskey_set(objectsKey, objects)); +#endif +} + +id +_objc_rootAutorelease(id object) +{ +#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) + 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) { + size = 16 * sizeof(id); + + OF_ENSURE((objects = malloc(size)) != NULL); + + top = objects; + +#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) + OF_ENSURE(of_tlskey_set(objectsKey, objects)); + OF_ENSURE(of_tlskey_set(sizeKey, (void *)(uintptr_t)size)); +#endif + } + + if ((uintptr_t)top >= (uintptr_t)objects + size) { + ptrdiff_t diff = top - objects; + + size *= 2; + OF_ENSURE((objects = realloc(objects, size)) != NULL); + +#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) + OF_ENSURE(of_tlskey_set(objectsKey, objects)); + OF_ENSURE(of_tlskey_set(sizeKey, (void *)(uintptr_t)size)); +#endif + + top = objects + diff; + } + + *top = object; + top++; + +#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) + OF_ENSURE(of_tlskey_set(topKey, top)); +#endif + + return object; +} Index: src/runtime/linklib/linklib.m ================================================================== --- src/runtime/linklib/linklib.m +++ src/runtime/linklib/linklib.m @@ -655,5 +655,23 @@ void * objc_destructInstance(id object) { return glue_objc_destructInstance(object); } + +void * +objc_autoreleasePoolPush(void) +{ + return glue_objc_autoreleasePoolPush(); +} + +void +objc_autoreleasePoolPop(void *pool) +{ + glue_objc_autoreleasePoolPop(pool); +} + +id +_objc_rootAutorelease(id object) +{ + return glue__objc_rootAutorelease(object); +} Index: src/runtime/morphos-clib.h ================================================================== --- src/runtime/morphos-clib.h +++ src/runtime/morphos-clib.h @@ -74,5 +74,8 @@ const char *glue_method_getTypeEncoding(Method method); objc_property_t *glue_class_copyPropertyList(Class class_, unsigned int *outCount); const char *glue_property_getName(objc_property_t property); char *glue_property_copyAttributeValue(objc_property_t property, const char *name); void *glue_objc_destructInstance(id object); +void *glue_objc_autoreleasePoolPush(void); +void glue_objc_autoreleasePoolPop(void *pool); +id glue__objc_rootAutorelease(id object); Index: src/runtime/morphos.fd ================================================================== --- src/runtime/morphos.fd +++ src/runtime/morphos.fd @@ -76,6 +76,9 @@ glue_method_getTypeEncoding(method)(sysv,r12base) glue_class_copyPropertyList(class_,outCount)(sysv,r12base) glue_property_getName(property)(sysv,r12base) glue_property_copyAttributeValue(property,name)(sysv,r12base) glue_objc_destructInstance(object)(sysv,r12base) +objc_autoreleasePoolPush()(sysv,r12base) +objc_autoreleasePoolPop(pool)(sysv,r12base) +_objc_rootAutorelease(object)(sysv,r12base) ##end Index: src/runtime/private.h ================================================================== --- src/runtime/private.h +++ src/runtime/private.h @@ -364,9 +364,17 @@ @interface DummyObject { Class _Nonnull isa; } +@property (readonly, nonatomic) bool allowsWeakReference; + + (void)initialize; + (bool)resolveClassMethod: (nonnull SEL)selector; + (bool)resolveInstanceMethod: (nonnull SEL)selector; +- (nonnull id)retain; +- (void)release; +- (nonnull id)autorelease; +- (nonnull id)copy; +- (nonnull id)mutableCopy; +- (bool)retainWeakReference; @end Index: src/runtime/property.m ================================================================== --- src/runtime/property.m +++ src/runtime/property.m @@ -20,12 +20,10 @@ #include #import "ObjFWRT.h" #import "private.h" -#import "OFObject.h" - #ifdef OF_HAVE_THREADS # import "mutex.h" # define NUM_SPINLOCKS 8 /* needs to be a power of 2 */ # define SPINLOCK_HASH(p) ((unsigned)((uintptr_t)p >> 4) & (NUM_SPINLOCKS - 1)) static of_spinlock_t spinlocks[NUM_SPINLOCKS];