php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #60139
Patch gc-closure2.diff revision 2011-10-31 11:04 UTC by dmitry@php.net
Patch gc-closure.diff revision 2011-10-31 11:04 UTC by dmitry@php.net
revision 2011-10-31 08:44 UTC by dmitry@php.net
Patch bug60139.php5.4.diff revision 2011-10-29 10:23 UTC by arnaud dot lb at gmail dot com
Patch test2.phpt revision 2011-10-28 14:24 UTC by arnaud dot lb at gmail dot com
Patch test1.phpt revision 2011-10-28 14:23 UTC by arnaud dot lb at gmail dot com

Patch gc-closure2.diff for Performance problem Bug #60139

Patch version 2011-10-31 11:04 UTC

Return to Bug #60139 | Download this patch
Patch Revisions:

Developer: dmitry@php.net

Index: php5.3/Zend/zend_closures.c
===================================================================
--- php5.3/Zend/zend_closures.c	(revision 318599)
+++ php5.3/Zend/zend_closures.c	(working copy)
@@ -280,6 +280,18 @@
 }
 /* }}} */
 
+static HashTable *zend_closure_get_properties(zval *obj TSRMLS_DC) /* {{{ */
+{
+	zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);	
+
+	if (GC_G(gc_active)) {
+		return (closure->func.type == ZEND_USER_FUNCTION) ? closure->func.op_array.static_variables : NULL;
+	}
+
+	return closure->std.properties;
+}
+/* }}} */
+
 /* {{{ proto Closure::__construct()
    Private constructor preventing instantiation */
 ZEND_METHOD(Closure, __construct)
@@ -316,6 +328,7 @@
 	closure_handlers.clone_obj = NULL;
 	closure_handlers.get_debug_info = zend_closure_get_debug_info;
 	closure_handlers.get_closure = zend_closure_get_closure;
+	closure_handlers.get_properties = zend_closure_get_properties;
 }
 /* }}} */
 
Index: php5.4/Zend/zend_closures.c
===================================================================
--- php5.4/Zend/zend_closures.c	(revision 318599)
+++ php5.4/Zend/zend_closures.c	(working copy)
@@ -376,6 +376,17 @@
 }
 /* }}} */
 
+static HashTable *zend_closure_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{ */
+{
+	zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);	
+
+	*table = closure->this_ptr ? &closure->this_ptr : NULL;
+	*n = closure->this_ptr ? 1 : 0;
+	return (closure->func.type == ZEND_USER_FUNCTION) ?
+		closure->func.op_array.static_variables : NULL;
+}
+/* }}} */
+
 /* {{{ proto Closure::__construct()
    Private constructor preventing instantiation */
 ZEND_METHOD(Closure, __construct)
@@ -425,6 +436,7 @@
 	closure_handlers.clone_obj = zend_closure_clone;
 	closure_handlers.get_debug_info = zend_closure_get_debug_info;
 	closure_handlers.get_closure = zend_closure_get_closure;
+	closure_handlers.get_gc = zend_closure_get_gc;
 }
 /* }}} */
 
Index: php5.4/Zend/zend_object_handlers.c
===================================================================
--- php5.4/Zend/zend_object_handlers.c	(revision 318599)
+++ php5.4/Zend/zend_object_handlers.c	(working copy)
@@ -102,6 +102,28 @@
 }
 /* }}} */
 
