18cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar/* 2b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * runtime.c 3b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * 4b1c07156bab839c0502789f09654ec5da8d33c39Blaine Garst * Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge, 5b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * to any person obtaining a copy of this software and associated documentation 6b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * files (the "Software"), to deal in the Software without restriction, 7b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * including without limitation the rights to use, copy, modify, merge, publish, 8b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * distribute, sublicense, and/or sell copies of the Software, and to permit 9b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * persons to whom the Software is furnished to do so, subject to the following 10b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * conditions: 11b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * 12b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * The above copyright notice and this permission notice shall be included in 13b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * all copies or substantial portions of the Software. 14b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * 15b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar * SOFTWARE. 228cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * 238cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar */ 248cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 258cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#include "Block_private.h" 268cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#include <stdio.h> 278cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#include <stdlib.h> 288cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#include <string.h> 298cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#include <stdint.h> 308cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 31b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#include "config.h" 32b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen 33b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#ifdef HAVE_AVAILABILITY_MACROS_H 34b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#include <AvailabilityMacros.h> 35962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* HAVE_AVAILABILITY_MACROS_H */ 36b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen 37b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#ifdef HAVE_TARGET_CONDITIONALS_H 38b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#include <TargetConditionals.h> 39962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* HAVE_TARGET_CONDITIONALS_H */ 40b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen 41b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#if defined(HAVE_OSATOMIC_COMPARE_AND_SWAP_INT) && defined(HAVE_OSATOMIC_COMPARE_AND_SWAP_LONG) 42962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan 43b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#ifdef HAVE_LIBKERN_OSATOMIC_H 448cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#include <libkern/OSAtomic.h> 45962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* HAVE_LIBKERN_OSATOMIC_H */ 46962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan 47ffd69e7b181a486cbba10deb386558cf3ff5e24aCharles Davis#elif defined(__WIN32__) || defined(_WIN32) 488cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#define _CRT_SECURE_NO_WARNINGS 1 498cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#include <windows.h> 50962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan 51962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghanstatic __inline bool OSAtomicCompareAndSwapLong(long oldl, long newl, long volatile *dst) { 52e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan /* fixme barrier is overkill -- see objc-os.h */ 538cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar long original = InterlockedCompareExchange(dst, newl, oldl); 548cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return (original == oldl); 558cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 568cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 57962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghanstatic __inline bool OSAtomicCompareAndSwapInt(int oldi, int newi, int volatile *dst) { 58e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan /* fixme barrier is overkill -- see objc-os.h */ 598cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar int original = InterlockedCompareExchange(dst, newi, oldi); 608cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return (original == oldi); 618cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 62962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan 63962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 64962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Check to see if the GCC atomic built-ins are available. If we're on 65e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan * a 64-bit system, make sure we have an 8-byte atomic function 66e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan * available. 67962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * 68e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan */ 69962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan 70b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#elif defined(HAVE_SYNC_BOOL_COMPARE_AND_SWAP_INT) && defined(HAVE_SYNC_BOOL_COMPARE_AND_SWAP_LONG) 71962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan 72962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghanstatic __inline bool OSAtomicCompareAndSwapLong(long oldl, long newl, long volatile *dst) { 73e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan return __sync_bool_compare_and_swap(dst, oldl, newl); 74e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan} 75e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan 76962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghanstatic __inline bool OSAtomicCompareAndSwapInt(int oldi, int newi, int volatile *dst) { 77e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan return __sync_bool_compare_and_swap(dst, oldi, newi); 78e8ce595140fa3f107db10a6b4d9184f7277e58c0Edward O'Callaghan} 79962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan 80b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#else 81b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#error unknown atomic compare-and-swap primitive 82962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* HAVE_OSATOMIC_COMPARE_AND_SWAP_INT && HAVE_OSATOMIC_COMPARE_AND_SWAP_LONG */ 838cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 848cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 85962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 86962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Globals: 87962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 888cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 898cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void *_Block_copy_class = _NSConcreteMallocBlock; 908cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void *_Block_copy_finalizing_class = _NSConcreteMallocBlock; 918cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic int _Block_copy_flag = BLOCK_NEEDS_FREE; 928cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic int _Byref_flag_initial_value = BLOCK_NEEDS_FREE | 2; 938cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 948cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic const int WANTS_ONE = (1 << 16); 958cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 968cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic bool isGC = false; 978cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 98962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 99962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Internal Utilities: 100962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 1018cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1028cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#if 0 1038cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic unsigned long int latching_incr_long(unsigned long int *where) { 1048cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar while (1) { 1058cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar unsigned long int old_value = *(volatile unsigned long int *)where; 1068cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) { 1078cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return BLOCK_REFCOUNT_MASK; 1088cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1098cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (OSAtomicCompareAndSwapLong(old_value, old_value+1, (volatile long int *)where)) { 1108cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return old_value+1; 1118cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1128cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1138cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 114962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* if 0 */ 1158cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1168cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic int latching_incr_int(int *where) { 1178cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar while (1) { 1188cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar int old_value = *(volatile int *)where; 1198cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) { 1208cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return BLOCK_REFCOUNT_MASK; 1218cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1228cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (OSAtomicCompareAndSwapInt(old_value, old_value+1, (volatile int *)where)) { 1238cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return old_value+1; 1248cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1258cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1268cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 1278cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1288cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#if 0 1298cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic int latching_decr_long(unsigned long int *where) { 1308cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar while (1) { 1318cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar unsigned long int old_value = *(volatile int *)where; 1328cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) { 1338cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return BLOCK_REFCOUNT_MASK; 1348cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1358cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if ((old_value & BLOCK_REFCOUNT_MASK) == 0) { 1368cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return 0; 1378cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1388cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (OSAtomicCompareAndSwapLong(old_value, old_value-1, (volatile long int *)where)) { 1398cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return old_value-1; 1408cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1418cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1428cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 143962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* if 0 */ 1448cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1458cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic int latching_decr_int(int *where) { 1468cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar while (1) { 1478cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar int old_value = *(volatile int *)where; 1488cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) { 1498cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return BLOCK_REFCOUNT_MASK; 1508cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1518cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if ((old_value & BLOCK_REFCOUNT_MASK) == 0) { 1528cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return 0; 1538cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1548cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (OSAtomicCompareAndSwapInt(old_value, old_value-1, (volatile int *)where)) { 1558cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return old_value-1; 1568cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1578cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 1588cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 1598cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1608cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 161962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 162962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * GC support stub routines: 163962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 164b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#if 0 1658cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#pragma mark GC Support Routines 166962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* if 0 */ 1678cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1688cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1698cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void *_Block_alloc_default(const unsigned long size, const bool initialCountIsOne, const bool isObject) { 1708cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return malloc(size); 1718cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 1728cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1738cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_assign_default(void *value, void **destptr) { 1748cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar *destptr = value; 1758cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 1768cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1778cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_setHasRefcount_default(const void *ptr, const bool hasRefcount) { 1788cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 1798cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1808cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_do_nothing(const void *aBlock) { } 1818cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1828cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_retain_object_default(const void *ptr) { 1838cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (!ptr) return; 1848cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 1858cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1868cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_release_object_default(const void *ptr) { 1878cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (!ptr) return; 1888cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 1898cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1908cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_assign_weak_default(const void *ptr, void *dest) { 1918cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar *(void **)dest = (void *)ptr; 1928cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 1938cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1948cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_memmove_default(void *dst, void *src, unsigned long size) { 1958cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar memmove(dst, src, (size_t)size); 1968cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 1978cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 1988cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_memmove_gc_broken(void *dest, void *src, unsigned long size) { 1998cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void **destp = (void **)dest; 2008cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void **srcp = (void **)src; 2018cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar while (size) { 2028cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_assign_default(*srcp, destp); 2038cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar destp++; 2048cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar srcp++; 2058cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar size -= sizeof(void *); 2068cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 2078cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 2088cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 209962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 210962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * GC support callout functions - initially set to stub routines: 211962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 2128cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 2138cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void *(*_Block_allocator)(const unsigned long, const bool isOne, const bool isObject) = _Block_alloc_default; 2148cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void (*_Block_deallocator)(const void *) = (void (*)(const void *))free; 2158cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void (*_Block_assign)(void *value, void **destptr) = _Block_assign_default; 2168cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void (*_Block_setHasRefcount)(const void *ptr, const bool hasRefcount) = _Block_setHasRefcount_default; 2178cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void (*_Block_retain_object)(const void *ptr) = _Block_retain_object_default; 2188cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void (*_Block_release_object)(const void *ptr) = _Block_release_object_default; 2198cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void (*_Block_assign_weak)(const void *dest, void *ptr) = _Block_assign_weak_default; 2208cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void (*_Block_memmove)(void *dest, void *src, unsigned long size) = _Block_memmove_default; 2218cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 2228cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 223962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 224962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * GC support SPI functions - called from ObjC runtime and CoreFoundation: 225962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 2268cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 227962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* Public SPI 228962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Called from objc-auto to turn on GC. 229962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * version 3, 4 arg, but changed 1st arg 230962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 2318cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarvoid _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject), 2328cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void (*setHasRefcount)(const void *, const bool), 2338cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void (*gc_assign)(void *, void **), 2348cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void (*gc_assign_weak)(const void *, void *), 2358cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void (*gc_memmove)(void *, void *, unsigned long)) { 2368cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 2378cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar isGC = true; 2388cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_allocator = alloc; 2398cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_deallocator = _Block_do_nothing; 2408cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_assign = gc_assign; 2418cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_copy_flag = BLOCK_IS_GC; 2428cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_copy_class = _NSConcreteAutoBlock; 243962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan /* blocks with ctors & dtors need to have the dtor run from a class with a finalizer */ 2448cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_copy_finalizing_class = _NSConcreteFinalizingBlock; 2458cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_setHasRefcount = setHasRefcount; 2468cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Byref_flag_initial_value = BLOCK_IS_GC; // no refcount 2478cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_retain_object = _Block_do_nothing; 2488cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_release_object = _Block_do_nothing; 2498cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_assign_weak = gc_assign_weak; 2508cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_memmove = gc_memmove; 2518cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 2528cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 253962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* transitional */ 2548cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarvoid _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject), 2558cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void (*setHasRefcount)(const void *, const bool), 2568cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void (*gc_assign)(void *, void **), 2578cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void (*gc_assign_weak)(const void *, void *)) { 258962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan /* until objc calls _Block_use_GC it will call us; supply a broken internal memmove implementation until then */ 2598cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_use_GC(alloc, setHasRefcount, gc_assign, gc_assign_weak, _Block_memmove_gc_broken); 2608cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 2618cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 2628cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 263962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 264962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Called from objc-auto to alternatively turn on retain/release. 265962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Prior to this the only "object" support we can provide is for those 266962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * super special objects that live in libSystem, namely dispatch queues. 267962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Blocks and Block_byrefs have their own special entry points. 268962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * 269962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 2708cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarvoid _Block_use_RR( void (*retain)(const void *), 2718cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar void (*release)(const void *)) { 2728cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_retain_object = retain; 2738cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_release_object = release; 2748cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 2758cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 276962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 277962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Internal Support routines for copying: 278962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 2798cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 280b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#if 0 2818cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#pragma mark Copy/Release support 282962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* if 0 */ 2838cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 284962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* Copy, or bump refcount, of a block. If really copying, call the copy helper if present. */ 2858cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void *_Block_copy_internal(const void *arg, const int flags) { 2868cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_layout *aBlock; 2878cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar const bool wantsOne = (WANTS_ONE & flags) == WANTS_ONE; 2888cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 2898cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("_Block_copy_internal(%p, %x)\n", arg, flags); 2908cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (!arg) return NULL; 2918cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 2928cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 2938cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // The following would be better done as a switch statement 2948cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar aBlock = (struct Block_layout *)arg; 2958cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (aBlock->flags & BLOCK_NEEDS_FREE) { 2968cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // latches on high 2978cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar latching_incr_int(&aBlock->flags); 2988cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return aBlock; 2998cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3008cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if (aBlock->flags & BLOCK_IS_GC) { 3018cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // GC refcounting is expensive so do most refcounting here. 3028cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (wantsOne && ((latching_incr_int(&aBlock->flags) & BLOCK_REFCOUNT_MASK) == 1)) { 3038cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // Tell collector to hang on this - it will bump the GC refcount version 3048cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_setHasRefcount(aBlock, true); 3058cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3068cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return aBlock; 3078cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3088cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if (aBlock->flags & BLOCK_IS_GLOBAL) { 3098cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return aBlock; 3108cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3118cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 3128cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // Its a stack block. Make a copy. 3138cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (!isGC) { 3148cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_layout *result = malloc(aBlock->descriptor->size); 3158cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (!result) return (void *)0; 3168cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first 3178cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // reset refcount 3188cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar result->flags &= ~(BLOCK_REFCOUNT_MASK); // XXX not needed 3198cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar result->flags |= BLOCK_NEEDS_FREE | 1; 3208cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar result->isa = _NSConcreteMallocBlock; 3218cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (result->flags & BLOCK_HAS_COPY_DISPOSE) { 3228cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("calling block copy helper %p(%p, %p)...\n", aBlock->descriptor->copy, result, aBlock); 3238cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar (*aBlock->descriptor->copy)(result, aBlock); // do fixup 3248cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3258cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return result; 3268cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3278cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else { 3288cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // Under GC want allocation with refcount 1 so we ask for "true" if wantsOne 3298cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // This allows the copy helper routines to make non-refcounted block copies under GC 3308cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar unsigned long int flags = aBlock->flags; 3318cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar bool hasCTOR = (flags & BLOCK_HAS_CTOR) != 0; 3328cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_layout *result = _Block_allocator(aBlock->descriptor->size, wantsOne, hasCTOR); 3338cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (!result) return (void *)0; 3348cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first 3358cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // reset refcount 3368cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // if we copy a malloc block to a GC block then we need to clear NEEDS_FREE. 3378cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar flags &= ~(BLOCK_NEEDS_FREE|BLOCK_REFCOUNT_MASK); // XXX not needed 3388cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (wantsOne) 3398cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar flags |= BLOCK_IS_GC | 1; 3408cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else 3418cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar flags |= BLOCK_IS_GC; 3428cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar result->flags = flags; 3438cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (flags & BLOCK_HAS_COPY_DISPOSE) { 3448cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("calling block copy helper...\n"); 3458cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar (*aBlock->descriptor->copy)(result, aBlock); // do fixup 3468cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3478cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (hasCTOR) { 3488cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar result->isa = _NSConcreteFinalizingBlock; 3498cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3508cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else { 3518cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar result->isa = _NSConcreteAutoBlock; 3528cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3538cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return result; 3548cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3558cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 3568cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 3578cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 358962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 359962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Runtime entry points for maintaining the sharing knowledge of byref data blocks. 360962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * 361962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * A closure has been copied and its fixup routine is asking us to fix up the reference to the shared byref data 362962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Closures that aren't copied must still work, so everyone always accesses variables after dereferencing the forwarding ptr. 363962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * We ask if the byref pointer that we know about has already been copied to the heap, and if so, increment it. 364962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Otherwise we need to copy it and update the stack forwarding pointer 365962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * XXX We need to account for weak/nonretained read-write barriers. 366962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 3678cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 3688cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_byref_assign_copy(void *dest, const void *arg, const int flags) { 3698cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_byref **destp = (struct Block_byref **)dest; 3708cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_byref *src = (struct Block_byref *)arg; 3718cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 3728cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("_Block_byref_assign_copy called, byref destp %p, src %p, flags %x\n", destp, src, flags); 3738cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("src dump: %s\n", _Block_byref_dump(src)); 3748cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (src->forwarding->flags & BLOCK_IS_GC) { 3758cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar ; // don't need to do any more work 3768cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3778cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if ((src->forwarding->flags & BLOCK_REFCOUNT_MASK) == 0) { 3788cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("making copy\n"); 3798cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // src points to stack 3808cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar bool isWeak = ((flags & (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK)) == (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK)); 3818cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // if its weak ask for an object (only matters under GC) 3828cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_byref *copy = (struct Block_byref *)_Block_allocator(src->size, false, isWeak); 3838cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar copy->flags = src->flags | _Byref_flag_initial_value; // non-GC one for caller, one for stack 3848cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar copy->forwarding = copy; // patch heap copy to point to itself (skip write-barrier) 3858cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar src->forwarding = copy; // patch stack to point to heap copy 3868cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar copy->size = src->size; 3878cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (isWeak) { 3888cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar copy->isa = &_NSConcreteWeakBlockVariable; // mark isa field so it gets weak scanning 3898cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3908cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (src->flags & BLOCK_HAS_COPY_DISPOSE) { 3918cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // Trust copy helper to copy everything of interest 3928cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // If more than one field shows up in a byref block this is wrong XXX 3938cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar copy->byref_keep = src->byref_keep; 3948cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar copy->byref_destroy = src->byref_destroy; 3958cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar (*src->byref_keep)(copy, src); 3968cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 3978cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else { 3988cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // just bits. Blast 'em using _Block_memmove in case they're __strong 3998cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_memmove( 4008cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar (void *)©->byref_keep, 4018cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar (void *)&src->byref_keep, 4028cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar src->size - sizeof(struct Block_byref_header)); 4038cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4048cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4058cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // already copied to heap 4068cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if ((src->forwarding->flags & BLOCK_NEEDS_FREE) == BLOCK_NEEDS_FREE) { 4078cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar latching_incr_int(&src->forwarding->flags); 4088cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4098cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // assign byref data block pointer into new Block 4108cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_assign(src->forwarding, (void **)destp); 4118cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 4128cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4138cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar// Old compiler SPI 4148cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_byref_release(const void *arg) { 4158cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_byref *shared_struct = (struct Block_byref *)arg; 4168cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar int refcount; 4178cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4188cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // dereference the forwarding pointer since the compiler isn't doing this anymore (ever?) 4198cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar shared_struct = shared_struct->forwarding; 4208cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4218cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("_Block_byref_release %p called, flags are %x\n", shared_struct, shared_struct->flags); 4228cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // To support C++ destructors under GC we arrange for there to be a finalizer for this 4238cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // by using an isa that directs the code to a finalizer that calls the byref_destroy method. 4248cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if ((shared_struct->flags & BLOCK_NEEDS_FREE) == 0) { 4258cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return; // stack or GC or global 4268cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4278cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar refcount = shared_struct->flags & BLOCK_REFCOUNT_MASK; 4288cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (refcount <= 0) { 4298cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar printf("_Block_byref_release: Block byref data structure at %p underflowed\n", arg); 4308cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4318cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if ((latching_decr_int(&shared_struct->flags) & BLOCK_REFCOUNT_MASK) == 0) { 4328cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("disposing of heap based byref block\n"); 4338cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (shared_struct->flags & BLOCK_HAS_COPY_DISPOSE) { 4348cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("calling out to helper\n"); 4358cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar (*shared_struct->byref_destroy)(shared_struct); 4368cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4378cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_deallocator((struct Block_layout *)shared_struct); 4388cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4398cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 4408cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4418cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 442962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 4438cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * 4448cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * API supporting SPI 4458cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * _Block_copy, _Block_release, and (old) _Block_destroy 4468cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * 447962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 4488cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 449b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#if 0 4508cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#pragma mark SPI/API 451962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* if 0 */ 4528cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4538cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarvoid *_Block_copy(const void *arg) { 4548cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return _Block_copy_internal(arg, WANTS_ONE); 4558cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 4568cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4578cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4588cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar// API entry point to release a copied Block 4598cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarvoid _Block_release(void *arg) { 4608cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_layout *aBlock = (struct Block_layout *)arg; 4618cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar int32_t newCount; 4628cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (!aBlock) return; 4638cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar newCount = latching_decr_int(&aBlock->flags) & BLOCK_REFCOUNT_MASK; 4648cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (newCount > 0) return; 4658cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // Hit zero 4668cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (aBlock->flags & BLOCK_IS_GC) { 4678cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // Tell GC we no longer have our own refcounts. GC will decr its refcount 4688cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // and unless someone has done a CFRetain or marked it uncollectable it will 4698cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // now be subject to GC reclamation. 4708cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_setHasRefcount(aBlock, false); 4718cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4728cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if (aBlock->flags & BLOCK_NEEDS_FREE) { 4738cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (aBlock->flags & BLOCK_HAS_COPY_DISPOSE)(*aBlock->descriptor->dispose)(aBlock); 4748cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_deallocator(aBlock); 4758cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4768cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if (aBlock->flags & BLOCK_IS_GLOBAL) { 4778cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar ; 4788cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4798cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else { 480b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen printf("Block_release called upon a stack Block: %p, ignored\n", (void *)aBlock); 4818cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4828cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 4838cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4848cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4858cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4868cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar// Old Compiler SPI point to release a copied Block used by the compiler in dispose helpers 4878cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarstatic void _Block_destroy(const void *arg) { 4888cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_layout *aBlock; 4898cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (!arg) return; 4908cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar aBlock = (struct Block_layout *)arg; 4918cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (aBlock->flags & BLOCK_IS_GC) { 4928cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // assert(aBlock->Block_flags & BLOCK_HAS_CTOR); 4938cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return; // ignore, we are being called because of a DTOR 4948cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 4958cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_release(aBlock); 4968cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 4978cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4988cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 4998cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 500962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 5018cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * 5028cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * SPI used by other layers 5038cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * 504962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 5058cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5068cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar// SPI, also internal. Called from NSAutoBlock only under GC 5078cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarvoid *_Block_copy_collectable(const void *aBlock) { 5088cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return _Block_copy_internal(aBlock, 0); 5098cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 5108cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5118cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5128cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar// SPI 5138cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarunsigned long int Block_size(void *arg) { 5148cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return ((struct Block_layout *)arg)->descriptor->size; 5158cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 5168cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5178cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 518b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#if 0 5198cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#pragma mark Compiler SPI entry points 520962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* if 0 */ 5218cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5228cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5238cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar/******************************************************* 5248cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5258cbe163cba77c772621f89ddb33793ac170b1faDaniel DunbarEntry points used by the compiler - the real API! 5268cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5278cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5288cbe163cba77c772621f89ddb33793ac170b1faDaniel DunbarA Block can reference four different kinds of things that require help when the Block is copied to the heap. 5298cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar1) C++ stack based objects 5308cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar2) References to Objective-C objects 5318cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar3) Other Blocks 5328cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar4) __block variables 5338cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5348cbe163cba77c772621f89ddb33793ac170b1faDaniel DunbarIn these cases helper functions are synthesized by the compiler for use in Block_copy and Block_release, called the copy and dispose helpers. The copy helper emits a call to the C++ const copy constructor for C++ stack based objects and for the rest calls into the runtime support function _Block_object_assign. The dispose helper has a call to the C++ destructor for case 1 and a call into _Block_object_dispose for the rest. 5358cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5368cbe163cba77c772621f89ddb33793ac170b1faDaniel DunbarThe flags parameter of _Block_object_assign and _Block_object_dispose is set to 5378cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * BLOCK_FIELD_IS_OBJECT (3), for the case of an Objective-C Object, 5388cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * BLOCK_FIELD_IS_BLOCK (7), for the case of another Block, and 5398cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar * BLOCK_FIELD_IS_BYREF (8), for the case of a __block variable. 5408cbe163cba77c772621f89ddb33793ac170b1faDaniel DunbarIf the __block variable is marked weak the compiler also or's in BLOCK_FIELD_IS_WEAK (16). 5418cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5428cbe163cba77c772621f89ddb33793ac170b1faDaniel DunbarSo the Block copy/dispose helpers should only ever generate the four flag values of 3, 7, 8, and 24. 5438cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5448cbe163cba77c772621f89ddb33793ac170b1faDaniel DunbarWhen a __block variable is either a C++ object, an Objective-C object, or another Block then the compiler also generates copy/dispose helper functions. Similarly to the Block copy helper, the "__block" copy helper (formerly and still a.k.a. "byref" copy helper) will do a C++ copy constructor (not a const one though!) and the dispose helper will do the destructor. And similarly the helpers will call into the same two support functions with the same values for objects and Blocks with the additional BLOCK_BYREF_CALLER (128) bit of information supplied. 5458cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5468cbe163cba77c772621f89ddb33793ac170b1faDaniel DunbarSo the __block copy/dispose helpers will generate flag values of 3 or 7 for objects and Blocks respectively, with BLOCK_FIELD_IS_WEAK (16) or'ed as appropriate and always 128 or'd in, for the following set of possibilities: 5478cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar __block id 128+3 5488cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar __weak block id 128+3+16 5498cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar __block (^Block) 128+7 5508cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar __weak __block (^Block) 128+7+16 5518cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5528cbe163cba77c772621f89ddb33793ac170b1faDaniel DunbarThe implementation of the two routines would be improved by switch statements enumerating the eight cases. 5538cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5548cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar********************************************************/ 5558cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 556962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 557962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * When Blocks or Block_byrefs hold objects then their copy routine helpers use this entry point 558962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * to do the assignment. 559962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 5608cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarvoid _Block_object_assign(void *destAddr, const void *object, const int flags) { 5618cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("_Block_object_assign(*%p, %p, %x)\n", destAddr, object, flags); 5628cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if ((flags & BLOCK_BYREF_CALLER) == BLOCK_BYREF_CALLER) { 5638cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if ((flags & BLOCK_FIELD_IS_WEAK) == BLOCK_FIELD_IS_WEAK) { 5648cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_assign_weak(object, destAddr); 5658cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 5668cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else { 5678cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // do *not* retain or *copy* __block variables whatever they are 5688cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_assign((void *)object, destAddr); 5698cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 5708cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 5718cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if ((flags & BLOCK_FIELD_IS_BYREF) == BLOCK_FIELD_IS_BYREF) { 5728cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // copying a __block reference from the stack Block to the heap 5738cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // flags will indicate if it holds a __weak reference and needs a special isa 5748cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_byref_assign_copy(destAddr, object, flags); 5758cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 5768cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // (this test must be before next one) 5778cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if ((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) { 5788cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // copying a Block declared variable from the stack Block to the heap 5798cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_assign(_Block_copy_internal(object, flags), destAddr); 5808cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 5818cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // (this test must be after previous one) 5828cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if ((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) { 5838cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("retaining object at %p\n", object); 5848cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_retain_object(object); 5858cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("done retaining object at %p\n", object); 5868cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_assign((void *)object, destAddr); 5878cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 5888cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 5898cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 5908cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar// When Blocks or Block_byrefs hold objects their destroy helper routines call this entry point 5918cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar// to help dispose of the contents 5928cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar// Used initially only for __attribute__((NSObject)) marked pointers. 5938cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarvoid _Block_object_dispose(const void *object, const int flags) { 5948cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar //printf("_Block_object_dispose(%p, %x)\n", object, flags); 5958cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (flags & BLOCK_FIELD_IS_BYREF) { 5968cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // get rid of the __block data structure held in a Block 5978cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_byref_release(object); 5988cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 5998cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if ((flags & (BLOCK_FIELD_IS_BLOCK|BLOCK_BYREF_CALLER)) == BLOCK_FIELD_IS_BLOCK) { 6008cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // get rid of a referenced Block held by this Block 6018cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // (ignore __block Block variables, compiler doesn't need to call us) 6028cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_destroy(object); 6038cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6048cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if ((flags & (BLOCK_FIELD_IS_WEAK|BLOCK_FIELD_IS_BLOCK|BLOCK_BYREF_CALLER)) == BLOCK_FIELD_IS_OBJECT) { 6058cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // get rid of a referenced object held by this Block 6068cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar // (ignore __block object variables, compiler doesn't need to call us) 6078cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar _Block_release_object(object); 6088cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6098cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 6108cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 6118cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 612962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan/* 613962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan * Debugging support: 614962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan */ 615b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen#if 0 6168cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar#pragma mark Debugging 617962a63123c07b5fed500390eb83f2f3aa8e5f8cbEdward O'Callaghan#endif /* if 0 */ 6188cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 6198cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 6208cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarconst char *_Block_dump(const void *block) { 6218cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_layout *closure = (struct Block_layout *)block; 6228cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar static char buffer[512]; 6238cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar char *cp = buffer; 6248cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (closure == NULL) { 6258cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar sprintf(cp, "NULL passed to _Block_dump\n"); 6268cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return buffer; 6278cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6288cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (! (closure->flags & BLOCK_HAS_DESCRIPTOR)) { 6298cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar printf("Block compiled by obsolete compiler, please recompile source for this Block\n"); 6308cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar exit(1); 6318cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 632b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen cp += sprintf(cp, "^%p (new layout) =\n", (void *)closure); 6338cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (closure->isa == NULL) { 6348cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "isa: NULL\n"); 6358cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6368cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if (closure->isa == _NSConcreteStackBlock) { 6378cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "isa: stack Block\n"); 6388cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6398cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if (closure->isa == _NSConcreteMallocBlock) { 6408cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "isa: malloc heap Block\n"); 6418cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6428cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if (closure->isa == _NSConcreteAutoBlock) { 6438cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "isa: GC heap Block\n"); 6448cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6458cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if (closure->isa == _NSConcreteGlobalBlock) { 6468cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "isa: global Block\n"); 6478cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6488cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else if (closure->isa == _NSConcreteFinalizingBlock) { 6498cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "isa: finalizing Block\n"); 6508cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6518cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar else { 652b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen cp += sprintf(cp, "isa?: %p\n", (void *)closure->isa); 6538cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6548cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "flags:"); 6558cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (closure->flags & BLOCK_HAS_DESCRIPTOR) { 6568cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, " HASDESCRIPTOR"); 6578cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6588cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (closure->flags & BLOCK_NEEDS_FREE) { 6598cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, " FREEME"); 6608cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6618cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (closure->flags & BLOCK_IS_GC) { 6628cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, " ISGC"); 6638cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6648cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (closure->flags & BLOCK_HAS_COPY_DISPOSE) { 6658cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, " HASHELP"); 6668cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6678cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (closure->flags & BLOCK_HAS_CTOR) { 6688cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, " HASCTOR"); 6698cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6708cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "\nrefcount: %u\n", closure->flags & BLOCK_REFCOUNT_MASK); 6713f55c61a5d7428eb18e65393e2b9e91ea9444fdbShantonu Sen cp += sprintf(cp, "invoke: %p\n", (void *)(uintptr_t)closure->invoke); 6728cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar { 6738cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar struct Block_descriptor *dp = closure->descriptor; 674b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen cp += sprintf(cp, "descriptor: %p\n", (void *)dp); 6758cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "descriptor->reserved: %lu\n", dp->reserved); 6768cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, "descriptor->size: %lu\n", dp->size); 6778cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 6788cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (closure->flags & BLOCK_HAS_COPY_DISPOSE) { 6793f55c61a5d7428eb18e65393e2b9e91ea9444fdbShantonu Sen cp += sprintf(cp, "descriptor->copy helper: %p\n", (void *)(uintptr_t)dp->copy); 6803f55c61a5d7428eb18e65393e2b9e91ea9444fdbShantonu Sen cp += sprintf(cp, "descriptor->dispose helper: %p\n", (void *)(uintptr_t)dp->dispose); 6818cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6828cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6838cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return buffer; 6848cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 6858cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 6868cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 6878cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbarconst char *_Block_byref_dump(struct Block_byref *src) { 6888cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar static char buffer[256]; 6898cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar char *cp = buffer; 690b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen cp += sprintf(cp, "byref data block %p contents:\n", (void *)src); 691b4c3b6f8a2d3481bac6b0e9b4240fa0c99412d10Shantonu Sen cp += sprintf(cp, " forwarding: %p\n", (void *)src->forwarding); 6928cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, " flags: 0x%x\n", src->flags); 6938cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar cp += sprintf(cp, " size: %d\n", src->size); 6948cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar if (src->flags & BLOCK_HAS_COPY_DISPOSE) { 6953f55c61a5d7428eb18e65393e2b9e91ea9444fdbShantonu Sen cp += sprintf(cp, " copy helper: %p\n", (void *)(uintptr_t)src->byref_keep); 6963f55c61a5d7428eb18e65393e2b9e91ea9444fdbShantonu Sen cp += sprintf(cp, " dispose helper: %p\n", (void *)(uintptr_t)src->byref_destroy); 6978cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar } 6988cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar return buffer; 6998cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar} 7008cbe163cba77c772621f89ddb33793ac170b1faDaniel Dunbar 701