Back to index

php5  5.3.10
Classes | Defines | Typedefs | Functions | Variables
zend_gc.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _gc_root_buffer
struct  _zval_gc_info
struct  _zend_gc_globals
union  _gc_root_buffer.u
union  _zval_gc_info.u

Defines

#define GC_BENCH   0
#define GC_BENCH_INC(counter)
#define GC_BENCH_DEC(counter)
#define GC_BENCH_PEAK(peak, counter)
#define GC_COLOR   0x03
#define GC_BLACK   0x00
#define GC_WHITE   0x01
#define GC_GREY   0x02
#define GC_PURPLE   0x03
#define GC_ADDRESS(v)   ((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))
#define GC_SET_ADDRESS(v, a)   (v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & GC_COLOR) | ((zend_uintptr_t)(a))))
#define GC_GET_COLOR(v)   (((zend_uintptr_t)(v)) & GC_COLOR)
#define GC_SET_COLOR(v, c)   (v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & ~GC_COLOR) | (c)))
#define GC_SET_BLACK(v)   (v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))
#define GC_SET_PURPLE(v)   (v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) | GC_PURPLE))
#define GC_ZVAL_INIT(z)   ((zval_gc_info*)(z))->u.buffered = NULL
#define GC_ZVAL_ADDRESS(v)   GC_ADDRESS(((zval_gc_info*)(v))->u.buffered)
#define GC_ZVAL_SET_ADDRESS(v, a)   GC_SET_ADDRESS(((zval_gc_info*)(v))->u.buffered, (a))
#define GC_ZVAL_GET_COLOR(v)   GC_GET_COLOR(((zval_gc_info*)(v))->u.buffered)
#define GC_ZVAL_SET_COLOR(v, c)   GC_SET_COLOR(((zval_gc_info*)(v))->u.buffered, (c))
#define GC_ZVAL_SET_BLACK(v)   GC_SET_BLACK(((zval_gc_info*)(v))->u.buffered)
#define GC_ZVAL_SET_PURPLE(v)   GC_SET_PURPLE(((zval_gc_info*)(v))->u.buffered)
#define GC_OBJ_INIT(z)   (z)->buffered = NULL
#define GC_G(v)   (gc_globals.v)
#define GC_ZVAL_CHECK_POSSIBLE_ROOT(z)   gc_zval_check_possible_root((z) TSRMLS_CC)
#define GC_REMOVE_FROM_BUFFER(current)   gc_remove_from_buffer((current) TSRMLS_CC)
#define GC_REMOVE_ZVAL_FROM_BUFFER(z)
#define GC_ZOBJ_CHECK_POSSIBLE_ROOT(zobject)
#define GC_REMOVE_ZOBJ_FROM_BUFFER(obj)
#define ALLOC_PERMANENT_ZVAL(z)
#define ALLOC_ZVAL(z)
#define FREE_ZVAL(z)
#define ALLOC_ZVAL_REL(z)
#define FREE_ZVAL_REL(z)
#define FREE_ZVAL_EX(z)   efree(z)
#define FREE_ZVAL_REL_EX(z)   efree_rel(z)

Typedefs

typedef struct _gc_root_buffer gc_root_buffer
typedef struct _zval_gc_info zval_gc_info
typedef struct _zend_gc_globals zend_gc_globals

Functions

ZEND_API int gc_collect_cycles (TSRMLS_D)
ZEND_API void gc_zval_possible_root (zval *zv TSRMLS_DC)
ZEND_API void gc_zobj_possible_root (zval *zv TSRMLS_DC)
ZEND_API void gc_remove_zval_from_buffer (zval *zv TSRMLS_DC)
ZEND_API void gc_globals_ctor (TSRMLS_D)
ZEND_API void gc_globals_dtor (TSRMLS_D)
ZEND_API void gc_init (TSRMLS_D)
ZEND_API void gc_reset (TSRMLS_D)
static zend_always_inline void gc_zval_check_possible_root (zval *z TSRMLS_DC)
static zend_always_inline void gc_remove_from_buffer (gc_root_buffer *root TSRMLS_DC)

Variables

ZEND_API zend_gc_globals gc_globals

Class Documentation

struct _gc_root_buffer

Definition at line 81 of file zend_gc.h.

Collaboration diagram for _gc_root_buffer:
Class Members
zend_object_handle handle
struct _gc_root_buffer * next
struct _gc_root_buffer * prev
union _gc_root_buffer u
struct _zval_gc_info

Definition at line 91 of file zend_gc.h.

Class Members
union _zval_gc_info u
zval z
struct _zend_gc_globals

