Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -73,11 +73,11 @@ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) OBJCFLAGS="$old_OBJCFLAGS" ]) -AC_CHECK_FUNC(_Block_copy,, AC_SUBST(BLOCK_M, "block.m")) +AC_CHECK_FUNC(_Block_copy,, AC_SUBST(OFBLOCK_M, "OFBlock.m")) AC_CHECK_HEADERS([objfw-rt.h objc/objc.h]) test x"$ac_cv_header_objfw_rt_h" = x"yes" && objc_runtime="ObjFW-RT" Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -4,13 +4,13 @@ OBJFW_LIB_MINOR = 0 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} ASPRINTF_M = @ASPRINTF_M@ ATOMIC_H = @ATOMIC_H@ -BLOCK_M = @BLOCK_M@ OBJC_PROPERTIES_M = @OBJC_PROPERTIES_M@ OBJC_SYNC_M = @OBJC_SYNC_M@ +OFBLOCK_M = @OFBLOCK_M@ OFPLUGIN_M = @OFPLUGIN_M@ OFPLUGINTESTS_M = @OFPLUGINTESTS_M@ OFTHREAD_M = @OFTHREAD_M@ OFTHREADTESTS_M = @OFTHREADTESTS_M@ PROPERTIESTESTS_M = @PROPERTIESTESTS_M@ Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -7,10 +7,11 @@ SRCS = OFApplication.m \ OFArray.m \ OFAutoreleasePool.m \ OFConstString.m \ + ${OFBLOCK_M} \ OFDataArray.m \ OFDictionary.m \ OFExceptions.m \ OFFile.m \ OFHash.m \ @@ -52,13 +53,12 @@ SRCS += ${ASPRINTF_M} \ iso_8859_15.m \ windows_1252.m \ ${OBJC_PROPERTIES_M} \ - ${OBJC_SYNC_M} \ - ${BLOCK_M} + ${OBJC_SYNC_M} include ../buildsys.mk CPPFLAGS += -I.. LD = ${OBJC} LDFLAGS += ${REEXPORT_LIBOBJC} ADDED src/OFBlock.h Index: src/OFBlock.h ================================================================== --- src/OFBlock.h +++ src/OFBlock.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008 - 2010 + * 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 included in + * the packaging of this file. + */ + +#import "objfw-defs.h" + +#ifdef OF_OBJFW_RUNTIME +# import +#else +# import +#endif + +typedef struct __of_block_literal { + Class isa; + int flags; + int reserved; + void (*invoke)(void *, ...); + struct __of_block_descriptor { + unsigned long reserved; + unsigned long size; + void (*copy_helper)(void *dest, void *src); + void (*dispose_helper)(void *src); + const char *signature; + } *descriptor; +} of_block_literal_t; + +typedef struct __of_block_byref { + Class isa; + struct __of_block_byref *forwarding; + int flags; + int size; + void (*byref_keep)(void *dest, void *src); + void (*byref_dispose)(void*); +} of_block_byref_t; + +enum { + OF_BLOCK_HAS_COPY_DISPOSE = (1 << 25), + OF_BLOCK_HAS_CTOR = (1 << 26), + OF_BLOCK_IS_GLOBAL = (1 << 28), + OF_BLOCK_HAS_STRET = (1 << 29), + OF_BLOCK_HAS_SIGNATURE = (1 << 30), +}; + +enum { + OF_BLOCK_FIELD_IS_OBJECT = 3, + OF_BLOCK_FIELD_IS_BLOCK = 7, + OF_BLOCK_FIELD_IS_BYREF = 8, + OF_BLOCK_FIELD_IS_WEAK = 16, + OF_BLOCK_BYREF_CALLER = 128, +}; + +@interface OFBlock +{ + Class isa; +} + +- copy; +- (void)release; +- autorelease; +@end ADDED src/OFBlock.m Index: src/OFBlock.m ================================================================== --- src/OFBlock.m +++ src/OFBlock.m @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2008 - 2010 + * 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 included in + * the packaging of this file. + */ + +#include "config.h" + +#include +#include +#include + +#import "OFBlock.h" +#import "OFAutoreleasePool.h" + +struct objc_abi_class { + struct objc_abi_class *metaclass; + const char *superclass, *name; + unsigned long version, info, instance_size; + void *ivars, *methodlist, *dtable, *subclass_list, *sibling_class; + void *protocols, *gc_object_type; + long abi_version; + void *ivar_offsets, *properties; +}; + +enum objc_abi_class_info { + OBJC_CLASS_INFO_CLASS = 0x01, + OBJC_CLASS_INFO_METACLASS = 0x02 +}; + +extern void __objc_exec_class(void*); + +/* Begin of ObjC module */ +static struct objc_abi_class _NSConcreteStackBlock_metaclass = { + &_NSConcreteStackBlock_metaclass, "OFBlock", "_NSConcreteStackBlock", 8, + OBJC_CLASS_INFO_METACLASS, sizeof(struct objc_class), NULL, NULL +}; + +struct objc_abi_class _NSConcreteStackBlock = { + &_NSConcreteStackBlock_metaclass, "OFBlock", "_NSConcreteStackBlock", 8, + OBJC_CLASS_INFO_CLASS, sizeof(of_block_literal_t), NULL, NULL +}; + +static struct objc_abi_class _NSConcreteGlobalBlock_metaclass = { + &_NSConcreteGlobalBlock_metaclass, "OFBlock", "_NSConcreteGlobalBlock", + 8, OBJC_CLASS_INFO_METACLASS, sizeof(struct objc_class), NULL, NULL +}; + +struct objc_abi_class _NSConcreteGlobalBlock = { + &_NSConcreteGlobalBlock_metaclass, "OFBlock", "_NSConcreteGlobalBlock", + 8, OBJC_CLASS_INFO_CLASS, sizeof(of_block_literal_t), NULL, NULL +}; + +static struct objc_abi_class _NSConcreteMallocBlock_metaclass = { + &_NSConcreteMallocBlock_metaclass, "OFBlock", "_NSConcreteMallocBlock", + 8, OBJC_CLASS_INFO_METACLASS, sizeof(struct objc_class), NULL, NULL +}; + +struct objc_abi_class _NSConcreteMallocBlock = { + &_NSConcreteMallocBlock_metaclass, "OFBlock", "_NSConcreteMallocBlock", + 8, OBJC_CLASS_INFO_CLASS, sizeof(of_block_literal_t), NULL, NULL +}; + +static struct { + unsigned int unknown; + struct objc_abi_selector *sel_refs; + uint16_t cls_def_cnt, cat_def_cnt; + void *defs[4]; +} symtab = { 0, NULL, 3, 0, { + &_NSConcreteStackBlock, &_NSConcreteGlobalBlock, + &_NSConcreteMallocBlock, NULL +}}; + +static struct { + unsigned long version, size; + const char *name; + void *symtab; +} module = { 8, sizeof(module), NULL, &symtab }; + +static void __attribute__((constructor)) +__objc_gnu_init() +{ + __objc_exec_class(&module); +} +/* Emd of ObjC module */ + +of_block_literal_t* +Block_copy(of_block_literal_t *block) +{ + if (block->isa == (Class)&_NSConcreteStackBlock) { + of_block_literal_t *copy; + + if ((copy = malloc(block->descriptor->size)) == NULL) { + fputs("Not enough memory to copy block!\n", stderr); + exit(1); + } + memcpy(copy, block, block->descriptor->size); + + copy->isa = (Class)&_NSConcreteMallocBlock; + copy->reserved++; + + if (block->flags & OF_BLOCK_HAS_COPY_DISPOSE) + block->descriptor->copy_helper(copy, block); + + return copy; + } + + if (block->isa == (Class)&_NSConcreteMallocBlock) + block->reserved++; + + return block; +} + +void +Block_release(of_block_literal_t *block) +{ + if (block->isa != (Class)&_NSConcreteMallocBlock) + return; + + if (--block->reserved == 0) { + if (block->flags & OF_BLOCK_HAS_COPY_DISPOSE) + block->descriptor->dispose_helper(block); + + free(block); + } +} + +void +_Block_object_assign(void *dst, void *src, int flags) +{ + flags &= OF_BLOCK_FIELD_IS_BLOCK | OF_BLOCK_FIELD_IS_OBJECT | + OF_BLOCK_FIELD_IS_BYREF; + + switch (flags) { + case OF_BLOCK_FIELD_IS_BLOCK: + *(of_block_literal_t**)dst = Block_copy(src); + break; + case OF_BLOCK_FIELD_IS_OBJECT: + *(id*)dst = [(id)src retain]; + break; + case OF_BLOCK_FIELD_IS_BYREF:; + of_block_byref_t *src_ = src; + of_block_byref_t **dst_ = dst; + + if ((src_->flags & ~OF_BLOCK_HAS_COPY_DISPOSE) == 0) { + if ((*dst_ = malloc(src_->size)) == NULL) { + fputs("Not enough memory for block " + "variables!\n", stderr); + exit(1); + } + + if (src_->forwarding == src) + src_->forwarding = *dst_; + + memcpy(*dst_, src_, src_->size); + + if (src_->size >= sizeof(of_block_byref_t)) + src_->byref_keep(*dst_, src_); + } else + *dst_ = src_; + + (*dst_)->flags++; + break; + } +} + +void +_Block_object_dispose(void *obj, int flags) +{ + flags &= OF_BLOCK_FIELD_IS_BLOCK | OF_BLOCK_FIELD_IS_OBJECT | + OF_BLOCK_FIELD_IS_BYREF; + + switch (flags) { + case OF_BLOCK_FIELD_IS_BLOCK: + Block_release(obj); + break; + case OF_BLOCK_FIELD_IS_OBJECT: + [(id)obj release]; + break; + case OF_BLOCK_FIELD_IS_BYREF:; + of_block_byref_t *obj_ = obj; + + if ((--obj_->flags & ~OF_BLOCK_HAS_COPY_DISPOSE) == 0) { + if (obj_->size >= sizeof(of_block_byref_t)) + obj_->byref_dispose(obj_); + + free(obj_); + } + break; + } +} + +static Class autoreleasepool = Nil; + +@implementation OFBlock +- copy +{ + return (id)Block_copy((of_block_literal_t*)self); +} + +- (void)release +{ + Block_release((of_block_literal_t*)self); +} + +- autorelease +{ + /* + * Cache OFAutoreleasePool since class lookups are expensive with the + * GNU runtime. + */ + if (autoreleasepool == Nil) + autoreleasepool = [OFAutoreleasePool class]; + + [autoreleasepool addObjectToTopmostPool: self]; + + return self; +} +@end Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -10,10 +10,11 @@ */ #import "objfw-defs.h" #import "OFObject.h" +#import "OFBlock.h" #import "OFExceptions.h" #import "OFAutoreleasePool.h" #import "OFString.h" DELETED src/block.m Index: src/block.m ================================================================== --- src/block.m +++ src/block.m @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2008 - 2010 - * 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 included in - * the packaging of this file. - */ - -#include "config.h" - -#include -#include -#include - -#ifdef OF_OBJFW_RUNTIME -# import -#else -# import -# ifdef OF_APPLE_RUNTIME -# import -# endif -#endif - -@interface RetainRelease -- retain; -- (void)release; -@end - -struct block_literal { - void *isa; - int flags; - int reserved; - void (*invoke)(void *, ...); - struct block_descriptor { - unsigned long reserved; - unsigned long size; - void (*copy_helper)(void *dest, void *src); - void (*dispose_helper)(void *src); - const char *signature; - } *descriptor; -}; - -struct block_byref { - void *isa; - struct block_byref *forwarding; - int flags; - int size; - void (*byref_keep)(void *dest, void *src); - void (*byref_dispose)(void*); -}; - -enum { - BLOCK_HAS_COPY_DISPOSE = (1 << 25), - BLOCK_HAS_CTOR = (1 << 26), - BLOCK_IS_GLOBAL = (1 << 28), - BLOCK_HAS_STRET = (1 << 29), - BLOCK_HAS_SIGNATURE = (1 << 30), -}; - -enum { - BLOCK_FIELD_IS_OBJECT = 3, - BLOCK_FIELD_IS_BLOCK = 7, - BLOCK_FIELD_IS_BYREF = 8, - BLOCK_FIELD_IS_WEAK = 16, - BLOCK_BYREF_CALLER = 128, -}; - -#ifndef __OBJC2__ -struct objc_class _NSConcreteStackBlock; -struct objc_class _NSConcreteGlobalBlock; -struct objc_class _NSConcreteMallocBlock; -#endif - -struct block_literal* -Block_copy(struct block_literal *block) -{ - if (block->isa == &_NSConcreteStackBlock) { - struct block_literal *copy; - - if ((copy = malloc(block->descriptor->size)) == NULL) { - fputs("Not enough memory to copy block!\n", stderr); - exit(1); - } - memcpy(copy, block, block->descriptor->size); - - copy->isa = &_NSConcreteMallocBlock; - copy->reserved++; - - if (block->flags & BLOCK_HAS_COPY_DISPOSE) - block->descriptor->copy_helper(copy, block); - - return copy; - } - - if (block->isa == &_NSConcreteMallocBlock) - block->reserved++; - - return block; -} - -void -Block_release(struct block_literal *block) -{ - if (block->isa != &_NSConcreteMallocBlock) - return; - - if (--block->reserved == 0) { - if (block->flags & BLOCK_HAS_COPY_DISPOSE) - block->descriptor->dispose_helper(block); - - free(block); - } -} - -void -_Block_object_assign(void *dst, void *src, int flags) -{ - flags &= BLOCK_FIELD_IS_BLOCK | BLOCK_FIELD_IS_OBJECT | - BLOCK_FIELD_IS_BYREF; - - switch (flags) { - case BLOCK_FIELD_IS_BLOCK: - *(struct block_literal**)dst = Block_copy(src); - break; - case BLOCK_FIELD_IS_OBJECT: - *(id*)dst = [(id)src retain]; - break; - case BLOCK_FIELD_IS_BYREF:; - struct block_byref *src_ = src; - struct block_byref **dst_ = dst; - - if ((src_->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0) { - if ((*dst_ = malloc(src_->size)) == NULL) { - fputs("Not enough memory for block " - "variables!\n", stderr); - exit(1); - } - - if (src_->forwarding == src) - src_->forwarding = *dst_; - - memcpy(*dst_, src_, src_->size); - - if (src_->size >= sizeof(struct block_byref)) - src_->byref_keep(*dst_, src_); - } else - *dst_ = src_; - - (*dst_)->flags++; - break; - } -} - -void -_Block_object_dispose(void *obj, int flags) -{ - flags &= BLOCK_FIELD_IS_BLOCK | BLOCK_FIELD_IS_OBJECT | - BLOCK_FIELD_IS_BYREF; - - switch (flags) { - case BLOCK_FIELD_IS_BLOCK: - Block_release(obj); - break; - case BLOCK_FIELD_IS_OBJECT: - [(id)obj release]; - break; - case BLOCK_FIELD_IS_BYREF:; - struct block_byref *obj_ = obj; - - if ((--obj_->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0) { - if (obj_->size >= sizeof(struct block_byref)) - obj_->byref_dispose(obj_); - - free(obj_); - } - break; - } -}