+ZEND_API HashTable *zend_std_get_gc(zval *object, zval ***table, int *n TSRMLS_DC) /* {{{ */
+{
+	if (Z_OBJ_HANDLER_P(object, get_properties) != zend_std_get_properties) {
+		*table = NULL;
+		*n = 0;
+		return Z_OBJ_HANDLER_P(object, get_properties)(object TSRMLS_CC);
+	} else {
+		zend_object *zobj = Z_OBJ_P(object);
+
+		if (zobj->properties) {
+			*table = NULL;
+			*n = 0;
+			return zobj->properties;
+		} else {
+			*table = zobj->properties_table;
+			*n = zobj->ce->default_properties_count;
+			return NULL;
+		}
+	}
+}
+/* }}} */
+
 ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
 {
 	*is_temp = 0;
@@ -1584,6 +1606,7 @@
 	NULL,									/* count_elements */
 	NULL,									/* get_debug_info */
 	zend_std_get_closure,					/* get_closure */
+	zend_std_get_gc,						/* get_gc */
 };
 
 /*
Index: php5.4/Zend/zend_object_handlers.h
===================================================================
--- php5.4/Zend/zend_object_handlers.h	(revision 318599)
+++ php5.4/Zend/zend_object_handlers.h	(working copy)
@@ -111,6 +111,8 @@
 
 typedef int (*zend_object_get_closure_t)(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC);
 
+typedef HashTable *(*zend_object_get_gc_t)(zval *object, zval ***table, int *n TSRMLS_DC);
+
 struct _zend_object_handlers {
 	/* general object functions */
 	zend_object_add_ref_t					add_ref;
@@ -139,6 +141,7 @@
 	zend_object_count_elements_t			count_elements;
 	zend_object_get_debug_info_t			get_debug_info;
 	zend_object_get_closure_t				get_closure;
+	zend_object_get_gc_t					get_gc;
 };
 
 extern ZEND_API zend_object_handlers std_object_handlers;
Index: php5.4/Zend/zend_gc.c
===================================================================
--- php5.4/Zend/zend_gc.c	(revision 318599)
+++ php5.4/Zend/zend_gc.c	(working copy)
@@ -194,7 +194,7 @@
 {
 	struct _store_object *obj;
 
-	if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_properties == NULL ||
+	if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_gc == NULL ||
 	    EG(objects_store).object_buckets == NULL)) {
 		return;
 	}
@@ -275,48 +275,38 @@
 	GC_ZVAL_SET_BLACK(pz);
 
 	if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
