diff --git a/GNUmakefile b/GNUmakefile index c5be0022..32102632 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -100,6 +100,7 @@ ${LIBOBJC}_HEADER_FILES = \ Availability.h\ Object.h\ Protocol.h\ + blocks_private.h\ blocks_runtime.h\ capabilities.h\ developer.h\ diff --git a/block_to_imp.c b/block_to_imp.c index dd9d46e1..5b0262c6 100644 --- a/block_to_imp.c +++ b/block_to_imp.c @@ -72,7 +72,7 @@ extern void __objc_block_trampoline_end_sret; IMP imp_implementationWithBlock(void *block) { - struct block_literal *b = block; + struct Block_layout *b = block; void *start; void *end; diff --git a/blocks_runtime.h b/blocks_runtime.h index 1838c48a..f69490ae 100644 --- a/blocks_runtime.h +++ b/blocks_runtime.h @@ -1,5 +1,5 @@ /** - * Block descriptor flags. + * Block descriptor flags. */ enum block_flags { @@ -37,7 +37,7 @@ enum block_flags * _Block_object_dispose(). These indicate the type of copy or dispose to * perform. */ -enum +enum { /** * The value is of some id-like type, and should be copied as an @@ -54,43 +54,23 @@ enum * __block storage qualifier. */ BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable - + BLOCK_FIELD_IS_WEAK = 16, // declared __weak - + BLOCK_BYREF_CALLER = 128, // called from byref copy/dispose helpers }; #define IS_SET(x, y) ((x & y) == y) -/** - * Block descriptor that contains copy and dispose operations. +/* + * Include the block_descriptor_copydispose and block_literal definitions that + * are also made public under different names for use in libdispatch. */ -struct block_descriptor_copydispose -{ - /** - * Reserved for future use. Currently always 0. - */ - unsigned long int reserved; - /** Size of the block. */ - unsigned long int size; - /** - * Copy function, generated by the compiler to help copy the block if it - * contains nontrivial copy operations. - */ - void (*copy_helper)(void *dst, void *src); - /** - * Dispose function, generated by the compiler to help copy the block if it - * contains nontrivial destructors. - */ - void (*dispose_helper)(void *src); - /** - * Objective-C type encoding of the block. - */ - const char *encoding; -}; +#include "objc/blocks_private.h" + /** * Block descriptor that does not contain copy and dispose helper functions. */ -struct block_descriptor +struct Block_descriptor_basic { /** * Reserved for future use, currently always 0. @@ -104,42 +84,6 @@ struct block_descriptor const char *encoding; }; -// Helper structure -struct block_literal -{ - /** - * Class pointer. Always initialised to &_NSConcreteStackBlock for blocks - * that are created on the stack or &_NSConcreteGlobalBlock for blocks that - * are created in global storage. - */ - void *isa; - /** - * Flags. See the block_flags enumerated type for possible values. - */ - int flags; - /** - * Reserved - always initialised to 0 by the compiler. Used for the - * reference count in this implementation. - */ - int reserved; - /** - * The function that implements the block. The first argument is this - * structure, the subsequent arguments are the block's explicit parameters. - * If the BLOCK_USE_SRET flag is set, there is an additional hidden - * argument, which is a pointer to the space on the stack allocated to hold - * the return value. - */ - void (*invoke)(void *, ...); - /** - * The block's descriptor. This is either block_descriptor or - * block_descriptor_copydispose, depending on whether the - * BLOCK_HAS_COPY_DISPOSE flag is set. - */ - struct block_descriptor_copydispose *descriptor; - /** - * Block variables are appended to this structure. - */ -}; /** * Structure used for on-stack variables that are referenced by blocks. diff --git a/blocks_runtime.m b/blocks_runtime.m index dd1d66ea..d84069ce 100644 --- a/blocks_runtime.m +++ b/blocks_runtime.m @@ -1,7 +1,7 @@ /* * Copyright (c) 2009 Remy Demarest * Portions Copyright (c) 2009 David Chisnall - * + * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without @@ -10,10 +10,10 @@ * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -44,14 +44,14 @@ */ const char *block_getType_np(void *b) { - struct block_literal *block = b; + struct Block_layout *block = b; if ((NULL == block) || !(block->flags & BLOCK_HAS_SIGNATURE)) { return NULL; } if (!(block->flags & BLOCK_HAS_COPY_DISPOSE)) { - return ((struct block_descriptor*)block->descriptor)->encoding; + return ((struct Block_descriptor_basic*)block->descriptor)->encoding; } return block->descriptor->encoding; } @@ -121,7 +121,7 @@ void _Block_object_assign(void *destAddr, const void *object, const int flags) struct block_byref_obj *src = (struct block_byref_obj *)object; struct block_byref_obj **dst = destAddr; src = src->forwarding; - + if ((src->flags & BLOCK_REFCOUNT_MASK) == 0) { *dst = gc->malloc(src->size); @@ -161,9 +161,9 @@ void _Block_object_assign(void *destAddr, const void *object, const int flags) } else if (IS_SET(flags, BLOCK_FIELD_IS_BLOCK)) { - struct block_literal *src = (struct block_literal*)object; - struct block_literal **dst = destAddr; - + struct Block_layout *src = (struct Block_layout*)object; + struct Block_layout **dst = destAddr; + *dst = Block_copy(src); } else if (IS_SET(flags, BLOCK_FIELD_IS_OBJECT) && @@ -196,7 +196,7 @@ void _Block_object_dispose(const void *object, const int flags) { if (IS_SET(flags, BLOCK_FIELD_IS_BYREF)) { - struct block_byref_obj *src = + struct block_byref_obj *src = (struct block_byref_obj*)object; if (src->isa == _HeapBlockByRef) { @@ -228,7 +228,7 @@ void _Block_object_dispose(const void *object, const int flags) } else if (IS_SET(flags, BLOCK_FIELD_IS_BLOCK)) { - struct block_literal *src = (struct block_literal*)object; + struct Block_layout *src = (struct Block_layout*)object; Block_release(src); } else if (IS_SET(flags, BLOCK_FIELD_IS_OBJECT) && @@ -248,12 +248,12 @@ void _Block_object_dispose(const void *object, const int flags) void *_Block_copy(void *src) { if (NULL == src) { return NULL; } - struct block_literal *self = src; - struct block_literal *ret = self; + struct Block_layout *self = src; + struct Block_layout *ret = self; extern void _NSConcreteStackBlock; extern void _NSConcreteMallocBlock; - + // If the block is Global, there's no need to copy it on the heap. if(self->isa == &_NSConcreteStackBlock) { @@ -282,8 +282,8 @@ void _Block_object_dispose(const void *object, const int flags) void _Block_release(void *src) { if (NULL == src) { return; } - struct block_literal *self = src; - + struct Block_layout *self = src; + extern void _NSConcreteStackBlock; extern void _NSConcreteMallocBlock; @@ -305,6 +305,6 @@ void _Block_release(void *src) PRIVATE void* block_load_weak(void *block) { - struct block_literal *self = block; + struct Block_layout *self = block; return (self->reserved) > 0 ? block : 0; } diff --git a/objc/blocks_private.h b/objc/blocks_private.h new file mode 100644 index 00000000..5f1fca15 --- /dev/null +++ b/objc/blocks_private.h @@ -0,0 +1,90 @@ +#ifndef __LIBOBJC_BLOCKS_PRIVATE_H_INCLUDED__ +#define __LIBOBJC_BLOCKS_PRIVATE_H_INCLUDED__ + +/* + * This header file exposes some implementation details of the blocks runtime + * that are needed, e.g., by libdispatch. + */ + + +/** + * Block descriptor that contains copy and dispose operations. + */ +struct Block_descriptor +{ + /** + * Reserved for future use. Currently always 0. + */ + unsigned long int reserved; + /** Size of the block. */ + unsigned long int size; + /** + * Copy function, generated by the compiler to help copy the block if it + * contains nontrivial copy operations. + */ + void (*copy_helper)(void *dst, void *src); + /** + * Dispose function, generated by the compiler to help copy the block if it + * contains nontrivial destructors. + */ + void (*dispose_helper)(void *src); + /** + * Objective-C type encoding of the block. + */ + const char *encoding; +}; + +// Helper structure +struct Block_layout +{ + /** + * Class pointer. Always initialised to &_NSConcreteStackBlock for blocks + * that are created on the stack or &_NSConcreteGlobalBlock for blocks that + * are created in global storage. + */ + void *isa; + /** + * Flags. See the block_flags enumerated type for possible values. + */ + int flags; + /** + * Reserved - always initialised to 0 by the compiler. Used for the + * reference count in this implementation. + */ + int reserved; + /** + * The function that implements the block. The first argument is this + * structure, the subsequent arguments are the block's explicit parameters. + * If the BLOCK_USE_SRET flag is set, there is an additional hidden + * argument, which is a pointer to the space on the stack allocated to hold + * the return value. + */ + void (*invoke)(void *, ...); + /** + * The block's descriptor. This is either Block_descriptor_basic or + * Block_descriptor, depending on whether the + * BLOCK_HAS_COPY_DISPOSE flag is set. + */ + struct Block_descriptor *descriptor; + /** + * Block variables are appended to this structure. + */ +}; + + + +#ifndef __OBJC_RUNTIME_INTERNAL__ +/* + * Deprecated Block_basic datastructure needed by libdispatch + */ +struct Block_basic { + void *isa; + int Block_flags; + int Block_size; + void (*Block_invoke)(void *); + void (*Block_copy)(void *dst, void *src); + void (*Block_dispose)(void *); +}; +#endif // __OBJC_RUNTIME_INTERNAL__ +#endif //__LIBOBJC_BLOCKS_PRIVATE_H_INCLUDED__ +