Definition at line 99 of file zend_gc.h.

Collaboration diagram for _zend_gc_globals:
Class Members
gc_root_buffer * buf
zend_uint collected
gc_root_buffer * first_unused
zval_gc_info * free_list
zend_bool gc_active
zend_bool gc_enabled
zend_uint gc_runs
gc_root_buffer * last_unused
zval_gc_info * next_to_free
gc_root_buffer roots
gc_root_buffer * unused
zval_gc_info * zval_to_free
union _gc_root_buffer.u

Definition at line 85 of file zend_gc.h.

Class Members
zend_object_handlers * handlers
zval * pz
union _zval_gc_info.u

Definition at line 93 of file zend_gc.h.

Class Members
gc_root_buffer * buffered
struct _zval_gc_info * next

Define Documentation

#define ALLOC_PERMANENT_ZVAL (   z)
Value:
do {                                                                                \
              (z) = (zval*)malloc(sizeof(zval_gc_info));              \
              GC_ZVAL_INIT(z);                                                      \
       } while (0)

Definition at line 196 of file zend_gc.h.

#define ALLOC_ZVAL (   z)
Value:
do {                                                                                \
              (z) = (zval*)emalloc(sizeof(zval_gc_info));             \
              GC_ZVAL_INIT(z);                                                      \
       } while (0)

Definition at line 204 of file zend_gc.h.

#define ALLOC_ZVAL_REL (   z)
Value:
do {                                                                                \
              (z) = (zval*)emalloc_rel(sizeof(zval_gc_info));  \
              GC_ZVAL_INIT(z);                                                      \
       } while (0)

Definition at line 218 of file zend_gc.h.

#define FREE_ZVAL (   z)
Value:
do {                                                                                \
           GC_REMOVE_ZVAL_FROM_BUFFER(z);                             \
              efree(z);                                                                    \
       } while (0)

Definition at line 211 of file zend_gc.h.

#define FREE_ZVAL_EX (   z)    efree(z)

Definition at line 231 of file zend_gc.h.

#define FREE_ZVAL_REL (   z)
Value:
do {                                                                                \
           GC_REMOVE_ZVAL_FROM_BUFFER(z);                             \
              efree_rel(z);                                                         \
       } while (0)

Definition at line 225 of file zend_gc.h.

#define FREE_ZVAL_REL_EX (   z)    efree_rel(z)

Definition at line 234 of file zend_gc.h.

#define GC_ADDRESS (   v)    ((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))

Definition at line 50 of file zend_gc.h.

#define GC_BENCH   0

Definition at line 26 of file zend_gc.h.

#define GC_BENCH_DEC (   counter)

Definition at line 39 of file zend_gc.h.

#define GC_BENCH_INC (   counter)

Definition at line 38 of file zend_gc.h.

#define GC_BENCH_PEAK (   peak,
  counter 
)

Definition at line 40 of file zend_gc.h.

#define GC_BLACK   0x00

Definition at line 45 of file zend_gc.h.

#define GC_COLOR   0x03

Definition at line 43 of file zend_gc.h.

#define GC_G (   v)    (gc_globals.v)

Definition at line 137 of file zend_gc.h.

#define GC_GET_COLOR (   v)    (((zend_uintptr_t)(v)) & GC_COLOR)

Definition at line 54 of file zend_gc.h.

#define GC_GREY   0x02

Definition at line 47 of file zend_gc.h.

#define GC_OBJ_INIT (   z)    (z)->buffered = NULL

Definition at line 78 of file zend_gc.h.

#define GC_PURPLE   0x03

Definition at line 48 of file zend_gc.h.

#define GC_REMOVE_FROM_BUFFER (   current)    gc_remove_from_buffer((current) TSRMLS_CC)

Definition at line 155 of file zend_gc.h.

#define GC_REMOVE_ZOBJ_FROM_BUFFER (   obj)
Value:
do {                                                                                                            \
              if (GC_ADDRESS((obj)->buffered) && !GC_G(gc_active)) {                \
                     GC_BENCH_INC(zobj_remove_from_buffer);                                       \
                     GC_REMOVE_FROM_BUFFER(GC_ADDRESS((obj)->buffered));                   \
                     (obj)->buffered = NULL;                                                                    \
              }                                                                                                               \
       } while (0)

Definition at line 171 of file zend_gc.h.

#define GC_REMOVE_ZVAL_FROM_BUFFER (   z)
Value:
if (GC_ADDRESS(((zval_gc_info*)z)->u.buffered)) {       \
              gc_remove_zval_from_buffer(z TSRMLS_CC);         \
       }

