10b57cec5SDimitry Andric /* 20b57cec5SDimitry Andric * Block_private.h 30b57cec5SDimitry Andric * 40b57cec5SDimitry Andric * Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge, 50b57cec5SDimitry Andric * to any person obtaining a copy of this software and associated documentation 60b57cec5SDimitry Andric * files (the "Software"), to deal in the Software without restriction, 70b57cec5SDimitry Andric * including without limitation the rights to use, copy, modify, merge, publish, 80b57cec5SDimitry Andric * distribute, sublicense, and/or sell copies of the Software, and to permit 90b57cec5SDimitry Andric * persons to whom the Software is furnished to do so, subject to the following 100b57cec5SDimitry Andric * conditions: 110b57cec5SDimitry Andric * 120b57cec5SDimitry Andric * The above copyright notice and this permission notice shall be included in 130b57cec5SDimitry Andric * all copies or substantial portions of the Software. 140b57cec5SDimitry Andric * 150b57cec5SDimitry Andric * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 160b57cec5SDimitry Andric * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 170b57cec5SDimitry Andric * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 180b57cec5SDimitry Andric * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 190b57cec5SDimitry Andric * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 200b57cec5SDimitry Andric * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 210b57cec5SDimitry Andric * SOFTWARE. 220b57cec5SDimitry Andric * 230b57cec5SDimitry Andric */ 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric #ifndef _BLOCK_PRIVATE_H_ 260b57cec5SDimitry Andric #define _BLOCK_PRIVATE_H_ 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #if !defined(BLOCK_EXPORT) 290b57cec5SDimitry Andric # if defined(__cplusplus) 300b57cec5SDimitry Andric # define BLOCK_EXPORT extern "C" 310b57cec5SDimitry Andric # else 320b57cec5SDimitry Andric # define BLOCK_EXPORT extern 330b57cec5SDimitry Andric # endif 340b57cec5SDimitry Andric #endif 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric #ifndef _MSC_VER 370b57cec5SDimitry Andric #include <stdbool.h> 380b57cec5SDimitry Andric #else 390b57cec5SDimitry Andric /* MSVC doesn't have <stdbool.h>. Compensate. */ 400b57cec5SDimitry Andric typedef char bool; 410b57cec5SDimitry Andric #define true (bool)1 420b57cec5SDimitry Andric #define false (bool)0 430b57cec5SDimitry Andric #endif 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric #if defined(__cplusplus) 460b57cec5SDimitry Andric extern "C" { 470b57cec5SDimitry Andric #endif 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric enum { 510b57cec5SDimitry Andric BLOCK_REFCOUNT_MASK = (0xffff), 520b57cec5SDimitry Andric BLOCK_NEEDS_FREE = (1 << 24), 530b57cec5SDimitry Andric BLOCK_HAS_COPY_DISPOSE = (1 << 25), 540b57cec5SDimitry Andric BLOCK_HAS_CTOR = (1 << 26), /* Helpers have C++ code. */ 550b57cec5SDimitry Andric BLOCK_IS_GC = (1 << 27), 560b57cec5SDimitry Andric BLOCK_IS_GLOBAL = (1 << 28), 570b57cec5SDimitry Andric BLOCK_HAS_DESCRIPTOR = (1 << 29) 580b57cec5SDimitry Andric }; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric /* Revised new layout. */ 620b57cec5SDimitry Andric struct Block_descriptor { 630b57cec5SDimitry Andric unsigned long int reserved; 640b57cec5SDimitry Andric unsigned long int size; 650b57cec5SDimitry Andric void (*copy)(void *dst, void *src); 660b57cec5SDimitry Andric void (*dispose)(void *); 670b57cec5SDimitry Andric }; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric struct Block_layout { 710b57cec5SDimitry Andric void *isa; 720b57cec5SDimitry Andric int flags; 730b57cec5SDimitry Andric int reserved; 740b57cec5SDimitry Andric void (*invoke)(void *, ...); 750b57cec5SDimitry Andric struct Block_descriptor *descriptor; 760b57cec5SDimitry Andric /* Imported variables. */ 770b57cec5SDimitry Andric }; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric struct Block_byref { 810b57cec5SDimitry Andric void *isa; 820b57cec5SDimitry Andric struct Block_byref *forwarding; 830b57cec5SDimitry Andric int flags; /* refcount; */ 840b57cec5SDimitry Andric int size; 850b57cec5SDimitry Andric void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src); 860b57cec5SDimitry Andric void (*byref_destroy)(struct Block_byref *); 870b57cec5SDimitry Andric /* long shared[0]; */ 880b57cec5SDimitry Andric }; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric struct Block_byref_header { 920b57cec5SDimitry Andric void *isa; 930b57cec5SDimitry Andric struct Block_byref *forwarding; 940b57cec5SDimitry Andric int flags; 950b57cec5SDimitry Andric int size; 960b57cec5SDimitry Andric }; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric /* Runtime support functions used by compiler when generating copy/dispose helpers. */ 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric enum { 1020b57cec5SDimitry Andric /* See function implementation for a more complete description of these fields and combinations */ 1030b57cec5SDimitry Andric BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), block, ... */ 1040b57cec5SDimitry Andric BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 1050b57cec5SDimitry Andric BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the __block variable */ 1060b57cec5SDimitry Andric BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy helpers */ 1070b57cec5SDimitry Andric BLOCK_BYREF_CALLER = 128 /* called from __block (byref) copy/dispose support routines. */ 1080b57cec5SDimitry Andric }; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric /* Runtime entry point called by compiler when assigning objects inside copy helper routines */ 1110b57cec5SDimitry Andric BLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags); 1120b57cec5SDimitry Andric /* BLOCK_FIELD_IS_BYREF is only used from within block copy helpers */ 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric /* runtime entry point called by the compiler when disposing of objects inside dispose helper routine */ 1160b57cec5SDimitry Andric BLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric /* Other support functions */ 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /* Runtime entry to get total size of a closure */ 1230b57cec5SDimitry Andric BLOCK_EXPORT unsigned long int Block_size(void *block_basic); 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric /* the raw data space for runtime classes for blocks */ 1280b57cec5SDimitry Andric /* class+meta used for stack, malloc, and collectable based blocks */ 1290b57cec5SDimitry Andric BLOCK_EXPORT void * _NSConcreteStackBlock[32]; 1300b57cec5SDimitry Andric BLOCK_EXPORT void * _NSConcreteMallocBlock[32]; 1310b57cec5SDimitry Andric BLOCK_EXPORT void * _NSConcreteAutoBlock[32]; 1320b57cec5SDimitry Andric BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32]; 1330b57cec5SDimitry Andric BLOCK_EXPORT void * _NSConcreteGlobalBlock[32]; 1340b57cec5SDimitry Andric BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32]; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric /* the intercept routines that must be used under GC */ 1380b57cec5SDimitry Andric BLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject), 1390b57cec5SDimitry Andric void (*setHasRefcount)(const void *, const bool), 1400b57cec5SDimitry Andric void (*gc_assign_strong)(void *, void **), 1410b57cec5SDimitry Andric void (*gc_assign_weak)(const void *, void *), 1420b57cec5SDimitry Andric void (*gc_memmove)(void *, void *, unsigned long)); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric /* earlier version, now simply transitional */ 1450b57cec5SDimitry Andric BLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject), 1460b57cec5SDimitry Andric void (*setHasRefcount)(const void *, const bool), 1470b57cec5SDimitry Andric void (*gc_assign_strong)(void *, void **), 1480b57cec5SDimitry Andric void (*gc_assign_weak)(const void *, void *)); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric BLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *), 1510b57cec5SDimitry Andric void (*release)(const void *)); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric /* make a collectable GC heap based Block. Not useful under non-GC. */ 1540b57cec5SDimitry Andric BLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric /* thread-unsafe diagnostic */ 1570b57cec5SDimitry Andric BLOCK_EXPORT const char *_Block_dump(const void *block); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric /* Obsolete */ 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric /* first layout */ 1630b57cec5SDimitry Andric struct Block_basic { 1640b57cec5SDimitry Andric void *isa; 1650b57cec5SDimitry Andric int Block_flags; /* int32_t */ 1660b57cec5SDimitry Andric int Block_size; /* XXX should be packed into Block_flags */ 1670b57cec5SDimitry Andric void (*Block_invoke)(void *); 1680b57cec5SDimitry Andric void (*Block_copy)(void *dst, void *src); /* iff BLOCK_HAS_COPY_DISPOSE */ 1690b57cec5SDimitry Andric void (*Block_dispose)(void *); /* iff BLOCK_HAS_COPY_DISPOSE */ 1700b57cec5SDimitry Andric /* long params[0]; // where const imports, __block storage references, etc. get laid down */ 1710b57cec5SDimitry Andric }; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric #if defined(__cplusplus) 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric #endif 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric #endif /* _BLOCK_PRIVATE_H_ */ 180