1*3cab2bb3Spatrick /* 2*3cab2bb3Spatrick * Block_private.h 3*3cab2bb3Spatrick * 4*3cab2bb3Spatrick * Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge, 5*3cab2bb3Spatrick * to any person obtaining a copy of this software and associated documentation 6*3cab2bb3Spatrick * files (the "Software"), to deal in the Software without restriction, 7*3cab2bb3Spatrick * including without limitation the rights to use, copy, modify, merge, publish, 8*3cab2bb3Spatrick * distribute, sublicense, and/or sell copies of the Software, and to permit 9*3cab2bb3Spatrick * persons to whom the Software is furnished to do so, subject to the following 10*3cab2bb3Spatrick * conditions: 11*3cab2bb3Spatrick * 12*3cab2bb3Spatrick * The above copyright notice and this permission notice shall be included in 13*3cab2bb3Spatrick * all copies or substantial portions of the Software. 14*3cab2bb3Spatrick * 15*3cab2bb3Spatrick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*3cab2bb3Spatrick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*3cab2bb3Spatrick * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18*3cab2bb3Spatrick * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19*3cab2bb3Spatrick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20*3cab2bb3Spatrick * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21*3cab2bb3Spatrick * SOFTWARE. 22*3cab2bb3Spatrick * 23*3cab2bb3Spatrick */ 24*3cab2bb3Spatrick 25*3cab2bb3Spatrick #ifndef _BLOCK_PRIVATE_H_ 26*3cab2bb3Spatrick #define _BLOCK_PRIVATE_H_ 27*3cab2bb3Spatrick 28*3cab2bb3Spatrick #if !defined(BLOCK_EXPORT) 29*3cab2bb3Spatrick # if defined(__cplusplus) 30*3cab2bb3Spatrick # define BLOCK_EXPORT extern "C" 31*3cab2bb3Spatrick # else 32*3cab2bb3Spatrick # define BLOCK_EXPORT extern 33*3cab2bb3Spatrick # endif 34*3cab2bb3Spatrick #endif 35*3cab2bb3Spatrick 36*3cab2bb3Spatrick #ifndef _MSC_VER 37*3cab2bb3Spatrick #include <stdbool.h> 38*3cab2bb3Spatrick #else 39*3cab2bb3Spatrick /* MSVC doesn't have <stdbool.h>. Compensate. */ 40*3cab2bb3Spatrick typedef char bool; 41*3cab2bb3Spatrick #define true (bool)1 42*3cab2bb3Spatrick #define false (bool)0 43*3cab2bb3Spatrick #endif 44*3cab2bb3Spatrick 45*3cab2bb3Spatrick #if defined(__cplusplus) 46*3cab2bb3Spatrick extern "C" { 47*3cab2bb3Spatrick #endif 48*3cab2bb3Spatrick 49*3cab2bb3Spatrick 50*3cab2bb3Spatrick enum { 51*3cab2bb3Spatrick BLOCK_REFCOUNT_MASK = (0xffff), 52*3cab2bb3Spatrick BLOCK_NEEDS_FREE = (1 << 24), 53*3cab2bb3Spatrick BLOCK_HAS_COPY_DISPOSE = (1 << 25), 54*3cab2bb3Spatrick BLOCK_HAS_CTOR = (1 << 26), /* Helpers have C++ code. */ 55*3cab2bb3Spatrick BLOCK_IS_GC = (1 << 27), 56*3cab2bb3Spatrick BLOCK_IS_GLOBAL = (1 << 28), 57*3cab2bb3Spatrick BLOCK_HAS_DESCRIPTOR = (1 << 29) 58*3cab2bb3Spatrick }; 59*3cab2bb3Spatrick 60*3cab2bb3Spatrick 61*3cab2bb3Spatrick /* Revised new layout. */ 62*3cab2bb3Spatrick struct Block_descriptor { 63*3cab2bb3Spatrick unsigned long int reserved; 64*3cab2bb3Spatrick unsigned long int size; 65*3cab2bb3Spatrick void (*copy)(void *dst, void *src); 66*3cab2bb3Spatrick void (*dispose)(void *); 67*3cab2bb3Spatrick }; 68*3cab2bb3Spatrick 69*3cab2bb3Spatrick 70*3cab2bb3Spatrick struct Block_layout { 71*3cab2bb3Spatrick void *isa; 72*3cab2bb3Spatrick int flags; 73*3cab2bb3Spatrick int reserved; 74*3cab2bb3Spatrick void (*invoke)(void *, ...); 75*3cab2bb3Spatrick struct Block_descriptor *descriptor; 76*3cab2bb3Spatrick /* Imported variables. */ 77*3cab2bb3Spatrick }; 78*3cab2bb3Spatrick 79*3cab2bb3Spatrick 80*3cab2bb3Spatrick struct Block_byref { 81*3cab2bb3Spatrick void *isa; 82*3cab2bb3Spatrick struct Block_byref *forwarding; 83*3cab2bb3Spatrick int flags; /* refcount; */ 84*3cab2bb3Spatrick int size; 85*3cab2bb3Spatrick void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src); 86*3cab2bb3Spatrick void (*byref_destroy)(struct Block_byref *); 87*3cab2bb3Spatrick /* long shared[0]; */ 88*3cab2bb3Spatrick }; 89*3cab2bb3Spatrick 90*3cab2bb3Spatrick 91*3cab2bb3Spatrick struct Block_byref_header { 92*3cab2bb3Spatrick void *isa; 93*3cab2bb3Spatrick struct Block_byref *forwarding; 94*3cab2bb3Spatrick int flags; 95*3cab2bb3Spatrick int size; 96*3cab2bb3Spatrick }; 97*3cab2bb3Spatrick 98*3cab2bb3Spatrick 99*3cab2bb3Spatrick /* Runtime support functions used by compiler when generating copy/dispose helpers. */ 100*3cab2bb3Spatrick 101*3cab2bb3Spatrick enum { 102*3cab2bb3Spatrick /* See function implementation for a more complete description of these fields and combinations */ 103*3cab2bb3Spatrick BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), block, ... */ 104*3cab2bb3Spatrick BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 105*3cab2bb3Spatrick BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the __block variable */ 106*3cab2bb3Spatrick BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy helpers */ 107*3cab2bb3Spatrick BLOCK_BYREF_CALLER = 128 /* called from __block (byref) copy/dispose support routines. */ 108*3cab2bb3Spatrick }; 109*3cab2bb3Spatrick 110*3cab2bb3Spatrick /* Runtime entry point called by compiler when assigning objects inside copy helper routines */ 111*3cab2bb3Spatrick BLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags); 112*3cab2bb3Spatrick /* BLOCK_FIELD_IS_BYREF is only used from within block copy helpers */ 113*3cab2bb3Spatrick 114*3cab2bb3Spatrick 115*3cab2bb3Spatrick /* runtime entry point called by the compiler when disposing of objects inside dispose helper routine */ 116*3cab2bb3Spatrick BLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags); 117*3cab2bb3Spatrick 118*3cab2bb3Spatrick 119*3cab2bb3Spatrick 120*3cab2bb3Spatrick /* Other support functions */ 121*3cab2bb3Spatrick 122*3cab2bb3Spatrick /* Runtime entry to get total size of a closure */ 123*3cab2bb3Spatrick BLOCK_EXPORT unsigned long int Block_size(void *block_basic); 124*3cab2bb3Spatrick 125*3cab2bb3Spatrick 126*3cab2bb3Spatrick 127*3cab2bb3Spatrick /* the raw data space for runtime classes for blocks */ 128*3cab2bb3Spatrick /* class+meta used for stack, malloc, and collectable based blocks */ 129*3cab2bb3Spatrick BLOCK_EXPORT void * _NSConcreteStackBlock[32]; 130*3cab2bb3Spatrick BLOCK_EXPORT void * _NSConcreteMallocBlock[32]; 131*3cab2bb3Spatrick BLOCK_EXPORT void * _NSConcreteAutoBlock[32]; 132*3cab2bb3Spatrick BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32]; 133*3cab2bb3Spatrick BLOCK_EXPORT void * _NSConcreteGlobalBlock[32]; 134*3cab2bb3Spatrick BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32]; 135*3cab2bb3Spatrick 136*3cab2bb3Spatrick 137*3cab2bb3Spatrick /* the intercept routines that must be used under GC */ 138*3cab2bb3Spatrick BLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject), 139*3cab2bb3Spatrick void (*setHasRefcount)(const void *, const bool), 140*3cab2bb3Spatrick void (*gc_assign_strong)(void *, void **), 141*3cab2bb3Spatrick void (*gc_assign_weak)(const void *, void *), 142*3cab2bb3Spatrick void (*gc_memmove)(void *, void *, unsigned long)); 143*3cab2bb3Spatrick 144*3cab2bb3Spatrick /* earlier version, now simply transitional */ 145*3cab2bb3Spatrick BLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject), 146*3cab2bb3Spatrick void (*setHasRefcount)(const void *, const bool), 147*3cab2bb3Spatrick void (*gc_assign_strong)(void *, void **), 148*3cab2bb3Spatrick void (*gc_assign_weak)(const void *, void *)); 149*3cab2bb3Spatrick 150*3cab2bb3Spatrick BLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *), 151*3cab2bb3Spatrick void (*release)(const void *)); 152*3cab2bb3Spatrick 153*3cab2bb3Spatrick /* make a collectable GC heap based Block. Not useful under non-GC. */ 154*3cab2bb3Spatrick BLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock); 155*3cab2bb3Spatrick 156*3cab2bb3Spatrick /* thread-unsafe diagnostic */ 157*3cab2bb3Spatrick BLOCK_EXPORT const char *_Block_dump(const void *block); 158*3cab2bb3Spatrick 159*3cab2bb3Spatrick 160*3cab2bb3Spatrick /* Obsolete */ 161*3cab2bb3Spatrick 162*3cab2bb3Spatrick /* first layout */ 163*3cab2bb3Spatrick struct Block_basic { 164*3cab2bb3Spatrick void *isa; 165*3cab2bb3Spatrick int Block_flags; /* int32_t */ 166*3cab2bb3Spatrick int Block_size; /* XXX should be packed into Block_flags */ 167*3cab2bb3Spatrick void (*Block_invoke)(void *); 168*3cab2bb3Spatrick void (*Block_copy)(void *dst, void *src); /* iff BLOCK_HAS_COPY_DISPOSE */ 169*3cab2bb3Spatrick void (*Block_dispose)(void *); /* iff BLOCK_HAS_COPY_DISPOSE */ 170*3cab2bb3Spatrick /* long params[0]; // where const imports, __block storage references, etc. get laid down */ 171*3cab2bb3Spatrick }; 172*3cab2bb3Spatrick 173*3cab2bb3Spatrick 174*3cab2bb3Spatrick #if defined(__cplusplus) 175*3cab2bb3Spatrick } 176*3cab2bb3Spatrick #endif 177*3cab2bb3Spatrick 178*3cab2bb3Spatrick 179*3cab2bb3Spatrick #endif /* _BLOCK_PRIVATE_H_ */ 180