Definition at line 158 of file zend_gc.h.

#define GC_SET_ADDRESS (   v,
 
)    (v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & GC_COLOR) | ((zend_uintptr_t)(a))))

Definition at line 52 of file zend_gc.h.

#define GC_SET_BLACK (   v)    (v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))

Definition at line 58 of file zend_gc.h.

#define GC_SET_COLOR (   v,
 
)    (v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & ~GC_COLOR) | (c)))

Definition at line 56 of file zend_gc.h.

#define GC_SET_PURPLE (   v)    (v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) | GC_PURPLE))

Definition at line 60 of file zend_gc.h.

#define GC_WHITE   0x01

Definition at line 46 of file zend_gc.h.

#define GC_ZOBJ_CHECK_POSSIBLE_ROOT (   zobject)
Value:
do {                                                                                                                          \
              if (EXPECTED(EG(objects_store).object_buckets != NULL) &&                           \
                  EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zobject)].valid) {       \
                     gc_zobj_possible_root(zobject TSRMLS_CC);                                           \
              }                                                                                                                             \
       } while (0)

Definition at line 163 of file zend_gc.h.

#define GC_ZVAL_ADDRESS (   v)    GC_ADDRESS(((zval_gc_info*)(v))->u.buffered)

Definition at line 65 of file zend_gc.h.

Definition at line 152 of file zend_gc.h.

#define GC_ZVAL_GET_COLOR (   v)    GC_GET_COLOR(((zval_gc_info*)(v))->u.buffered)

Definition at line 69 of file zend_gc.h.

#define GC_ZVAL_INIT (   z)    ((zval_gc_info*)(z))->u.buffered = NULL

Definition at line 63 of file zend_gc.h.

#define GC_ZVAL_SET_ADDRESS (   v,
 
)    GC_SET_ADDRESS(((zval_gc_info*)(v))->u.buffered, (a))

Definition at line 67 of file zend_gc.h.

#define GC_ZVAL_SET_BLACK (   v)    GC_SET_BLACK(((zval_gc_info*)(v))->u.buffered)

Definition at line 73 of file zend_gc.h.

#define GC_ZVAL_SET_COLOR (   v,
 
)    GC_SET_COLOR(((zval_gc_info*)(v))->u.buffered, (c))

Definition at line 71 of file zend_gc.h.

#define GC_ZVAL_SET_PURPLE (   v)    GC_SET_PURPLE(((zval_gc_info*)(v))->u.buffered)

Definition at line 75 of file zend_gc.h.


Typedef Documentation

typedef struct _zval_gc_info zval_gc_info

Function Documentation

Definition at line 651 of file zend_gc.c.

{
       int count = 0;

       if (GC_G(roots).next != &GC_G(roots)) {
              zval_gc_info *p, *q, *orig_free_list, *orig_next_to_free;

              if (GC_G(gc_active)) {
                     return 0;
              }
              GC_G(gc_runs)++;
              GC_G(zval_to_free) = FREE_LIST_END;
              GC_G(gc_active) = 1;
              gc_mark_roots(TSRMLS_C);
              gc_scan_roots(TSRMLS_C);
              gc_collect_roots(TSRMLS_C);

              orig_free_list = GC_G(free_list);
              orig_next_to_free = GC_G(next_to_free);
              p = GC_G(free_list) = GC_G(zval_to_free);
              GC_G(zval_to_free) = NULL;
              GC_G(gc_active) = 0;

              /* First call destructors */
              while (p != FREE_LIST_END) {
                     if (Z_TYPE(p->z) == IS_OBJECT) {
                            if (EG(objects_store).object_buckets &&
                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].valid &&
                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0 &&
                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor &&
                                   !EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called) {

                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called = 1;
                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount++;
                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor(EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.object, Z_OBJ_HANDLE(p->z) TSRMLS_CC);
                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount--;
                            }
                     }
                     count++;
                     p = p->u.next;
              }

              /* Destroy zvals */
              p = GC_G(free_list);
              while (p != FREE_LIST_END) {
                     GC_G(next_to_free) = p->u.next;
                     if (Z_TYPE(p->z) == IS_OBJECT) {
                            if (EG(objects_store).object_buckets &&
                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].valid &&
                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0) {
                                   EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount = 1;
                                   Z_TYPE(p->z) = IS_NULL;
                                   zend_objects_store_del_ref_by_handle_ex(Z_OBJ_HANDLE(p->z), Z_OBJ_HT(p->z) TSRMLS_CC);
                            }
                     } else if (Z_TYPE(p->z) == IS_ARRAY) {
                            Z_TYPE(p->z) = IS_NULL;
                            zend_hash_destroy(Z_ARRVAL(p->z));
                            FREE_HASHTABLE(Z_ARRVAL(p->z));
                     } else {
                            zval_dtor(&p->z);
                            Z_TYPE(p->z) = IS_NULL;
                     }
                     p = GC_G(next_to_free);
              }

              /* Free zvals */
              p = GC_G(free_list);
              while (p != FREE_LIST_END) {
                     q = p->u.next;
                     FREE_ZVAL_EX(&p->z);
                     p = q;
              }
              GC_G(collected) += count;
              GC_G(free_list) = orig_free_list;
              GC_G(next_to_free) = orig_next_to_free;
       }

       return count;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 72 of file zend_gc.c.

