1 /*
2  * Block_private.h
3  *
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
6  * files (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to permit
9  * persons to whom the Software is furnished to do so, subject to the following
10  * conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  */
24 
25 #ifndef _BLOCK_PRIVATE_H_
26 #define _BLOCK_PRIVATE_H_
27 
28 #if !defined(BLOCK_EXPORT)
29 #   if defined(__cplusplus)
30 #       define BLOCK_EXPORT extern "C"
31 #   else
32 #       define BLOCK_EXPORT extern
33 #   endif
34 #endif
35 
36 #ifndef _MSC_VER
37 #include <stdbool.h>
38 #else
39 /* MSVC doesn't have <stdbool.h>. Compensate. */
40 typedef char bool;
41 #define true (bool)1
42 #define false (bool)0
43 #endif
44 
45 #if defined(__cplusplus)
46 extern "C" {
47 #endif
48 
49 
50 enum {
51     BLOCK_REFCOUNT_MASK =     (0xffff),
52     BLOCK_NEEDS_FREE =        (1 << 24),
53     BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
54     BLOCK_HAS_CTOR =          (1 << 26), /* Helpers have C++ code. */
55     BLOCK_IS_GC =             (1 << 27),
56     BLOCK_IS_GLOBAL =         (1 << 28),
57     BLOCK_HAS_DESCRIPTOR =    (1 << 29)
58 };
59 
60 
61 /* Revised new layout. */
62 struct Block_descriptor {
63     unsigned long int reserved;
64     unsigned long int size;
65     void (*copy)(void *dst, void *src);
66     void (*dispose)(void *);
67 };
68 
69 
70 struct Block_layout {
71     void *isa;
72     int flags;
73     int reserved;
74     void (*invoke)(void *, ...);
75     struct Block_descriptor *descriptor;
76     /* Imported variables. */
77 };
78 
79 
80 struct Block_byref {
81     void *isa;
82     struct Block_byref *forwarding;
83     int flags; /* refcount; */
84     int size;
85     void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src);
86     void (*byref_destroy)(struct Block_byref *);
87     /* long shared[0]; */
88 };
89 
90 
91 struct Block_byref_header {
92     void *isa;
93     struct Block_byref *forwarding;
94     int flags;
95     int size;
96 };
97 
98 
99 /* Runtime support functions used by compiler when generating copy/dispose helpers. */
100 
101 enum {
102     /* See function implementation for a more complete description of these fields and combinations */
103     BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)), block, ... */
104     BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
105     BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the __block variable */
106     BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy helpers */
107     BLOCK_BYREF_CALLER      = 128  /* called from __block (byref) copy/dispose support routines. */
108 };
109 
110 /* Runtime entry point called by compiler when assigning objects inside copy helper routines */
111 BLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags);
112     /* BLOCK_FIELD_IS_BYREF is only used from within block copy helpers */
113 
114 
115 /* runtime entry point called by the compiler when disposing of objects inside dispose helper routine */
116 BLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags);
117 
118 
119 
120 /* Other support functions */
121 
122 /* Runtime entry to get total size of a closure */
123 BLOCK_EXPORT unsigned long int Block_size(void *block_basic);
124 
125 
126 
127 /* the raw data space for runtime classes for blocks */
128 /* class+meta used for stack, malloc, and collectable based blocks */
129 BLOCK_EXPORT void * _NSConcreteStackBlock[32];
130 BLOCK_EXPORT void * _NSConcreteMallocBlock[32];
131 BLOCK_EXPORT void * _NSConcreteAutoBlock[32];
132 BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32];
133 BLOCK_EXPORT void * _NSConcreteGlobalBlock[32];
134 BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32];
135 
136 
137 /* the intercept routines that must be used under GC */
138 BLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
139                                   void (*setHasRefcount)(const void *, const bool),
140                                   void (*gc_assign_strong)(void *, void **),
141                                   void (*gc_assign_weak)(const void *, void *),
142                                   void (*gc_memmove)(void *, void *, unsigned long));
143 
144 /* earlier version, now simply transitional */
145 BLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
146                                   void (*setHasRefcount)(const void *, const bool),
147                                   void (*gc_assign_strong)(void *, void **),
148                                   void (*gc_assign_weak)(const void *, void *));
149 
150 BLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *),
151                                  void (*release)(const void *));
152 
153 /* make a collectable GC heap based Block.  Not useful under non-GC. */
154 BLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock);
155 
156 /* thread-unsafe diagnostic */
157 BLOCK_EXPORT const char *_Block_dump(const void *block);
158 
159 
160 /* Obsolete */
161 
162 /* first layout */
163 struct Block_basic {
164     void *isa;
165     int Block_flags;  /* int32_t */
166     int Block_size;  /* XXX should be packed into Block_flags */
167     void (*Block_invoke)(void *);
168     void (*Block_copy)(void *dst, void *src);  /* iff BLOCK_HAS_COPY_DISPOSE */
169     void (*Block_dispose)(void *);             /* iff BLOCK_HAS_COPY_DISPOSE */
170     /* long params[0];  // where const imports, __block storage references, etc. get laid down */
171 };
172 
173 
174 #if defined(__cplusplus)
175 }
176 #endif
177 
178 
179 #endif /* _BLOCK_PRIVATE_H_ */
180