xref: /xnu-11215/libkern/libclosure/runtime.cpp (revision cc9a6355)
1 /*
2  * runtime.c
3  * libclosure
4  *
5  * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
6  *
7  * @APPLE_LLVM_LICENSE_HEADER@
8  */
9 
10 
11 #ifndef KERNEL
12 
13 #include "Block_private.h"
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <dlfcn.h>
17 #include <os/assumes.h>
18 
19 #else /* !KERNEL */
20 
21 #include <libkern/Block_private.h>
22 #include <libkern/OSRuntime.h>
23 
24 #define malloc(s)  kern_os_malloc((s))
25 #define free(a)    kern_os_free((a))
26 
27 #endif /* KERNEL */
28 
29 #include <string.h>
30 #include <stdint.h>
31 #ifndef os_assumes
32 #define os_assumes(_x) (_x)
33 #endif
34 #ifndef os_assert
35 #define os_assert(_x) assert(_x)
36 #endif
37 
38 #if TARGET_OS_WIN32
39 #define _CRT_SECURE_NO_WARNINGS 1
40 #include <windows.h>
41 static __inline bool OSAtomicCompareAndSwapLong(long oldl, long newl, long volatile *dst)
42 {
43     // fixme barrier is overkill -- see objc-os.h
44     long original = InterlockedCompareExchange(dst, newl, oldl);
45     return (original == oldl);
46 }
47 
48 static __inline bool OSAtomicCompareAndSwapInt(int oldi, int newi, int volatile *dst)
49 {
50     // fixme barrier is overkill -- see objc-os.h
51     int original = InterlockedCompareExchange(dst, newi, oldi);
52     return (original == oldi);
53 }
54 #else
55 #define OSAtomicCompareAndSwapLong(_Old, _New, _Ptr) __sync_bool_compare_and_swap(_Ptr, _Old, _New)
56 #define OSAtomicCompareAndSwapInt(_Old, _New, _Ptr) __sync_bool_compare_and_swap(_Ptr, _Old, _New)
57 #endif
58 
59 
60 /*******************************************************************************
61 Internal Utilities
62 ********************************************************************************/
63 
64 static int32_t latching_incr_int(volatile int32_t *where) {
65     while (1) {
66         int32_t old_value = *where;
67         if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
68             return BLOCK_REFCOUNT_MASK;
69         }
70         if (OSAtomicCompareAndSwapInt(old_value, old_value+2, where)) {
71             return old_value+2;
72         }
73     }
74 }
75 
76 static bool latching_incr_int_not_deallocating(volatile int32_t *where) {
77     while (1) {
78         int32_t old_value = *where;
79         if (old_value & BLOCK_DEALLOCATING) {
80             // if deallocating we can't do this
81             return false;
82         }
83         if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
84             // if latched, we're leaking this block, and we succeed
85             return true;
86         }
87         if (OSAtomicCompareAndSwapInt(old_value, old_value+2, where)) {
88             // otherwise, we must store a new retained value without the deallocating bit set
89             return true;
90         }
91     }
92 }
93 
94 
95 // return should_deallocate?
96 static bool latching_decr_int_should_deallocate(volatile int32_t *where) {
97     while (1) {
98         int32_t old_value = *where;
99         if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
100             return false; // latched high
101         }
102         if ((old_value & BLOCK_REFCOUNT_MASK) == 0) {
103             return false;   // underflow, latch low
104         }
105         int32_t new_value = old_value - 2;
106         bool result = false;
107         if ((old_value & (BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING)) == 2) {
108             new_value = old_value - 1;
109             result = true;
110         }
111         if (OSAtomicCompareAndSwapInt(old_value, new_value, where)) {
112             return result;
113         }
114     }
115 }
116 
117 
118 /**************************************************************************
119 Framework callback functions and their default implementations.
120 ***************************************************************************/
121 #if !TARGET_OS_WIN32
122 #pragma mark Framework Callback Routines
123 #endif
124 
125 static void _Block_retain_object_default(const void *ptr __unused) { }
126 
127 static void _Block_release_object_default(const void *ptr __unused) { }
128 
129 static void _Block_destructInstance_default(const void *aBlock __unused) {}
130 
131 static void (*_Block_retain_object)(const void *ptr) = _Block_retain_object_default;
132 static void (*_Block_release_object)(const void *ptr) = _Block_release_object_default;
133 static void (*_Block_destructInstance) (const void *aBlock) = _Block_destructInstance_default;
134 
135 
136 /**************************************************************************
137 Callback registration from ObjC runtime and CoreFoundation
138 ***************************************************************************/
139 
140 void _Block_use_RR2(const Block_callbacks_RR *callbacks) {
141     _Block_retain_object = callbacks->retain;
142     _Block_release_object = callbacks->release;
143     _Block_destructInstance = callbacks->destructInstance;
144 }
145 
146 /****************************************************************************
147 Accessors for block descriptor fields
148 *****************************************************************************/
149 #if 0
150 static struct Block_descriptor_1 * _Block_descriptor_1(struct Block_layout *aBlock)
151 {
152     return aBlock->descriptor;
153 }
154 #endif
155 
156 static struct Block_descriptor_2 * _Block_descriptor_2(struct Block_layout *aBlock)
157 {
158     if (! (aBlock->flags & BLOCK_HAS_COPY_DISPOSE)) return NULL;
159     uint8_t *desc = (uint8_t *)aBlock->descriptor;
160     desc += sizeof(struct Block_descriptor_1);
161     return __IGNORE_WCASTALIGN((struct Block_descriptor_2 *)desc);
162 }
163 
164 static struct Block_descriptor_3 * _Block_descriptor_3(struct Block_layout *aBlock)
165 {
166     if (! (aBlock->flags & BLOCK_HAS_SIGNATURE)) return NULL;
167     uint8_t *desc = (uint8_t *)aBlock->descriptor;
168     desc += sizeof(struct Block_descriptor_1);
169     if (aBlock->flags & BLOCK_HAS_COPY_DISPOSE) {
170         desc += sizeof(struct Block_descriptor_2);
171     }
172     return __IGNORE_WCASTALIGN((struct Block_descriptor_3 *)desc);
173 }
174 
175 static void _Block_call_copy_helper(void *result, struct Block_layout *aBlock)
176 {
177     struct Block_descriptor_2 *desc = _Block_descriptor_2(aBlock);
178     if (!desc) return;
179 
180     (*desc->copy)(result, aBlock); // do fixup
181 }
182 
183 static void _Block_call_dispose_helper(struct Block_layout *aBlock)
184 {
185     struct Block_descriptor_2 *desc = _Block_descriptor_2(aBlock);
186     if (!desc) return;
187 
188     (*desc->dispose)(aBlock);
189 }
190 
191 /*******************************************************************************
192 Internal Support routines for copying
193 ********************************************************************************/
194 
195 #if !TARGET_OS_WIN32
196 #pragma mark Copy/Release support
197 #endif
198 
199 // Copy, or bump refcount, of a block.  If really copying, call the copy helper if present.
200 void *_Block_copy(const void *arg) {
201     struct Block_layout *aBlock;
202 
203     if (!arg) return NULL;
204 
205     // The following would be better done as a switch statement
206     aBlock = (struct Block_layout *)arg;
207     if (aBlock->flags & BLOCK_NEEDS_FREE) {
208         // latches on high
209         latching_incr_int(&aBlock->flags);
210         return aBlock;
211     }
212     else if (aBlock->flags & BLOCK_IS_GLOBAL) {
213         return aBlock;
214     }
215     else {
216         // Its a stack block.  Make a copy.
217         struct Block_layout *result = (typeof(result)) malloc(aBlock->descriptor->size);
218         if (!result) return NULL;
219         memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first
220 #if __has_feature(ptrauth_calls)
221         // Resign the invoke pointer as it uses address authentication.
222         result->invoke = aBlock->invoke;
223 #endif
224         // reset refcount
225         result->flags &= ~(BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING);    // XXX not needed
226         result->flags |= BLOCK_NEEDS_FREE | 2;  // logical refcount 1
227         _Block_call_copy_helper(result, aBlock);
228         // Set isa last so memory analysis tools see a fully-initialized object.
229         result->isa = _NSConcreteMallocBlock;
230         return result;
231     }
232 }
233 
234 
235 // Runtime entry points for maintaining the sharing knowledge of byref data blocks.
236 
237 // A closure has been copied and its fixup routine is asking us to fix up the reference to the shared byref data
238 // Closures that aren't copied must still work, so everyone always accesses variables after dereferencing the forwarding ptr.
239 // We ask if the byref pointer that we know about has already been copied to the heap, and if so, increment and return it.
240 // Otherwise we need to copy it and update the stack forwarding pointer
241 static struct Block_byref *_Block_byref_copy(const void *arg) {
242     struct Block_byref *src = (struct Block_byref *)arg;
243 
244     if ((src->forwarding->flags & BLOCK_REFCOUNT_MASK) == 0) {
245         // src points to stack
246         struct Block_byref *copy = (struct Block_byref *)malloc(src->size);
247         copy->isa = NULL;
248         // byref value 4 is logical refcount of 2: one for caller, one for stack
249         copy->flags = src->flags | BLOCK_BYREF_NEEDS_FREE | 4;
250         copy->forwarding = copy; // patch heap copy to point to itself
251         src->forwarding = copy;  // patch stack to point to heap copy
252         copy->size = src->size;
253 
254         if (src->flags & BLOCK_BYREF_HAS_COPY_DISPOSE) {
255             // Trust copy helper to copy everything of interest
256             // If more than one field shows up in a byref block this is wrong XXX
257             struct Block_byref_2 *src2 = (struct Block_byref_2 *)(src+1);
258             struct Block_byref_2 *copy2 = (struct Block_byref_2 *)(copy+1);
259             copy2->byref_keep = src2->byref_keep;
260             copy2->byref_destroy = src2->byref_destroy;
261 
262             if (src->flags & BLOCK_BYREF_LAYOUT_EXTENDED) {
263                 struct Block_byref_3 *src3 = (struct Block_byref_3 *)(src2+1);
264                 struct Block_byref_3 *copy3 = (struct Block_byref_3*)(copy2+1);
265                 copy3->layout = src3->layout;
266             }
267 
268             (*src2->byref_keep)(copy, src);
269         }
270         else {
271             // Bitwise copy.
272             // This copy includes Block_byref_3, if any.
273             memmove(copy+1, src+1, src->size - sizeof(*src));
274         }
275     }
276     // already copied to heap
277     else if ((src->forwarding->flags & BLOCK_BYREF_NEEDS_FREE) == BLOCK_BYREF_NEEDS_FREE) {
278         latching_incr_int(&src->forwarding->flags);
279     }
280 
281     return src->forwarding;
282 }
283 
284 static void _Block_byref_release(const void *arg) {
285     struct Block_byref *byref = (struct Block_byref *)arg;
286 
287     // dereference the forwarding pointer since the compiler isn't doing this anymore (ever?)
288     byref = byref->forwarding;
289 
290     if (byref->flags & BLOCK_BYREF_NEEDS_FREE) {
291         __assert_only int32_t refcount = byref->flags & BLOCK_REFCOUNT_MASK;
292         os_assert(refcount);
293         if (latching_decr_int_should_deallocate(&byref->flags)) {
294             if (byref->flags & BLOCK_BYREF_HAS_COPY_DISPOSE) {
295                 struct Block_byref_2 *byref2 = (struct Block_byref_2 *)(byref+1);
296                 (*byref2->byref_destroy)(byref);
297             }
298             free(byref);
299         }
300     }
301 }
302 
303 
304 /************************************************************
305  *
306  * API supporting SPI
307  * _Block_copy, _Block_release, and (old) _Block_destroy
308  *
309  ***********************************************************/
310 
311 #if !TARGET_OS_WIN32
312 #pragma mark SPI/API
313 #endif
314 
315 
316 // API entry point to release a copied Block
317 void _Block_release(const void *arg) {
318     struct Block_layout *aBlock = (struct Block_layout *)arg;
319     if (!aBlock) return;
320     if (aBlock->flags & BLOCK_IS_GLOBAL) return;
321     if (! (aBlock->flags & BLOCK_NEEDS_FREE)) return;
322 
323     if (latching_decr_int_should_deallocate(&aBlock->flags)) {
324         _Block_call_dispose_helper(aBlock);
325         _Block_destructInstance(aBlock);
326         free(aBlock);
327     }
328 }
329 
330 bool _Block_tryRetain(const void *arg) {
331     struct Block_layout *aBlock = (struct Block_layout *)arg;
332     return latching_incr_int_not_deallocating(&aBlock->flags);
333 }
334 
335 bool _Block_isDeallocating(const void *arg) {
336     struct Block_layout *aBlock = (struct Block_layout *)arg;
337     return (aBlock->flags & BLOCK_DEALLOCATING) != 0;
338 }
339 
340 
341 /************************************************************
342  *
343  * SPI used by other layers
344  *
345  ***********************************************************/
346 
347 size_t Block_size(void *aBlock) {
348     return ((struct Block_layout *)aBlock)->descriptor->size;
349 }
350 
351 bool _Block_use_stret(void *aBlock) {
352     struct Block_layout *layout = (struct Block_layout *)aBlock;
353 
354     int requiredFlags = BLOCK_HAS_SIGNATURE | BLOCK_USE_STRET;
355     return (layout->flags & requiredFlags) == requiredFlags;
356 }
357 
358 // Checks for a valid signature, not merely the BLOCK_HAS_SIGNATURE bit.
359 bool _Block_has_signature(void *aBlock) {
360     return _Block_signature(aBlock) ? true : false;
361 }
362 
363 const char * _Block_signature(void *aBlock)
364 {
365     struct Block_descriptor_3 *desc3 = _Block_descriptor_3((struct Block_layout *)aBlock);
366     if (!desc3) return NULL;
367 
368     return desc3->signature;
369 }
370 
371 const char * _Block_layout(void *aBlock)
372 {
373     // Don't return extended layout to callers expecting old GC layout
374     struct Block_layout *layout = (struct Block_layout *)aBlock;
375     if (layout->flags & BLOCK_HAS_EXTENDED_LAYOUT) return NULL;
376 
377     struct Block_descriptor_3 *desc3 = _Block_descriptor_3((struct Block_layout *)aBlock);
378     if (!desc3) return NULL;
379 
380     return desc3->layout;
381 }
382 
383 const char * _Block_extended_layout(void *aBlock)
384 {
385     // Don't return old GC layout to callers expecting extended layout
386     struct Block_layout *layout = (struct Block_layout *)aBlock;
387     if (! (layout->flags & BLOCK_HAS_EXTENDED_LAYOUT)) return NULL;
388 
389     struct Block_descriptor_3 *desc3 = _Block_descriptor_3((struct Block_layout *)aBlock);
390     if (!desc3) return NULL;
391 
392     // Return empty string (all non-object bytes) instead of NULL
393     // so callers can distinguish "empty layout" from "no layout".
394     if (!desc3->layout) return "";
395     else return desc3->layout;
396 }
397 
398 #if !TARGET_OS_WIN32
399 #pragma mark Compiler SPI entry points
400 #endif
401 
402 
403 /*******************************************************
404 
405 Entry points used by the compiler - the real API!
406 
407 
408 A Block can reference four different kinds of things that require help when the Block is copied to the heap.
409 1) C++ stack based objects
410 2) References to Objective-C objects
411 3) Other Blocks
412 4) __block variables
413 
414 In 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.
415 
416 The flags parameter of _Block_object_assign and _Block_object_dispose is set to
417     * BLOCK_FIELD_IS_OBJECT (3), for the case of an Objective-C Object,
418     * BLOCK_FIELD_IS_BLOCK (7), for the case of another Block, and
419     * BLOCK_FIELD_IS_BYREF (8), for the case of a __block variable.
420 If the __block variable is marked weak the compiler also or's in BLOCK_FIELD_IS_WEAK (16)
421 
422 So the Block copy/dispose helpers should only ever generate the four flag values of 3, 7, 8, and 24.
423 
424 When  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.
425 
426 So 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:
427     __block id                   128+3       (0x83)
428     __block (^Block)             128+7       (0x87)
429     __weak __block id            128+3+16    (0x93)
430     __weak __block (^Block)      128+7+16    (0x97)
431 
432 
433 ********************************************************/
434 
435 //
436 // When Blocks or Block_byrefs hold objects then their copy routine helpers use this entry point
437 // to do the assignment.
438 //
439 void _Block_object_assign(void *destArg, const void *object, const int flags) {
440     const void **dest = (const void **)destArg;
441     switch (os_assumes(flags & BLOCK_ALL_COPY_DISPOSE_FLAGS)) {
442       case BLOCK_FIELD_IS_OBJECT:
443         /*******
444         id object = ...;
445         [^{ object; } copy];
446         ********/
447 
448         _Block_retain_object(object);
449         *dest = object;
450         break;
451 
452       case BLOCK_FIELD_IS_BLOCK:
453         /*******
454         void (^object)(void) = ...;
455         [^{ object; } copy];
456         ********/
457 
458         *dest = _Block_copy(object);
459         break;
460 
461       case BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK:
462       case BLOCK_FIELD_IS_BYREF:
463         /*******
464          // copy the onstack __block container to the heap
465          // Note this __weak is old GC-weak/MRC-unretained.
466          // ARC-style __weak is handled by the copy helper directly.
467          __block ... x;
468          __weak __block ... x;
469          [^{ x; } copy];
470          ********/
471 
472         *dest = _Block_byref_copy(object);
473         break;
474 
475       case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT:
476       case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK:
477         /*******
478          // copy the actual field held in the __block container
479          // Note this is MRC unretained __block only.
480          // ARC retained __block is handled by the copy helper directly.
481          __block id object;
482          __block void (^object)(void);
483          [^{ object; } copy];
484          ********/
485 
486         *dest = object;
487         break;
488 
489       case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK:
490       case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK  | BLOCK_FIELD_IS_WEAK:
491         /*******
492          // copy the actual field held in the __block container
493          // Note this __weak is old GC-weak/MRC-unretained.
494          // ARC-style __weak is handled by the copy helper directly.
495          __weak __block id object;
496          __weak __block void (^object)(void);
497          [^{ object; } copy];
498          ********/
499 
500         *dest = object;
501         break;
502 
503       default:
504         break;
505     }
506 }
507 
508 // When Blocks or Block_byrefs hold objects their destroy helper routines call this entry point
509 // to help dispose of the contents
510 void _Block_object_dispose(const void *object, const int flags) {
511     switch (os_assumes(flags & BLOCK_ALL_COPY_DISPOSE_FLAGS)) {
512       case BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK:
513       case BLOCK_FIELD_IS_BYREF:
514         // get rid of the __block data structure held in a Block
515         _Block_byref_release(object);
516         break;
517       case BLOCK_FIELD_IS_BLOCK:
518         _Block_release(object);
519         break;
520       case BLOCK_FIELD_IS_OBJECT:
521         _Block_release_object(object);
522         break;
523       case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT:
524       case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK:
525       case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK:
526       case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK  | BLOCK_FIELD_IS_WEAK:
527         break;
528       default:
529         break;
530     }
531 }
532 
533 
534 // Workaround for <rdar://26015603> dylib with no __DATA segment fails to rebase
535 __attribute__((used))
536 static int let_there_be_data = 42;
537 
538 #undef malloc
539 #undef free
540 
541