cvs: ZendEngine2(PHP_5_3) / zend_gc.c zend_gc.h /tests gc_029.phpt

[email protected] ("Dmitry Stogov")
Newsgroups php.zend-engine.cvs
Message-ID <cvsdmitry1205519795@cvsserver>
dmitry		Fri Mar 14 18:36:35 2008 UTC

  Added files:                 (Branch: PHP_5_3)
    /ZendEngine2/tests	gc_029.phpt 

  Modified files:              
    /ZendEngine2	zend_gc.c zend_gc.h 
  Log:
  Improve GC to support garbage created in destructors during objects utilization
  
  
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_gc.c?r1=1.1.2.8&r2=1.1.2.9&diff_format=u
Index: ZendEngine2/zend_gc.c
diff -u ZendEngine2/zend_gc.c:1.1.2.8 ZendEngine2/zend_gc.c:1.1.2.9
--- ZendEngine2/zend_gc.c:1.1.2.8	Fri Mar 14 13:35:40 2008
+++ ZendEngine2/zend_gc.c	Fri Mar 14 18:36:34 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_gc.c,v 1.1.2.8 2008/03/14 13:35:40 dmitry Exp $ */
+/* $Id: zend_gc.c,v 1.1.2.9 2008/03/14 18:36:34 dmitry Exp $ */
 
 #include "zend.h"
 #include "zend_API.h"
@@ -56,6 +56,7 @@
 	gc_globals->unused = NULL;
 	gc_globals->zval_to_free = NULL;
 	gc_globals->free_list = NULL;
+	gc_globals->next_to_free = NULL;
 
 	gc_globals->gc_runs = 0;
 	gc_globals->collected = 0;
@@ -138,7 +139,7 @@
 ZEND_API void gc_zval_possible_root(zval *zv TSRMLS_DC)
 {
 	if (UNEXPECTED(GC_G(free_list) != NULL &&
-		           GC_ZVAL_ADDRESS(zv) != NULL &&
+	               GC_ZVAL_ADDRESS(zv) != NULL &&
 		           GC_ZVAL_GET_COLOR(zv) == GC_BLACK)) {
 		zval_gc_info **p = &GC_G(free_list);
 
@@ -260,6 +261,9 @@
 
 		while (*p != NULL) {
 			if (*p == (zval_gc_info*)zv) {
+				if (GC_G(next_to_free) == (zval_gc_info*)zv) {
+					GC_G(next_to_free) = ((zval_gc_info*)zv)->u.next;
+				}
 				*p = (*p)->u.next;
 				return;
 			}
@@ -470,14 +474,9 @@
 
 		if (Z_TYPE_P(pz) == IS_OBJECT) {
 			zobj_collect_white(pz TSRMLS_CC);
-			if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
-			             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-				Z_OBJPROP_P(pz)->pDestructor = NULL;
-			}
 		} else {
 			if (Z_TYPE_P(pz) == IS_ARRAY) {
 				zend_hash_apply(Z_ARRVAL_P(pz), (apply_func_t) children_collect_white TSRMLS_CC);
-				Z_ARRVAL_P(pz)->pDestructor = NULL;
 			}
 		}
 
@@ -521,30 +520,33 @@
 	}
 }
 
+#define FREE_LIST_END ((zval_gc_info*)((-1)|~GC_COLOR))
+
 ZEND_API int gc_collect_cycles(TSRMLS_D)
 {
 	int count = 0;
 
 	if (GC_G(roots).next != &GC_G(roots)) {
-		zval_gc_info *p, *q, *orig_free_list;
+		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) = NULL;
+		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) {
+		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 &&
@@ -558,32 +560,47 @@
 					} zend_end_try();
 				}
 			}
+			count++;
 			p = p->u.next;
 		}
 
+		/* Destroy zvals */
 		p = GC_G(free_list);
-		while (p) {
-			q = p->u.next;
+		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;
 					zend_try {
+						Z_TYPE(p->z) = IS_NULL;
 						zend_objects_store_del_ref_by_handle(Z_OBJ_HANDLE(p->z) TSRMLS_CC);
 					} zend_end_try();
 				}
+			} 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 {
 				zend_try {
 					zval_dtor(&p->z);
 				} zend_end_try();
+				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;
-			count++;
 		}
 		GC_G(collected) += count;
 		GC_G(free_list) = orig_free_list;
+		GC_G(next_to_free) = orig_next_to_free;
 	}
 
 	return count;
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_gc.h?r1=1.1.2.5&r2=1.1.2.6&diff_format=u
Index: ZendEngine2/zend_gc.h
diff -u ZendEngine2/zend_gc.h:1.1.2.5 ZendEngine2/zend_gc.h:1.1.2.6
--- ZendEngine2/zend_gc.h:1.1.2.5	Fri Mar 14 13:35:40 2008
+++ ZendEngine2/zend_gc.h	Fri Mar 14 18:36:34 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_gc.h,v 1.1.2.5 2008/03/14 13:35:40 dmitry Exp $ */
+/* $Id: zend_gc.h,v 1.1.2.6 2008/03/14 18:36:34 dmitry Exp $ */
 
 #ifndef ZEND_GC_H
 #define ZEND_GC_H
@@ -106,6 +106,7 @@
 
 	zval_gc_info     *zval_to_free;		/* temporaryt list of zvals to free */
 	zval_gc_info     *free_list;
+	zval_gc_info     *next_to_free;
 
 	zend_uint gc_runs;
 	zend_uint collected;

http://cvs.php.net/viewvc.cgi/ZendEngine2/tests/gc_029.phpt?view=markup&rev=1.1
Index: ZendEngine2/tests/gc_029.phpt
+++ ZendEngine2/tests/gc_029.phpt
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.