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