-		zend_object_get_properties_t get_props;
+		zend_object_get_gc_t get_gc;
 		struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
 
 		obj->refcount++;
 		if (GC_GET_COLOR(obj->buffered) != GC_BLACK) {
 			GC_SET_BLACK(obj->buffered);
 			if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
-			             (get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) {
-				if (get_props == zend_std_get_properties) {
-					zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object));
+			             (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+				int i, n;
+				zval **table;
+				HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
 
-					if (!zobj->properties) {
-						int i;
-						int n = zobj->ce->default_properties_count;
-
-						while (n > 0 && !zobj->properties_table[n-1]) n--;
-						for (i = 0; i < n; i++) {
-							if (zobj->properties_table[i]) {
-								pz = zobj->properties_table[i];
-								if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
-									pz->refcount__gc++;
-								}
-								if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
-									if (i == n - 1) {
-										goto tail_call;
-									} else {
-										zval_scan_black(pz TSRMLS_CC);
-									}
-								}
+				while (n > 0 && !table[n-1]) n--;
+				for (i = 0; i < n; i++) {
+					if (table[i]) {
+						pz = table[i];
+						if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+							pz->refcount__gc++;
+						}
+						if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
+							if (!props && i == n - 1) {
+								goto tail_call;
+							} else {
+								zval_scan_black(pz TSRMLS_CC);
 							}
 						}
-						return;
-					} else {
-						p = zobj->properties->pListHead;
 					}
-				} else {
-					HashTable *props = get_props(pz TSRMLS_CC);
-					if(!props) {
-						return;
-					}
-					p = props->pListHead;
 				}
+				if (!props) {
+					return;
+				}
+				p = props->pListHead;
 			}
 		}
 	} else if (Z_TYPE_P(pz) == IS_ARRAY) {
@@ -343,39 +333,30 @@
 static void zobj_scan_black(struct _store_object *obj, zval *pz TSRMLS_DC)
 {
 	Bucket *p;
-	zend_object_get_properties_t get_props;
+	zend_object_get_gc_t get_gc;
 
 	GC_SET_BLACK(obj->buffered);
 	if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
-	             (get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) {
-		if (get_props == zend_std_get_properties) {
-			zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object));
+	             (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+		int i, n;
+		zval **table;
+		HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
 
-			if (!zobj->properties) {
-				int i;
-
-				for (i = 0; i < zobj->ce->default_properties_count; i++) {
-					if (zobj->properties_table[i]) {
-						pz = zobj->properties_table[i];
-						if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
-							pz->refcount__gc++;
-						}
-						if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
-							zval_scan_black(pz TSRMLS_CC);
-						}
-                    }
+		for (i = 0; i < n; i++) {
+			if (table[i]) {
+				pz = table[i];
+				if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+					pz->refcount__gc++;
 				}
-				return;
-			} else {
-				p = zobj->properties->pListHead;
+				if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
+					zval_scan_black(pz TSRMLS_CC);
+				}
 			}
-		} else {
-			HashTable *props = get_props(pz TSRMLS_CC);
-			if(!props) {
-				return;
-			}
-			p = props->pListHead;
 		}
+		if (!props) {
+			return;
+		}
+		p = props->pListHead;
 		while (p != NULL) {
 			pz = *(zval**)p->pData;
 			if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
@@ -400,7 +381,7 @@
 		GC_ZVAL_SET_COLOR(pz, GC_GREY);
 
 		if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
-			zend_object_get_properties_t get_props;
+			zend_object_get_gc_t get_gc;
 			struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
 
 			obj->refcount--;
@@ -408,39 +389,29 @@
 				GC_BENCH_INC(zobj_marked_grey);
 				GC_SET_COLOR(obj->buffered, GC_GREY);
 				if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
-				             (get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) {
-					if (get_props == zend_std_get_properties) {
-						zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object));
+				             (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+					int i, n;
+					zval **table;
+					HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
 
-						if (!zobj->properties) {
-							int i;
-							int n = zobj->ce->default_properties_count;
-
-							while (n > 0 && !zobj->properties_table[n-1]) n--;
-							for (i = 0; i < n; i++) {
-								if (zobj->properties_table[i]) {
-									pz = zobj->properties_table[i];
-									if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
-										pz->refcount__gc--;
-									}
-									if (i == n - 1) {
-										goto tail_call;
-									} else {
-										zval_mark_grey(pz TSRMLS_CC);
-									}
-								}
+					while (n > 0 && !table[n-1]) n--;
+					for (i = 0; i < n; i++) {
+						if (table[i]) {
+							pz = table[i];
+							if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+								pz->refcount__gc--;
 							}
-							return;
-						} else {
-							p = zobj->properties->pListHead;
+							if (!props && i == n - 1) {
+								goto tail_call;
+							} else {
+								zval_mark_grey(pz TSRMLS_CC);
+							}
 						}
-					} else {
-						HashTable *props = get_props(pz TSRMLS_CC);
-						if(!props) {
-							return;
-						}
-						p = props->pListHead;
 					}
+					if (!props) {
+						return;
+					}
+					p = props->pListHead;
 				}
 			}
 		} else if (Z_TYPE_P(pz) == IS_ARRAY) {
@@ -468,39 +439,30 @@
 static void zobj_mark_grey(struct _store_object *obj, zval *pz TSRMLS_DC)
 {
 	Bucket *p;
-	zend_object_get_properties_t get_props;
+	zend_object_get_gc_t get_gc;
 
 	if (GC_GET_COLOR(obj->buffered) != GC_GREY) {
 		GC_BENCH_INC(zobj_marked_grey);
 		GC_SET_COLOR(obj->buffered, GC_GREY);
 		if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
-		             (get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) {
-			if (get_props == zend_std_get_properties) {
-				zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object));
+		             (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+			int i, n;
+			zval **table;
+			HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
 
-				if (!zobj->properties) {
-					int i;
-
-					for (i = 0; i < zobj->ce->default_properties_count; i++) {
-						if (zobj->properties_table[i]) {
-							pz = zobj->properties_table[i];
-							if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
-								pz->refcount__gc--;
-							}
-							zval_mark_grey(pz TSRMLS_CC);
-    	                }
+			for (i = 0; i < n; i++) {
+				if (table[i]) {
+					pz = table[i];
+					if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+						pz->refcount__gc--;
 					}
-					return;
-				} else {
-					p = zobj->properties->pListHead;
+					zval_mark_grey(pz TSRMLS_CC);
 				}
-			} else {
-				HashTable *props = get_props(pz TSRMLS_CC);
-				if(!props) {
-					return;
-				}
-				p = props->pListHead;
 			}
+			if (!props) {
+				return;
+			}
+			p = props->pListHead;
 			while (p != NULL) {
 				pz = *(zval**)p->pData;
 				if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
@@ -558,7 +520,7 @@
 		} else {
 			GC_ZVAL_SET_COLOR(pz, GC_WHITE);
 			if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
-				zend_object_get_properties_t get_props;
+				zend_object_get_gc_t get_gc;
 				struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
 
 				if (GC_GET_COLOR(obj->buffered) == GC_GREY) {
@@ -567,36 +529,26 @@
 					} else {
 						GC_SET_COLOR(obj->buffered, GC_WHITE);
 						if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
-						             (get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) {
-							if (get_props == zend_std_get_properties) {
-								zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object));
+						             (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+							int i, n;
+							zval **table;
+							HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
 
-								if (!zobj->properties) {
-									int i;
-									int n = zobj->ce->default_properties_count;
-
-									while (n > 0 && !zobj->properties_table[n-1]) n--;
-									for (i = 0; i < n; i++) {
-										if (zobj->properties_table[i]) {
-											pz = zobj->properties_table[i];
-											if (i == n - 1) {
-												goto tail_call;
-											} else {
-												zval_scan(pz TSRMLS_CC);
-											}
-										}
+							while (n > 0 && !table[n-1]) n--;
+							for (i = 0; i < n; i++) {
+								if (table[i]) {
+									pz = table[i];
+									if (!props && i == n - 1) {
+										goto tail_call;
+									} else {
+										zval_scan(pz TSRMLS_CC);
 									}
-									return;
-								} else {
-									p = zobj->properties->pListHead;
 								}
-							} else {
-								HashTable *props = get_props(pz TSRMLS_CC);
-								if(!props) {
-									return;
-								}
-								p = props->pListHead;
 							}
+							if (!props) {
+								return;
+							}
+							p = props->pListHead;
 						}
 					}
 				}
@@ -623,7 +575,7 @@
 static void zobj_scan(zval *pz TSRMLS_DC)
 {
 	Bucket *p;
-	zend_object_get_properties_t get_props;
+	zend_object_get_gc_t get_gc;
 
 	if (EG(objects_store).object_buckets) {
 		struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
@@ -634,30 +586,21 @@
 			} else {
 				GC_SET_COLOR(obj->buffered, GC_WHITE);
 				if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
-				             (get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) {
-					if (get_props == zend_std_get_properties) {
-						zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object));
+				             (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+					int i, n;
+					zval **table;
+					HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
 
-						if (!zobj->properties) {
-							int i;
-
-							for (i = 0; i < zobj->ce->default_properties_count; i++) {
-								if (zobj->properties_table[i]) {
-									pz = zobj->properties_table[i];
-									zval_scan(pz TSRMLS_CC);
-		                    	}
-							}
-							return;
-						} else {
-							p = zobj->properties->pListHead;
-						}
-					} else {
-						HashTable *props = get_props(pz TSRMLS_CC);
-						if(!props) {
-							return;
-						}
-						p = props->pListHead;
+					for (i = 0; i < n; i++) {
+						if (table[i]) {
+							pz = table[i];
+							zval_scan(pz TSRMLS_CC);
+                    	}
 					}
+					if (!props) {
+						return;
+					}
+					p = props->pListHead;
 					while (p != NULL) {
 						zval_scan(*(zval**)p->pData TSRMLS_CC);
 						p = p->pListNext;
@@ -697,52 +640,44 @@
 		GC_ZVAL_SET_BLACK(pz);
 
 		if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
-			zend_object_get_properties_t get_props;
+			zend_object_get_gc_t get_gc;
 			struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
 
 			if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
 				GC_SET_BLACK(obj->buffered);
 
 				if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
-				             (get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) {
-					if (get_props == zend_std_get_properties) {
-						zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object));
+				             (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+					int i, n;
+					zval **table, *zv;
+					HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
 
-						if (!zobj->properties) {
-							int i;
-							int n = zobj->ce->default_properties_count;
+					if (!props) {
+						/* restore refcount and put into list to free */
+						pz->refcount__gc++;
+						((zval_gc_info*)pz)->u.next = GC_G(zval_to_free);
+						GC_G(zval_to_free) = (zval_gc_info*)pz;
+					}
 
-							while (n > 0 && !zobj->properties_table[n-1]) n--;
-
-							/* restore refcount and put into list to free */
-							pz->refcount__gc++;
-							((zval_gc_info*)pz)->u.next = GC_G(zval_to_free);
-							GC_G(zval_to_free) = (zval_gc_info*)pz;
-
-							for (i = 0; i < n; i++) {
-								if (zobj->properties_table[i]) {
-									pz = zobj->properties_table[i];
-									if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
-										pz->refcount__gc++;
-									}
-									if (i == n - 1) {
-										goto tail_call;
-									} else {
-										zval_collect_white(pz TSRMLS_CC);
-									}
-								}
+					while (n > 0 && !table[n-1]) n--;
+					for (i = 0; i < n; i++) {
+						if (table[i]) {
+							zv = table[i];
+							if (Z_TYPE_P(zv) != IS_ARRAY || Z_ARRVAL_P(zv) != &EG(symbol_table)) {
+								zv->refcount__gc++;
 							}
-							return;
-						} else {
-							p = zobj->properties->pListHead;
+							if (!props && i == n - 1) {
+								pz = zv;
+								goto tail_call;
+							} else {
+								zval_collect_white(zv TSRMLS_CC);
+							}
 						}
-					} else {
-						HashTable *props = get_props(pz TSRMLS_CC);
-						if(!props) {
-							return;
-						}
-						p = props->pListHead;
 					}
+					if (!props) {
+						return;
+					}
+					p = props->pListHead;
 				}
 			}
 		} else {
@@ -776,40 +711,31 @@
 	Bucket *p;
 
 	if (EG(objects_store).object_buckets) {
-		zend_object_get_properties_t get_props;
+		zend_object_get_gc_t get_gc;
 		struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
 
 		if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
 			GC_SET_BLACK(obj->buffered);
 
 			if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
-			             (get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) {
-				if (get_props == zend_std_get_properties) {
-					zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object));
+			             (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+				int i, n;
+				zval **table;
+				HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
 
-					if (!zobj->properties) {
-						int i;
-
-						for (i = 0; i < zobj->ce->default_properties_count; i++) {
-							if (zobj->properties_table[i]) {
-								pz = zobj->properties_table[i];
-								if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
-									pz->refcount__gc++;
-								}
-								zval_collect_white(pz TSRMLS_CC);
-							}
+				for (i = 0; i < n; i++) {
+					if (table[i]) {
+						pz = table[i];
+						if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+							pz->refcount__gc++;
 						}
-						return;
-					} else {
-						p = zobj->properties->pListHead;
+						zval_collect_white(pz TSRMLS_CC);
 					}
-				} else {
-					HashTable *props = get_props(pz TSRMLS_CC);
-					if(!props) {
-						return;
-					}
-					p = props->pListHead;
 				}
+				if (!props) {
+					return;
+				}
+				p = props->pListHead;
 				while (p != NULL) {
 					pz = *(zval**)p->pData;
 					if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC