Lines Matching +full:object +full:- +full:copy
4 * Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge,
5 * to any person obtaining a copy of this software and associated documentation
7 * including without limitation the rights to use, copy, modify, merge, publish,
52 /* fixme barrier is overkill -- see objc-os.h */ in OSAtomicCompareAndSwapLong()
58 /* fixme barrier is overkill -- see objc-os.h */ in OSAtomicCompareAndSwapInt()
64 * Check to see if the GCC atomic built-ins are available. If we're on
65 * a 64-bit system, make sure we have an 8-byte atomic function
81 #error unknown atomic compare-and-swap primitive
138 if (OSAtomicCompareAndSwapLong(old_value, old_value-1, (volatile long int *)where)) {
139 return old_value-1;
154 if (OSAtomicCompareAndSwapInt(old_value, old_value-1, (volatile int *)where)) { in latching_decr_int()
155 return old_value-1; in latching_decr_int()
205 size -= sizeof(void *); in _Block_memmove_gc_broken()
210 * GC support callout functions - initially set to stub routines:
224 * GC support SPI functions - called from ObjC runtime and CoreFoundation:
228 * Called from objc-auto to turn on GC.
264 * Called from objc-auto to alternatively turn on retain/release.
265 * Prior to this the only "object" support we can provide is for those
281 #pragma mark Copy/Release support
284 /* Copy, or bump refcount, of a block. If really copying, call the copy helper if present. */
295 if (aBlock->flags & BLOCK_NEEDS_FREE) { in _Block_copy_internal()
297 latching_incr_int(&aBlock->flags); in _Block_copy_internal()
300 else if (aBlock->flags & BLOCK_IS_GC) { in _Block_copy_internal()
302 if (wantsOne && ((latching_incr_int(&aBlock->flags) & BLOCK_REFCOUNT_MASK) == 1)) { in _Block_copy_internal()
303 // Tell collector to hang on this - it will bump the GC refcount version in _Block_copy_internal()
308 else if (aBlock->flags & BLOCK_IS_GLOBAL) { in _Block_copy_internal()
312 // Its a stack block. Make a copy. in _Block_copy_internal()
314 struct Block_layout *result = malloc(aBlock->descriptor->size); in _Block_copy_internal()
316 memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first in _Block_copy_internal()
318 result->flags &= ~(BLOCK_REFCOUNT_MASK); // XXX not needed in _Block_copy_internal()
319 result->flags |= BLOCK_NEEDS_FREE | 1; in _Block_copy_internal()
320 result->isa = _NSConcreteMallocBlock; in _Block_copy_internal()
321 if (result->flags & BLOCK_HAS_COPY_DISPOSE) { in _Block_copy_internal()
322 … //printf("calling block copy helper %p(%p, %p)...\n", aBlock->descriptor->copy, result, aBlock); in _Block_copy_internal()
323 (*aBlock->descriptor->copy)(result, aBlock); // do fixup in _Block_copy_internal()
329 // This allows the copy helper routines to make non-refcounted block copies under GC in _Block_copy_internal()
330 unsigned long int flags = aBlock->flags; in _Block_copy_internal()
332 struct Block_layout *result = _Block_allocator(aBlock->descriptor->size, wantsOne, hasCTOR); in _Block_copy_internal()
334 memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first in _Block_copy_internal()
336 // if we copy a malloc block to a GC block then we need to clear NEEDS_FREE. in _Block_copy_internal()
342 result->flags = flags; in _Block_copy_internal()
344 //printf("calling block copy helper...\n"); in _Block_copy_internal()
345 (*aBlock->descriptor->copy)(result, aBlock); // do fixup in _Block_copy_internal()
348 result->isa = _NSConcreteFinalizingBlock; in _Block_copy_internal()
351 result->isa = _NSConcreteAutoBlock; in _Block_copy_internal()
364 * Otherwise we need to copy it and update the stack forwarding pointer
365 * XXX We need to account for weak/nonretained read-write barriers.
374 if (src->forwarding->flags & BLOCK_IS_GC) { in _Block_byref_assign_copy()
377 else if ((src->forwarding->flags & BLOCK_REFCOUNT_MASK) == 0) { in _Block_byref_assign_copy()
378 //printf("making copy\n"); in _Block_byref_assign_copy()
381 // if its weak ask for an object (only matters under GC) in _Block_byref_assign_copy()
382 struct Block_byref *copy = (struct Block_byref *)_Block_allocator(src->size, false, isWeak); in _Block_byref_assign_copy() local
383 … copy->flags = src->flags | _Byref_flag_initial_value; // non-GC one for caller, one for stack in _Block_byref_assign_copy()
384 copy->forwarding = copy; // patch heap copy to point to itself (skip write-barrier) in _Block_byref_assign_copy()
385 src->forwarding = copy; // patch stack to point to heap copy in _Block_byref_assign_copy()
386 copy->size = src->size; in _Block_byref_assign_copy()
388 copy->isa = &_NSConcreteWeakBlockVariable; // mark isa field so it gets weak scanning in _Block_byref_assign_copy()
390 if (src->flags & BLOCK_HAS_COPY_DISPOSE) { in _Block_byref_assign_copy()
391 // Trust copy helper to copy everything of interest in _Block_byref_assign_copy()
393 copy->byref_keep = src->byref_keep; in _Block_byref_assign_copy()
394 copy->byref_destroy = src->byref_destroy; in _Block_byref_assign_copy()
395 (*src->byref_keep)(copy, src); in _Block_byref_assign_copy()
400 (void *)©->byref_keep, in _Block_byref_assign_copy()
401 (void *)&src->byref_keep, in _Block_byref_assign_copy()
402 src->size - sizeof(struct Block_byref_header)); in _Block_byref_assign_copy()
406 else if ((src->forwarding->flags & BLOCK_NEEDS_FREE) == BLOCK_NEEDS_FREE) { in _Block_byref_assign_copy()
407 latching_incr_int(&src->forwarding->flags); in _Block_byref_assign_copy()
410 _Block_assign(src->forwarding, (void **)destp); in _Block_byref_assign_copy()
419 shared_struct = shared_struct->forwarding; in _Block_byref_release()
421 //printf("_Block_byref_release %p called, flags are %x\n", shared_struct, shared_struct->flags); in _Block_byref_release()
424 if ((shared_struct->flags & BLOCK_NEEDS_FREE) == 0) { in _Block_byref_release()
427 refcount = shared_struct->flags & BLOCK_REFCOUNT_MASK; in _Block_byref_release()
431 else if ((latching_decr_int(&shared_struct->flags) & BLOCK_REFCOUNT_MASK) == 0) { in _Block_byref_release()
433 if (shared_struct->flags & BLOCK_HAS_COPY_DISPOSE) { in _Block_byref_release()
435 (*shared_struct->byref_destroy)(shared_struct); in _Block_byref_release()
463 newCount = latching_decr_int(&aBlock->flags) & BLOCK_REFCOUNT_MASK; in _Block_release()
466 if (aBlock->flags & BLOCK_IS_GC) { in _Block_release()
472 else if (aBlock->flags & BLOCK_NEEDS_FREE) { in _Block_release()
473 if (aBlock->flags & BLOCK_HAS_COPY_DISPOSE)(*aBlock->descriptor->dispose)(aBlock); in _Block_release()
476 else if (aBlock->flags & BLOCK_IS_GLOBAL) { in _Block_release()
491 if (aBlock->flags & BLOCK_IS_GC) { in _Block_destroy()
492 // assert(aBlock->Block_flags & BLOCK_HAS_CTOR); in _Block_destroy()
514 return ((struct Block_layout *)arg)->descriptor->size; in Block_size()
525 Entry points used by the compiler - the real API!
530 2) References to Objective-C objects
534 …ck_copy and Block_release, called the copy and dispose helpers. The copy helper emits a call to t…
537 * BLOCK_FIELD_IS_OBJECT (3), for the case of an Objective-C Object,
542 So the Block copy/dispose helpers should only ever generate the four flag values of 3, 7, 8, and 24.
544 …object, an Objective-C object, or another Block then the compiler also generates copy/dispose help…
546 So the __block copy/dispose helpers will generate flag values of 3 or 7 for objects and Blocks resp…
557 * When Blocks or Block_byrefs hold objects then their copy routine helpers use this entry point
560 void _Block_object_assign(void *destAddr, const void *object, const int flags) { in _Block_object_assign() argument
561 //printf("_Block_object_assign(*%p, %p, %x)\n", destAddr, object, flags); in _Block_object_assign()
564 _Block_assign_weak(object, destAddr); in _Block_object_assign()
567 // do *not* retain or *copy* __block variables whatever they are in _Block_object_assign()
568 _Block_assign((void *)object, destAddr); in _Block_object_assign()
574 _Block_byref_assign_copy(destAddr, object, flags); in _Block_object_assign()
579 _Block_assign(_Block_copy_internal(object, flags), destAddr); in _Block_object_assign()
583 //printf("retaining object at %p\n", object); in _Block_object_assign()
584 _Block_retain_object(object); in _Block_object_assign()
585 //printf("done retaining object at %p\n", object); in _Block_object_assign()
586 _Block_assign((void *)object, destAddr); in _Block_object_assign()
593 void _Block_object_dispose(const void *object, const int flags) { in _Block_object_dispose() argument
594 //printf("_Block_object_dispose(%p, %x)\n", object, flags); in _Block_object_dispose()
597 _Block_byref_release(object); in _Block_object_dispose()
602 _Block_destroy(object); in _Block_object_dispose()
605 // get rid of a referenced object held by this Block in _Block_object_dispose()
606 // (ignore __block object variables, compiler doesn't need to call us) in _Block_object_dispose()
607 _Block_release_object(object); in _Block_object_dispose()
628 if (! (closure->flags & BLOCK_HAS_DESCRIPTOR)) { in _Block_dump()
633 if (closure->isa == NULL) { in _Block_dump()
636 else if (closure->isa == _NSConcreteStackBlock) { in _Block_dump()
639 else if (closure->isa == _NSConcreteMallocBlock) { in _Block_dump()
642 else if (closure->isa == _NSConcreteAutoBlock) { in _Block_dump()
645 else if (closure->isa == _NSConcreteGlobalBlock) { in _Block_dump()
648 else if (closure->isa == _NSConcreteFinalizingBlock) { in _Block_dump()
652 cp += sprintf(cp, "isa?: %p\n", (void *)closure->isa); in _Block_dump()
655 if (closure->flags & BLOCK_HAS_DESCRIPTOR) { in _Block_dump()
658 if (closure->flags & BLOCK_NEEDS_FREE) { in _Block_dump()
661 if (closure->flags & BLOCK_IS_GC) { in _Block_dump()
664 if (closure->flags & BLOCK_HAS_COPY_DISPOSE) { in _Block_dump()
667 if (closure->flags & BLOCK_HAS_CTOR) { in _Block_dump()
670 cp += sprintf(cp, "\nrefcount: %u\n", closure->flags & BLOCK_REFCOUNT_MASK); in _Block_dump()
671 cp += sprintf(cp, "invoke: %p\n", (void *)(uintptr_t)closure->invoke); in _Block_dump()
673 struct Block_descriptor *dp = closure->descriptor; in _Block_dump()
675 cp += sprintf(cp, "descriptor->reserved: %lu\n", dp->reserved); in _Block_dump()
676 cp += sprintf(cp, "descriptor->size: %lu\n", dp->size); in _Block_dump()
678 if (closure->flags & BLOCK_HAS_COPY_DISPOSE) { in _Block_dump()
679 cp += sprintf(cp, "descriptor->copy helper: %p\n", (void *)(uintptr_t)dp->copy); in _Block_dump()
680 cp += sprintf(cp, "descriptor->dispose helper: %p\n", (void *)(uintptr_t)dp->dispose); in _Block_dump()
691 cp += sprintf(cp, " forwarding: %p\n", (void *)src->forwarding); in _Block_byref_dump()
692 cp += sprintf(cp, " flags: 0x%x\n", src->flags); in _Block_byref_dump()
693 cp += sprintf(cp, " size: %d\n", src->size); in _Block_byref_dump()
694 if (src->flags & BLOCK_HAS_COPY_DISPOSE) { in _Block_byref_dump()
695 cp += sprintf(cp, " copy helper: %p\n", (void *)(uintptr_t)src->byref_keep); in _Block_byref_dump()
696 cp += sprintf(cp, " dispose helper: %p\n", (void *)(uintptr_t)src->byref_destroy); in _Block_byref_dump()