summaryrefslogtreecommitdiff
path: root/Zend/zend_gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_gc.c')
-rw-r--r--Zend/zend_gc.c57
1 files changed, 53 insertions, 4 deletions
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index 95be5d80c0..377280e17c 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -19,6 +19,56 @@
/* $Id$ */
+
+/**
+ * zend_gc_collect_cycles
+ * ======================
+ *
+ * Colors and its meaning
+ * ----------------------
+ *
+ * BLACK (GC_BLACK) - In use or free.
+ * GREY (GC_GREY) - Possible member of cycle.
+ * WHITE (GC_WHITE) - Member of garbage cycle.
+ * PURPLE (GC_PURPLE) - Possible root of cycle.
+ *
+ * Colors described in the paper but not used
+ * ------------------------------------------
+ *
+ * GREEN - Acyclic
+ * RED - Candidate cycle underogin
+ * ORANGE - Candidate cycle awaiting epoch boundary.
+ *
+ *
+ * Flow
+ * =====
+ *
+ * The garbage collect cycle starts from 'gc_mark_roots', which traverses the
+ * possible roots, and calls mark_grey for roots are marked purple with
+ * depth-first traverse.
+ *
+ * After all possible roots are traversed and marked,
+ * gc_scan_roots will be called, and each root will be called with
+ * gc_scan(root->ref)
+ *
+ * gc_scan checkes the colors of possible members.
+ *
+ * If the node is marked as grey and the refcount > 0
+ * gc_scan_black will be called on that node to scan it's subgraph.
+ * otherwise (refcount == 0), it marks the node white.
+ *
+ * A node MAY be added to possbile roots when ZEND_UNSET_VAR happens or
+ * zend_assign_to_variable is called only when possible garbage node is
+ * produced.
+ * gc_possible_root() will be called to add the nodes to possible roots.
+ *
+ *
+ * For objects, we call their get_gc handler (by default 'zend_std_get_gc') to
+ * get the object properties to scan.
+ *
+ *
+ * @see http://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon01Concurrent.pdf
+ */
#include "zend.h"
#include "zend_API.h"
@@ -243,7 +293,7 @@ ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref)
gc_collect_cycles();
GC_REFCOUNT(ref)--;
if (UNEXPECTED(GC_REFCOUNT(ref)) == 0) {
- zval_dtor_func_for_ptr(ref);
+ zval_dtor_func(ref);
return;
}
if (UNEXPECTED(GC_INFO(ref))) {
@@ -685,7 +735,6 @@ static void gc_add_garbage(zend_refcounted *ref, gc_additional_buffer **addition
GC_TYPE(ref) |= GC_FAKE_BUFFER_FLAG;
}
if (buf) {
- GC_REFCOUNT(ref)++;
buf->ref = ref;
buf->next = GC_G(roots).next;
buf->prev = &GC_G(roots);
@@ -848,7 +897,6 @@ static int gc_collect_roots(uint32_t *flags, gc_additional_buffer **additional_b
current = GC_G(roots).next;
while (current != &GC_G(roots)) {
- GC_REFCOUNT(current->ref)++;
if (GC_REF_GET_COLOR(current->ref) == GC_WHITE) {
count += gc_collect_white(current->ref, flags, additional_buffer);
}
@@ -889,7 +937,6 @@ tail_call:
GC_REF_GET_COLOR(ref) == GC_BLACK &&
GC_ADDRESS(GC_INFO(ref)) != GC_ROOT_BUFFER_MAX_ENTRIES)) {
GC_TRACE_REF(ref, "removing from buffer");
- GC_REFCOUNT(ref)--;
if (root) {
GC_INFO(ref) = 0;
GC_REMOVE_FROM_ROOTS(root);
@@ -1157,4 +1204,6 @@ ZEND_API int zend_gc_collect_cycles(void)
* c-basic-offset: 4
* indent-tabs-mode: t
* End:
+ *
+ * vim:noexpandtab:
*/