// Old compiler SPI static void _Block_byref_release(const void *arg) { struct Block_byref *shared_struct = (struct Block_byref *)arg; int refcount; // dereference the forwarding pointer since the compiler isn't doing this anymore (ever?) shared_struct = shared_struct->forwarding; //printf("_Block_byref_release %p called, flags are %x\n", shared_struct, shared_struct->flags); // To support C++ destructors under GC we arrange for there to be a finalizer for this // by using an isa that directs the code to a finalizer that calls the byref_destroy method. if ((shared_struct->flags & BLOCK_NEEDS_FREE) == 0) { return; // stack or GC or global } refcount = shared_struct->flags & BLOCK_REFCOUNT_MASK; if (refcount <= 0) { printf("_Block_byref_release: Block byref data structure at %p underflowed\n", arg); } else if ((latching_decr_int(&shared_struct->flags) & BLOCK_REFCOUNT_MASK) == 0) { //printf("disposing of heap based byref block\n"); if (shared_struct->flags & BLOCK_HAS_COPY_DISPOSE) { //printf("calling out to helper\n"); (*shared_struct->byref_destroy)(shared_struct); } _Block_deallocator((struct Block_layout *)shared_struct); } }
// API entry point to release a copied Block void _Block_release(const void *arg) { struct Block_layout *aBlock = (struct Block_layout *)arg; if (!aBlock || (aBlock->flags & BLOCK_IS_GLOBAL) || ((aBlock->flags & (BLOCK_IS_GC|BLOCK_NEEDS_FREE)) == 0) ) return; if (aBlock->flags & BLOCK_IS_GC) { if (latching_decr_int_now_zero(&aBlock->flags)) { // Tell GC we no longer have our own refcounts. GC will decr its refcount // and unless someone has done a CFRetain or marked it uncollectable it will // now be subject to GC reclamation. _Block_setHasRefcount(aBlock, false); } } else if (aBlock->flags & BLOCK_NEEDS_FREE) { if (latching_decr_int_should_deallocate(&aBlock->flags)) { _Block_call_dispose_helper(aBlock); _Block_destructInstance(aBlock); _Block_deallocator(aBlock); } } }
// Old compiler SPI static void _Block_byref_release(const void *arg) { struct Block_byref *byref = (struct Block_byref *)arg; int32_t refcount; // dereference the forwarding pointer since the compiler isn't doing this anymore (ever?) byref = byref->forwarding; // To support C++ destructors under GC we arrange for there to be a finalizer for this // by using an isa that directs the code to a finalizer that calls the byref_destroy method. if ((byref->flags & BLOCK_BYREF_NEEDS_FREE) == 0) { return; // stack or GC or global } refcount = byref->flags & BLOCK_REFCOUNT_MASK; osx_assert(refcount); if (latching_decr_int_should_deallocate(&byref->flags)) { if (byref->flags & BLOCK_BYREF_HAS_COPY_DISPOSE) { struct Block_byref_2 *byref2 = (struct Block_byref_2 *)(byref+1); (*byref2->byref_destroy)(byref); } _Block_deallocator((struct Block_layout *)byref); } }
// API entry point to release a copied Block void _Block_release(void *arg) { struct Block_layout *aBlock = (struct Block_layout *)arg; int32_t newCount; if (!aBlock) return; newCount = latching_decr_int(&aBlock->flags) & BLOCK_REFCOUNT_MASK; if (newCount > 0) return; // Hit zero if (aBlock->flags & BLOCK_IS_GC) { // Tell GC we no longer have our own refcounts. GC will decr its refcount // and unless someone has done a CFRetain or marked it uncollectable it will // now be subject to GC reclamation. _Block_setHasRefcount(aBlock, false); } else if (aBlock->flags & BLOCK_NEEDS_FREE) { if (aBlock->flags & BLOCK_HAS_COPY_DISPOSE)(*aBlock->descriptor->dispose)(aBlock); _Block_deallocator(aBlock); } else if (aBlock->flags & BLOCK_IS_GLOBAL) { ; } else { printf("Block_release called upon a stack Block: %p, ignored\n", (void *)aBlock); } }