/* * Block_private.h * * SPI for Blocks * * Copyright (c) 2008-2010 Apple Inc. All rights reserved. * * @APPLE_LLVM_LICENSE_HEADER@ * */ #ifndef _BLOCK_PRIVATE_H_ #define _BLOCK_PRIVATE_H_ #include #include #include #include #include #include #if __cplusplus extern "C" { #endif enum { BLOCK_DEALLOCATING = (0x0001), // runtime BLOCK_REFCOUNT_MASK = (0xfffe), // runtime BLOCK_NEEDS_FREE = (1 << 24), // runtime BLOCK_HAS_COPY_DISPOSE = (1 << 25), // compiler BLOCK_HAS_CTOR = (1 << 26), // compiler: helpers have C++ code BLOCK_IS_GC = (1 << 27), // runtime BLOCK_IS_GLOBAL = (1 << 28), // compiler BLOCK_USE_STRET = (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE BLOCK_HAS_SIGNATURE = (1 << 30) // compiler }; // revised new layout #define BLOCK_DESCRIPTOR_1 1 struct Block_descriptor_1 { unsigned long int reserved; unsigned long int size; }; #define BLOCK_DESCRIPTOR_2 1 struct Block_descriptor_2 { // requires BLOCK_HAS_COPY_DISPOSE void (*copy)(void *dst, const void *src); void (*dispose)(const void *); }; #define BLOCK_DESCRIPTOR_3 1 struct Block_descriptor_3 { // requires BLOCK_HAS_SIGNATURE const char *signature; const char *layout; }; struct Block_layout { void *isa; volatile int flags; // contains ref count int reserved; void (*invoke)(void *, ...); struct Block_descriptor_1 *descriptor; // imported variables }; struct Block_byref { void *isa; struct Block_byref *forwarding; volatile int flags; // contains ref count unsigned int size; void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src); void (*byref_destroy)(struct Block_byref *); // long shared[0]; }; struct Block_byref_header { void *isa; struct Block_byref *forwarding; int flags; unsigned int size; }; // Runtime support functions used by compiler when generating copy/dispose helpers enum { // see function implementation for a more complete description of these fields and combinations BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ... BLOCK_FIELD_IS_BLOCK = 7, // a block variable BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable BLOCK_FIELD_IS_WEAK = 16, // declared __weak, only used in byref copy helpers BLOCK_BYREF_CALLER = 128, // called from __block (byref) copy/dispose support routines. }; enum { BLOCK_ALL_COPY_DISPOSE_FLAGS = BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_BLOCK | BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK | BLOCK_BYREF_CALLER }; // Runtime entry point called by compiler when assigning objects inside copy helper routines BLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags); // BLOCK_FIELD_IS_BYREF is only used from within block copy helpers // runtime entry point called by the compiler when disposing of objects inside dispose helper routine BLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags); // Other support functions // runtime entry to get total size of a closure BLOCK_EXPORT size_t Block_size(void *aBlock); // indicates whether block was compiled with compiler that sets the ABI related metadata bits BLOCK_EXPORT bool _Block_has_signature(void *aBlock) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); // returns TRUE if return value of block is on the stack, FALSE otherwise BLOCK_EXPORT bool _Block_use_stret(void *aBlock) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); // Returns a string describing the block's parameter and return types. // The encoding scheme is the same as Objective-C @encode. // Returns NULL for blocks compiled with some compilers. BLOCK_EXPORT const char * _Block_signature(void *aBlock) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); // Returns a string describing the block's GC layout. // Returns NULL for blocks compiled with some compilers. BLOCK_EXPORT const char * _Block_layout(void *aBlock) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); // Callable only from the ARR weak subsystem while in exclusion zone BLOCK_EXPORT bool _Block_tryRetain(const void *aBlock) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); // Callable only from the ARR weak subsystem while in exclusion zone BLOCK_EXPORT bool _Block_isDeallocating(const void *aBlock) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); // the raw data space for runtime classes for blocks // class+meta used for stack, malloc, and collectable based blocks BLOCK_EXPORT void * _NSConcreteMallocBlock[32] __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); BLOCK_EXPORT void * _NSConcreteAutoBlock[32] __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32] __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32] __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); // declared in Block.h // BLOCK_EXPORT void * _NSConcreteGlobalBlock[32]; // BLOCK_EXPORT void * _NSConcreteStackBlock[32]; // the intercept routines that must be used under GC BLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject), void (*setHasRefcount)(const void *, const bool), void (*gc_assign_strong)(void *, void **), void (*gc_assign_weak)(const void *, void *), void (*gc_memmove)(void *, void *, unsigned long)); // earlier version, now simply transitional BLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject), void (*setHasRefcount)(const void *, const bool), void (*gc_assign_strong)(void *, void **), void (*gc_assign_weak)(const void *, void *)); BLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *), void (*release)(const void *)); struct Block_callbacks_RR { size_t size; // size == sizeof(struct Block_callbacks_RR) void (*retain)(const void *); void (*release)(const void *); void (*destructInstance)(const void *); }; typedef struct Block_callbacks_RR Block_callbacks_RR; BLOCK_EXPORT void _Block_use_RR2(const Block_callbacks_RR *callbacks); // make a collectable GC heap based Block. Not useful under non-GC. BLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock); // thread-unsafe diagnostic BLOCK_EXPORT const char *_Block_dump(const void *block); // Obsolete // first layout struct Block_basic { void *isa; int Block_flags; // int32_t int Block_size; // XXX should be packed into Block_flags void (*Block_invoke)(void *); void (*Block_copy)(void *dst, void *src); // iff BLOCK_HAS_COPY_DISPOSE void (*Block_dispose)(void *); // iff BLOCK_HAS_COPY_DISPOSE //long params[0]; // where const imports, __block storage references, etc. get laid down }; #if __cplusplus } #endif #endif