1214152Sed/*
2214152Sed * Block_private.h
3214152Sed *
4214152Sed * Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge,
5214152Sed * to any person obtaining a copy of this software and associated documentation
6214152Sed * files (the "Software"), to deal in the Software without restriction,
7214152Sed * including without limitation the rights to use, copy, modify, merge, publish,
8214152Sed * distribute, sublicense, and/or sell copies of the Software, and to permit
9214152Sed * persons to whom the Software is furnished to do so, subject to the following
10214152Sed * conditions:
11214152Sed *
12214152Sed * The above copyright notice and this permission notice shall be included in
13214152Sed * all copies or substantial portions of the Software.
14214152Sed *
15214152Sed * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16214152Sed * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17214152Sed * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18214152Sed * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19214152Sed * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20214152Sed * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21214152Sed * SOFTWARE.
22214152Sed *
23214152Sed */
24214152Sed
25214152Sed#ifndef _BLOCK_PRIVATE_H_
26214152Sed#define _BLOCK_PRIVATE_H_
27214152Sed
28214152Sed#if !defined(BLOCK_EXPORT)
29214152Sed#   if defined(__cplusplus)
30214152Sed#       define BLOCK_EXPORT extern "C"
31214152Sed#   else
32214152Sed#       define BLOCK_EXPORT extern
33214152Sed#   endif
34214152Sed#endif
35214152Sed
36214152Sed#ifndef _MSC_VER
37214152Sed#include <stdbool.h>
38214152Sed#else
39214152Sed/* MSVC doesn't have <stdbool.h>. Compensate. */
40214152Sedtypedef char bool;
41214152Sed#define true (bool)1
42214152Sed#define false (bool)0
43214152Sed#endif
44214152Sed
45214152Sed#if defined(__cplusplus)
46214152Sedextern "C" {
47214152Sed#endif
48214152Sed
49214152Sed
50214152Sedenum {
51214152Sed    BLOCK_REFCOUNT_MASK =     (0xffff),
52214152Sed    BLOCK_NEEDS_FREE =        (1 << 24),
53214152Sed    BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
54214152Sed    BLOCK_HAS_CTOR =          (1 << 26), /* Helpers have C++ code. */
55214152Sed    BLOCK_IS_GC =             (1 << 27),
56214152Sed    BLOCK_IS_GLOBAL =         (1 << 28),
57214152Sed    BLOCK_HAS_DESCRIPTOR =    (1 << 29)
58214152Sed};
59214152Sed
60214152Sed
61214152Sed/* Revised new layout. */
62214152Sedstruct Block_descriptor {
63214152Sed    unsigned long int reserved;
64214152Sed    unsigned long int size;
65214152Sed    void (*copy)(void *dst, void *src);
66214152Sed    void (*dispose)(void *);
67214152Sed};
68214152Sed
69214152Sed
70214152Sedstruct Block_layout {
71214152Sed    void *isa;
72214152Sed    int flags;
73214152Sed    int reserved;
74214152Sed    void (*invoke)(void *, ...);
75214152Sed    struct Block_descriptor *descriptor;
76214152Sed    /* Imported variables. */
77214152Sed};
78214152Sed
79214152Sed
80214152Sedstruct Block_byref {
81214152Sed    void *isa;
82214152Sed    struct Block_byref *forwarding;
83214152Sed    int flags; /* refcount; */
84214152Sed    int size;
85214152Sed    void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src);
86214152Sed    void (*byref_destroy)(struct Block_byref *);
87214152Sed    /* long shared[0]; */
88214152Sed};
89214152Sed
90214152Sed
91214152Sedstruct Block_byref_header {
92214152Sed    void *isa;
93214152Sed    struct Block_byref *forwarding;
94214152Sed    int flags;
95214152Sed    int size;
96214152Sed};
97214152Sed
98214152Sed
99214152Sed/* Runtime support functions used by compiler when generating copy/dispose helpers. */
100214152Sed
101214152Sedenum {
102214152Sed    /* See function implementation for a more complete description of these fields and combinations */
103214152Sed    BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)), block, ... */
104214152Sed    BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
105214152Sed    BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the __block variable */
106214152Sed    BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy helpers */
107214152Sed    BLOCK_BYREF_CALLER      = 128  /* called from __block (byref) copy/dispose support routines. */
108214152Sed};
109214152Sed
110214152Sed/* Runtime entry point called by compiler when assigning objects inside copy helper routines */
111214152SedBLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags);
112214152Sed    /* BLOCK_FIELD_IS_BYREF is only used from within block copy helpers */
113214152Sed
114214152Sed
115214152Sed/* runtime entry point called by the compiler when disposing of objects inside dispose helper routine */
116214152SedBLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags);
117214152Sed
118214152Sed
119214152Sed
120214152Sed/* Other support functions */
121214152Sed
122214152Sed/* Runtime entry to get total size of a closure */
123214152SedBLOCK_EXPORT unsigned long int Block_size(void *block_basic);
124214152Sed
125214152Sed
126214152Sed
127214152Sed/* the raw data space for runtime classes for blocks */
128214152Sed/* class+meta used for stack, malloc, and collectable based blocks */
129214152SedBLOCK_EXPORT void * _NSConcreteStackBlock[32];
130214152SedBLOCK_EXPORT void * _NSConcreteMallocBlock[32];
131214152SedBLOCK_EXPORT void * _NSConcreteAutoBlock[32];
132214152SedBLOCK_EXPORT void * _NSConcreteFinalizingBlock[32];
133214152SedBLOCK_EXPORT void * _NSConcreteGlobalBlock[32];
134214152SedBLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32];
135214152Sed
136214152Sed
137214152Sed/* the intercept routines that must be used under GC */
138214152SedBLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
139214152Sed                                  void (*setHasRefcount)(const void *, const bool),
140214152Sed                                  void (*gc_assign_strong)(void *, void **),
141214152Sed                                  void (*gc_assign_weak)(const void *, void *),
142214152Sed                                  void (*gc_memmove)(void *, void *, unsigned long));
143214152Sed
144214152Sed/* earlier version, now simply transitional */
145214152SedBLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
146214152Sed                                  void (*setHasRefcount)(const void *, const bool),
147214152Sed                                  void (*gc_assign_strong)(void *, void **),
148214152Sed                                  void (*gc_assign_weak)(const void *, void *));
149214152Sed
150214152SedBLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *),
151214152Sed                                 void (*release)(const void *));
152214152Sed
153214152Sed/* make a collectable GC heap based Block.  Not useful under non-GC. */
154214152SedBLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock);
155214152Sed
156214152Sed/* thread-unsafe diagnostic */
157214152SedBLOCK_EXPORT const char *_Block_dump(const void *block);
158214152Sed
159214152Sed
160214152Sed/* Obsolete */
161214152Sed
162214152Sed/* first layout */
163214152Sedstruct Block_basic {
164214152Sed    void *isa;
165214152Sed    int Block_flags;  /* int32_t */
166214152Sed    int Block_size;  /* XXX should be packed into Block_flags */
167214152Sed    void (*Block_invoke)(void *);
168214152Sed    void (*Block_copy)(void *dst, void *src);  /* iff BLOCK_HAS_COPY_DISPOSE */
169214152Sed    void (*Block_dispose)(void *);             /* iff BLOCK_HAS_COPY_DISPOSE */
170214152Sed    /* long params[0];  // where const imports, __block storage references, etc. get laid down */
171214152Sed};
172214152Sed
173214152Sed
174214152Sed#if defined(__cplusplus)
175214152Sed}
176214152Sed#endif
177214152Sed
178214152Sed
179214152Sed#endif /* _BLOCK_PRIVATE_H_ */
180