Annotation of embedaddon/php/Zend/zend_gc.h, revision 1.1.1.3

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | Zend Engine                                                          |
                      4:    +----------------------------------------------------------------------+
1.1.1.3 ! misho       5:    | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
1.1       misho       6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 2.00 of the Zend license,     |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.zend.com/license/2_00.txt.                                |
                     11:    | If you did not receive a copy of the Zend license and are unable to  |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@zend.com so we can mail you a copy immediately.              |
                     14:    +----------------------------------------------------------------------+
                     15:    | Authors: David Wang <planetbeing@gmail.com>                          |
                     16:    |          Dmitry Stogov <dmitry@zend.com>                             |
                     17:    +----------------------------------------------------------------------+
                     18: */
                     19: 
1.1.1.2   misho      20: /* $Id$ */
1.1       misho      21: 
                     22: #ifndef ZEND_GC_H
                     23: #define ZEND_GC_H
                     24: 
                     25: #ifndef GC_BENCH
                     26: # define GC_BENCH 0
                     27: #endif
                     28: 
                     29: #if GC_BENCH
                     30: # define GC_BENCH_INC(counter) GC_G(counter)++
                     31: # define GC_BENCH_DEC(counter) GC_G(counter)--
                     32: # define GC_BENCH_PEAK(peak, counter) do {             \
                     33:                if (GC_G(counter) > GC_G(peak)) {               \
                     34:                        GC_G(peak) = GC_G(counter);                     \
                     35:                }                                                                               \
                     36:        } while (0)
                     37: #else
                     38: # define GC_BENCH_INC(counter)
                     39: # define GC_BENCH_DEC(counter)
                     40: # define GC_BENCH_PEAK(peak, counter)
                     41: #endif
                     42: 
                     43: #define GC_COLOR  0x03
                     44: 
                     45: #define GC_BLACK  0x00
                     46: #define GC_WHITE  0x01
                     47: #define GC_GREY   0x02
                     48: #define GC_PURPLE 0x03
                     49: 
                     50: #define GC_ADDRESS(v) \
                     51:        ((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))
                     52: #define GC_SET_ADDRESS(v, a) \
                     53:        (v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & GC_COLOR) | ((zend_uintptr_t)(a))))
                     54: #define GC_GET_COLOR(v) \
                     55:        (((zend_uintptr_t)(v)) & GC_COLOR)
                     56: #define GC_SET_COLOR(v, c) \
                     57:        (v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & ~GC_COLOR) | (c)))
                     58: #define GC_SET_BLACK(v) \
                     59:        (v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))
                     60: #define GC_SET_PURPLE(v) \
                     61:        (v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) | GC_PURPLE))
                     62: 
                     63: #define GC_ZVAL_INIT(z) \
                     64:        ((zval_gc_info*)(z))->u.buffered = NULL
                     65: #define GC_ZVAL_ADDRESS(v) \
                     66:        GC_ADDRESS(((zval_gc_info*)(v))->u.buffered)
                     67: #define GC_ZVAL_SET_ADDRESS(v, a) \
                     68:        GC_SET_ADDRESS(((zval_gc_info*)(v))->u.buffered, (a))
                     69: #define GC_ZVAL_GET_COLOR(v) \
                     70:        GC_GET_COLOR(((zval_gc_info*)(v))->u.buffered)
                     71: #define GC_ZVAL_SET_COLOR(v, c) \
                     72:        GC_SET_COLOR(((zval_gc_info*)(v))->u.buffered, (c))
                     73: #define GC_ZVAL_SET_BLACK(v) \
                     74:        GC_SET_BLACK(((zval_gc_info*)(v))->u.buffered)
                     75: #define GC_ZVAL_SET_PURPLE(v) \
                     76:        GC_SET_PURPLE(((zval_gc_info*)(v))->u.buffered)
                     77: 
                     78: #define GC_OBJ_INIT(z) \
                     79:        (z)->buffered = NULL
                     80: 
                     81: typedef struct _gc_root_buffer {
                     82:        struct _gc_root_buffer   *prev;         /* double-linked list               */
                     83:        struct _gc_root_buffer   *next;
                     84:        zend_object_handle        handle;       /* must be 0 for zval               */
                     85:        union {
                     86:                zval                 *pz;
1.1.1.2   misho      87:                const zend_object_handlers *handlers;
1.1       misho      88:        } u;
                     89: } gc_root_buffer;
                     90: 
                     91: typedef struct _zval_gc_info {
                     92:        zval z;
                     93:        union {
                     94:                gc_root_buffer       *buffered;
                     95:                struct _zval_gc_info *next;
                     96:        } u;
                     97: } zval_gc_info;
                     98: 
                     99: typedef struct _zend_gc_globals {
                    100:        zend_bool         gc_enabled;
                    101:        zend_bool         gc_active;
                    102: 
                    103:        gc_root_buffer   *buf;                          /* preallocated arrays of buffers   */
                    104:        gc_root_buffer    roots;                        /* list of possible roots of cycles */
                    105:        gc_root_buffer   *unused;                       /* list of unused buffers           */
                    106:        gc_root_buffer   *first_unused;         /* pointer to first unused buffer   */
                    107:        gc_root_buffer   *last_unused;          /* pointer to last unused buffer    */
                    108: 
1.1.1.3 ! misho     109:        zval_gc_info     *zval_to_free;         /* temporary list of zvals to free */
1.1       misho     110:        zval_gc_info     *free_list;
                    111:        zval_gc_info     *next_to_free;
                    112: 
                    113:        zend_uint gc_runs;
                    114:        zend_uint collected;
                    115: 
                    116: #if GC_BENCH
                    117:        zend_uint root_buf_length;
                    118:        zend_uint root_buf_peak;
                    119:        zend_uint zval_possible_root;
                    120:        zend_uint zobj_possible_root;
                    121:        zend_uint zval_buffered;
                    122:        zend_uint zobj_buffered;
                    123:        zend_uint zval_remove_from_buffer;
                    124:        zend_uint zobj_remove_from_buffer;
                    125:        zend_uint zval_marked_grey;
                    126:        zend_uint zobj_marked_grey;
                    127: #endif
                    128: 
                    129: } zend_gc_globals;
                    130: 
                    131: #ifdef ZTS
                    132: BEGIN_EXTERN_C()
                    133: ZEND_API extern int gc_globals_id;
                    134: END_EXTERN_C()
                    135: #define GC_G(v) TSRMG(gc_globals_id, zend_gc_globals *, v)
                    136: #else
                    137: #define GC_G(v) (gc_globals.v)
                    138: extern ZEND_API zend_gc_globals gc_globals;
                    139: #endif
                    140: 
                    141: BEGIN_EXTERN_C()
                    142: ZEND_API int  gc_collect_cycles(TSRMLS_D);
                    143: ZEND_API void gc_zval_possible_root(zval *zv TSRMLS_DC);
                    144: ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC);
                    145: ZEND_API void gc_remove_zval_from_buffer(zval *zv TSRMLS_DC);
                    146: ZEND_API void gc_globals_ctor(TSRMLS_D);
                    147: ZEND_API void gc_globals_dtor(TSRMLS_D);
                    148: ZEND_API void gc_init(TSRMLS_D);
                    149: ZEND_API void gc_reset(TSRMLS_D);
                    150: END_EXTERN_C()
                    151: 
                    152: #define GC_ZVAL_CHECK_POSSIBLE_ROOT(z) \
                    153:        gc_zval_check_possible_root((z) TSRMLS_CC)
                    154: 
                    155: #define GC_REMOVE_FROM_BUFFER(current) \
                    156:        gc_remove_from_buffer((current) TSRMLS_CC)
                    157: 
                    158: #define GC_REMOVE_ZVAL_FROM_BUFFER(z)                                  \
                    159:        if (GC_ADDRESS(((zval_gc_info*)z)->u.buffered)) {       \
                    160:                gc_remove_zval_from_buffer(z TSRMLS_CC);                \
                    161:        }
                    162: 
                    163: #define GC_ZOBJ_CHECK_POSSIBLE_ROOT(zobject)                                                                   \
                    164:        do {                                                                                                                                            \
                    165:                if (EXPECTED(EG(objects_store).object_buckets != NULL) &&                               \
                    166:                    EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zobject)].valid) {  \
                    167:                        gc_zobj_possible_root(zobject TSRMLS_CC);                                                       \
                    168:                }                                                                                                                                               \
                    169:        } while (0)
                    170: 
                    171: #define GC_REMOVE_ZOBJ_FROM_BUFFER(obj)                                                                        \
                    172:        do {                                                                                                                            \
                    173:                if (GC_ADDRESS((obj)->buffered) && !GC_G(gc_active)) {                  \
                    174:                        GC_BENCH_INC(zobj_remove_from_buffer);                                          \
                    175:                        GC_REMOVE_FROM_BUFFER(GC_ADDRESS((obj)->buffered));                     \
                    176:                        (obj)->buffered = NULL;                                                                         \
                    177:                }                                                                                                                               \
                    178:        } while (0)
                    179: 
                    180: static zend_always_inline void gc_zval_check_possible_root(zval *z TSRMLS_DC)
                    181: {
                    182:        if (z->type == IS_ARRAY || z->type == IS_OBJECT) {
                    183:                gc_zval_possible_root(z TSRMLS_CC);
                    184:        }
                    185: }
                    186: 
                    187: static zend_always_inline void gc_remove_from_buffer(gc_root_buffer *root TSRMLS_DC)
                    188: {
                    189:        root->next->prev = root->prev;
                    190:        root->prev->next = root->next;
                    191:        root->prev = GC_G(unused);
                    192:        GC_G(unused) = root;
                    193:        GC_BENCH_DEC(root_buf_length);
                    194: }
                    195: 
                    196: #define ALLOC_PERMANENT_ZVAL(z)                                                        \
                    197:        do {                                                                                            \
                    198:                (z) = (zval*)malloc(sizeof(zval_gc_info));              \
                    199:                GC_ZVAL_INIT(z);                                                                \
                    200:        } while (0)
                    201: 