{
#ifdef ZTS
       ts_allocate_id(&gc_globals_id, sizeof(zend_gc_globals), (ts_allocate_ctor) gc_globals_ctor_ex, (ts_allocate_dtor) root_buffer_dtor);
#else
       gc_globals_ctor_ex(&gc_globals);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 81 of file zend_gc.c.

{
#ifndef ZTS
       root_buffer_dtor(&gc_globals TSRMLS_DC);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 121 of file zend_gc.c.

{
       if (GC_G(buf) == NULL && GC_G(gc_enabled)) {
              GC_G(buf) = (gc_root_buffer*) malloc(sizeof(gc_root_buffer) * GC_ROOT_BUFFER_MAX_ENTRIES);
              GC_G(last_unused) = &GC_G(buf)[GC_ROOT_BUFFER_MAX_ENTRIES];
              gc_reset(TSRMLS_C);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static zend_always_inline void gc_remove_from_buffer ( gc_root_buffer *root  TSRMLS_DC) [static]

Definition at line 187 of file zend_gc.h.

{
       root->next->prev = root->prev;
       root->prev->next = root->next;
       root->prev = GC_G(unused);
       GC_G(unused) = root;
       GC_BENCH_DEC(root_buf_length);
}
ZEND_API void gc_remove_zval_from_buffer ( zval *zv  TSRMLS_DC)

Definition at line 249 of file zend_gc.c.

{
       gc_root_buffer* root_buffer = GC_ADDRESS(((zval_gc_info*)zv)->u.buffered);

       if (UNEXPECTED(GC_G(free_list) != NULL &&
                         GC_ZVAL_GET_COLOR(zv) == GC_BLACK) &&
                         (GC_ZVAL_ADDRESS(zv) < GC_G(buf) ||
                          GC_ZVAL_ADDRESS(zv) >= GC_G(last_unused))) {
              /* The given zval is a garbage that is going to be deleted by
               * currently running GC */
              if (GC_G(next_to_free) == (zval_gc_info*)zv) {
                     GC_G(next_to_free) = ((zval_gc_info*)zv)->u.next;
              }
              return;
       }
       GC_BENCH_INC(zval_remove_from_buffer);
       GC_REMOVE_FROM_BUFFER(root_buffer);
       ((zval_gc_info*)zv)->u.buffered = NULL;
}

Definition at line 88 of file zend_gc.c.

{
       GC_G(gc_runs) = 0;
       GC_G(collected) = 0;

#if GC_BENCH
       GC_G(root_buf_length) = 0;
       GC_G(root_buf_peak) = 0;
       GC_G(zval_possible_root) = 0;
       GC_G(zobj_possible_root) = 0;
       GC_G(zval_buffered) = 0;
       GC_G(zobj_buffered) = 0;
       GC_G(zval_remove_from_buffer) = 0;
       GC_G(zobj_remove_from_buffer) = 0;
       GC_G(zval_marked_grey) = 0;
       GC_G(zobj_marked_grey) = 0;
#endif

       GC_G(roots).next = &GC_G(roots);
       GC_G(roots).prev = &GC_G(roots);

       if (GC_G(buf)) {
              GC_G(unused) = NULL;
              GC_G(first_unused) = GC_G(buf);

              GC_G(zval_to_free) = NULL;
       } else {
              GC_G(unused) = NULL;
              GC_G(first_unused) = NULL;
              GC_G(last_unused) = NULL;
       }
}

Here is the caller graph for this function:

ZEND_API void gc_zobj_possible_root ( zval *zv  TSRMLS_DC)

Definition at line 193 of file zend_gc.c.

{
       struct _store_object *obj;

       if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_properties == NULL ||
           EG(objects_store).object_buckets == NULL)) {
              return;
       }

       GC_BENCH_INC(zobj_possible_root);

       obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zv)].bucket.obj;
       if (GC_GET_COLOR(obj->buffered) != GC_PURPLE) {
              GC_SET_PURPLE(obj->buffered);
              if (!GC_ADDRESS(obj->buffered)) {
                     gc_root_buffer *newRoot = GC_G(unused);

                     if (newRoot) {
                            GC_G(unused) = newRoot->prev;
                     } else if (GC_G(first_unused) != GC_G(last_unused)) {
                            newRoot = GC_G(first_unused);
                            GC_G(first_unused)++;
                     } else {
                            if (!GC_G(gc_enabled)) {
                                   GC_ZVAL_SET_BLACK(zv);
                                   return;
                            }
                            zv->refcount__gc++;
                            gc_collect_cycles(TSRMLS_C);
                            zv->refcount__gc--;
                            newRoot = GC_G(unused);
                            if (!newRoot) {
                                   return;
                            }
                            obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zv)].bucket.obj;
                            GC_SET_PURPLE(obj->buffered);
                            GC_G(unused) = newRoot->prev;
                     }

                     newRoot->next = GC_G(roots).next;
                     newRoot->prev = &GC_G(roots);
                     GC_G(roots).next->prev = newRoot;
                     GC_G(roots).next = newRoot;

                     GC_SET_ADDRESS(obj->buffered, newRoot);

                     newRoot->handle = Z_OBJ_HANDLE_P(zv);
                     newRoot->u.handlers = Z_OBJ_HT_P(zv);

                     GC_BENCH_INC(zobj_buffered);
                     GC_BENCH_INC(root_buf_length);
                     GC_BENCH_PEAK(root_buf_peak, root_buf_length);
              }
       }
}

