177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/*
277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * Block_private.h
377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *
477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * Copyright 2008-2009 Apple, Inc. Permission is hereby granted, free of charge,
577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * to any person obtaining a copy of this software and associated documentation
677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * files (the "Software"), to deal in the Software without restriction,
777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * including without limitation the rights to use, copy, modify, merge, publish,
877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * distribute, sublicense, and/or sell copies of the Software, and to permit
977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * persons to whom the Software is furnished to do so, subject to the following
1077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * conditions:
1177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *
1277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * The above copyright notice and this permission notice shall be included in
1377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * all copies or substantial portions of the Software.
1477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *
1577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * SOFTWARE.
2277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *
2377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */
2477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
2577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#ifndef _BLOCK_PRIVATE_H_
2677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#define _BLOCK_PRIVATE_H_
2777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
2877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#if !defined(BLOCK_EXPORT)
2977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#   if defined(__cplusplus)
3077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#       define BLOCK_EXPORT extern "C"
3177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#   else
3277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#       define BLOCK_EXPORT extern
3377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#   endif
3477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#endif
3577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
3677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#include <stdbool.h>
3777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
3877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#if defined(__cplusplus)
3977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaoextern "C" {
4077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#endif
4177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
4277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
4377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaoenum {
4477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_REFCOUNT_MASK =     (0xffff),
4577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_NEEDS_FREE =        (1 << 24),
4677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
4777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_HAS_CTOR =          (1 << 26), /* Helpers have C++ code. */
4877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_IS_GC =             (1 << 27),
4977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_IS_GLOBAL =         (1 << 28),
5077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_HAS_DESCRIPTOR =    (1 << 29)
5177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao};
5277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
5377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
5477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Revised new layout. */
5577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaostruct Block_descriptor {
5677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    unsigned long int reserved;
5777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    unsigned long int size;
5877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void (*copy)(void *dst, void *src);
5977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void (*dispose)(void *);
6077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao};
6177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
6277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
6377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaostruct Block_layout {
6477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void *isa;
6577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int flags;
6677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int reserved;
6777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void (*invoke)(void *, ...);
6877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    struct Block_descriptor *descriptor;
6977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    /* Imported variables. */
7077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao};
7177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
7277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
7377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaostruct Block_byref {
7477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void *isa;
7577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    struct Block_byref *forwarding;
7677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int flags; /* refcount; */
7777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int size;
7877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src);
7977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void (*byref_destroy)(struct Block_byref *);
8077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    /* long shared[0]; */
8177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao};
8277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
8377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
8477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaostruct Block_byref_header {
8577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void *isa;
8677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    struct Block_byref *forwarding;
8777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int flags;
8877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int size;
8977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao};
9077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
9177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
9277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Runtime support functions used by compiler when generating copy/dispose helpers. */
9377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
9477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaoenum {
9577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    /* See function implementation for a more complete description of these fields and combinations */
9677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)), block, ... */
9777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
9877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the __block variable */
9977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy helpers */
10077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    BLOCK_BYREF_CALLER      = 128  /* called from __block (byref) copy/dispose support routines. */
10177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao};
10277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
10377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Runtime entry point called by compiler when assigning objects inside copy helper routines */
10477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags);
10577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    /* BLOCK_FIELD_IS_BYREF is only used from within block copy helpers */
10677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
10777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
10877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* runtime entry point called by the compiler when disposing of objects inside dispose helper routine */
10977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags);
11077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
11177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
11277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
11377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Other support functions */
11477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
11577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Runtime entry to get total size of a closure */
11677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT unsigned long int Block_size(void *block_basic);
11777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
11877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
11977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
12077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* the raw data space for runtime classes for blocks */
12177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* class+meta used for stack, malloc, and collectable based blocks */
12277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void * _NSConcreteStackBlock[32];
12377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void * _NSConcreteMallocBlock[32];
12477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void * _NSConcreteAutoBlock[32];
12577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void * _NSConcreteFinalizingBlock[32];
12677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void * _NSConcreteGlobalBlock[32];
12777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32];
12877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
12977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
13077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* the intercept routines that must be used under GC */
13177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
13277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                                  void (*setHasRefcount)(const void *, const bool),
13377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                                  void (*gc_assign_strong)(void *, void **),
13477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                                  void (*gc_assign_weak)(const void *, void *),
13577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                                  void (*gc_memmove)(void *, void *, unsigned long));
13677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
13777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* earlier version, now simply transitional */
13877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
13977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                                  void (*setHasRefcount)(const void *, const bool),
14077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                                  void (*gc_assign_strong)(void *, void **),
14177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                                  void (*gc_assign_weak)(const void *, void *));
14277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
14377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *),
14477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                                 void (*release)(const void *));
14577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
14677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* make a collectable GC heap based Block.  Not useful under non-GC. */
14777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock);
14877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
14977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* thread-unsafe diagnostic */
15077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei LiaoBLOCK_EXPORT const char *_Block_dump(const void *block);
15177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
15277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
15377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Obsolete */
15477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
15577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* first layout */
15677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaostruct Block_basic {
15777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void *isa;
15877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int Block_flags;  /* int32_t */
15977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int Block_size;  /* XXX should be packed into Block_flags */
16077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void (*Block_invoke)(void *);
16177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void (*Block_copy)(void *dst, void *src);  /* iff BLOCK_HAS_COPY_DISPOSE */
16277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    void (*Block_dispose)(void *);             /* iff BLOCK_HAS_COPY_DISPOSE */
16377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    /* long params[0];  // where const imports, __block storage references, etc. get laid down */
16477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao};
16577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
16677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
16777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#if defined(__cplusplus)
16877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao}
16977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#endif
17077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
17177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
17277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#endif /* _BLOCK_PRIVATE_H_ */
173