1.1.1.3 ! misho     202: /* The following macros override macros from zend_alloc.h */
1.1       misho     203: #undef  ALLOC_ZVAL
                    204: #define ALLOC_ZVAL(z)                                                                  \
                    205:        do {                                                                                            \
                    206:                (z) = (zval*)emalloc(sizeof(zval_gc_info));             \
                    207:                GC_ZVAL_INIT(z);                                                                \
                    208:        } while (0)
                    209: 
                    210: #undef  FREE_ZVAL
                    211: #define FREE_ZVAL(z)                                                                   \
                    212:        do {                                                                                            \
                    213:            GC_REMOVE_ZVAL_FROM_BUFFER(z);                                      \
                    214:                efree(z);                                                                               \
                    215:        } while (0)
                    216: 
                    217: #undef  ALLOC_ZVAL_REL
                    218: #define ALLOC_ZVAL_REL(z)                                                              \
                    219:        do {                                                                                            \
                    220:                (z) = (zval*)emalloc_rel(sizeof(zval_gc_info)); \
                    221:                GC_ZVAL_INIT(z);                                                                \
                    222:        } while (0)
                    223: 
                    224: #undef  FREE_ZVAL_REL
                    225: #define FREE_ZVAL_REL(z)                                                               \
                    226:        do {                                                                                            \
                    227:            GC_REMOVE_ZVAL_FROM_BUFFER(z);                                      \
                    228:                efree_rel(z);                                                                   \
                    229:        } while (0)
                    230: 
                    231: #define FREE_ZVAL_EX(z)                                                                        \
                    232:        efree(z)
                    233: 
                    234: #define FREE_ZVAL_REL_EX(z)                                                            \
                    235:        efree_rel(z)
                    236: 
                    237: #endif /* ZEND_GC_H */
                    238: 
                    239: /*
                    240:  * Local variables:
                    241:  * tab-width: 4
                    242:  * c-basic-offset: 4
                    243:  * indent-tabs-mode: t
                    244:  * End:
                    245:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>