Here is the call graph for this function:

static zend_always_inline void gc_zval_check_possible_root ( zval *z  TSRMLS_DC) [static]

Definition at line 180 of file zend_gc.h.

{
       if (z->type == IS_ARRAY || z->type == IS_OBJECT) {
              gc_zval_possible_root(z TSRMLS_CC);
       }
}

Here is the call graph for this function:

ZEND_API void gc_zval_possible_root ( zval *zv  TSRMLS_DC)

Definition at line 130 of file zend_gc.c.

{
       if (UNEXPECTED(GC_G(free_list) != NULL &&
                      GC_ZVAL_ADDRESS(zv) != NULL &&
                         GC_ZVAL_GET_COLOR(zv) == GC_BLACK) &&
                         (GC_ZVAL_ADDRESS(zv) < GC_G(buf) ||
                          GC_ZVAL_ADDRESS(zv) >= GC_G(last_unused))) {
              /* The given zval is a garbage that is going to be deleted by
               * currently running GC */
              return;
       }

       if (zv->type == IS_OBJECT) {
              GC_ZOBJ_CHECK_POSSIBLE_ROOT(zv);
              return;
       }

       GC_BENCH_INC(zval_possible_root);

       if (GC_ZVAL_GET_COLOR(zv) != GC_PURPLE) {
              GC_ZVAL_SET_PURPLE(zv);

              if (!GC_ZVAL_ADDRESS(zv)) {
                     gc_root_buffer *newRoot = GC_G(unused);

                     if (newRoot) {
                            GC_G(unused) = newRoot->prev;
                     } else if (GC_G(first_unused) != GC_G(last_unused)) {
                            newRoot = GC_G(first_unused);
                            GC_G(first_unused)++;
                     } else {
                            if (!GC_G(gc_enabled)) {
                                   GC_ZVAL_SET_BLACK(zv);
                                   return;
                            }
                            zv->refcount__gc++;
                            gc_collect_cycles(TSRMLS_C);
                            zv->refcount__gc--;
                            newRoot = GC_G(unused);
                            if (!newRoot) {
                                   return;
                            }
                            GC_ZVAL_SET_PURPLE(zv);
                            GC_G(unused) = newRoot->prev;
                     }

                     newRoot->next = GC_G(roots).next;
                     newRoot->prev = &GC_G(roots);
                     GC_G(roots).next->prev = newRoot;
                     GC_G(roots).next = newRoot;

                     GC_ZVAL_SET_ADDRESS(zv, newRoot);

                     newRoot->handle = 0;
                     newRoot->u.pz = zv;

                     GC_BENCH_INC(zval_buffered);
                     GC_BENCH_INC(root_buf_length);
                     GC_BENCH_PEAK(root_buf_peak, root_buf_length);
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 30 of file zend_gc.c.