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-closure.diff for Performance problem Bug #60139

Patch version 2011-10-31 11:04 UTC

Return to Bug #60139 | Download this patch
This patch renders other patches obsolete

Obsolete patches:

Patch Revisions:

Developer: dmitry@php.net

Index: php5.3/Zend/zend_gc.c
===================================================================
--- php5.3/Zend/zend_gc.c	(revision 318599)
+++ php5.3/Zend/zend_gc.c	(working copy)
@@ -21,6 +21,7 @@
 
 #include "zend.h"
 #include "zend_API.h"
+#include "zend_closures.h"
 
 #define GC_ROOT_BUFFER_MAX_ENTRIES 10000
 
@@ -282,11 +283,20 @@
 			GC_SET_BLACK(obj->buffered);
 			if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
 			             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-				HashTable *props = Z_OBJPROP_P(pz);
-				if(!props) {
-					return;
+				if (Z_OBJCE_P(pz) == zend_ce_closure) {
+					const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+					if (func->type != ZEND_USER_FUNCTION || !func->op_array.static_variables) {
+						return;
+					}
+					p = func->op_array.static_variables->pListHead;
+				} else {
+					HashTable *props = Z_OBJPROP_P(pz);
+					if(!props) {
+						return;
+					}
+					p = props->pListHead;
 				}
-				p = props->pListHead;
 			}
 		}
 	} else if (Z_TYPE_P(pz) == IS_ARRAY) {
@@ -317,11 +327,20 @@
 	GC_SET_BLACK(obj->buffered);
 	if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
 	             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-		HashTable *props = Z_OBJPROP_P(pz);
-		if(!props) {
-			return;
+		if (Z_OBJCE_P(pz) == zend_ce_closure) {
+			const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+			if (func->type != ZEND_USER_FUNCTION || !func->op_array.static_variables) {
+				return;
+			}
+			p = func->op_array.static_variables->pListHead;
+		} else {
+			HashTable *props = Z_OBJPROP_P(pz);
+			if(!props) {
+				return;
+			}
+			p = props->pListHead;
 		}
-		p = props->pListHead;
 		while (p != NULL) {
 			pz = *(zval**)p->pData;
 			if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
@@ -354,11 +373,20 @@
 				GC_SET_COLOR(obj->buffered, GC_GREY);
 				if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
 				             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-					HashTable *props = Z_OBJPROP_P(pz);
-					if(!props) {
-						return;
+					if (Z_OBJCE_P(pz) == zend_ce_closure) {
+						const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+						if (func->type != ZEND_USER_FUNCTION || !func->op_array.static_variables) {
+							return;
+						}
+						p = func->op_array.static_variables->pListHead;
+					} else {
+						HashTable *props = Z_OBJPROP_P(pz);
+						if(!props) {
+							return;
+						}
+						p = props->pListHead;
 					}
-					p = props->pListHead;
 				}
 			}
 		} else if (Z_TYPE_P(pz) == IS_ARRAY) {
@@ -392,11 +420,20 @@
 		GC_SET_COLOR(obj->buffered, GC_GREY);
 		if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
 		             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-			HashTable *props = Z_OBJPROP_P(pz);
-			if(!props) {
-				return;
+			if (Z_OBJCE_P(pz) == zend_ce_closure) {
+				const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+				if (func->type != ZEND_USER_FUNCTION || !func->op_array.static_variables) {
+					return;
+				}
+				p = func->op_array.static_variables->pListHead;
+			} else {
+				HashTable *props = Z_OBJPROP_P(pz);
+				if(!props) {
+					return;
+				}
+				p = props->pListHead;
 			}
-			p = props->pListHead;
 			while (p != NULL) {
 				pz = *(zval**)p->pData;
 				if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
@@ -463,11 +500,20 @@
 						GC_SET_COLOR(obj->buffered, GC_WHITE);
 						if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
 						             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-							HashTable *props = Z_OBJPROP_P(pz);
-							if(!props) {
-								return 0;
+							if (Z_OBJCE_P(pz) == zend_ce_closure) {
+								const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+								if (func->type != ZEND_USER_FUNCTION || !func->op_array.static_variables) {
+									return 0;
+								}
+								p = func->op_array.static_variables->pListHead;
+							} else {
+								HashTable *props = Z_OBJPROP_P(pz);
+								if(!props) {
+									return 0;
+								}
+								p = props->pListHead;
 							}
-							p = props->pListHead;
 						}
 					}
 				}
@@ -506,11 +552,20 @@
 				GC_SET_COLOR(obj->buffered, GC_WHITE);
 				if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
 				             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-					HashTable *props = Z_OBJPROP_P(pz);
-					if(!props) {
-						return;
+					if (Z_OBJCE_P(pz) == zend_ce_closure) {
+						const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+						if (func->type != ZEND_USER_FUNCTION || !func->op_array.static_variables) {
+							return;
+						}
+						p = func->op_array.static_variables->pListHead;
+					} else {
+						HashTable *props = Z_OBJPROP_P(pz);
+						if(!props) {
+							return;
+						}
+						p = props->pListHead;
 					}
-					p = props->pListHead;
 					while (p != NULL) {
 						zval_scan(*(zval**)p->pData TSRMLS_CC);
 						p = p->pListNext;
@@ -557,11 +612,20 @@
 
 				if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
 				             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-					HashTable *props = Z_OBJPROP_P(pz);
-					if(!props) {
-						return;
+					if (Z_OBJCE_P(pz) == zend_ce_closure) {
+						const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+						if (func->type != ZEND_USER_FUNCTION || !func->op_array.static_variables) {
+							return;
+						}
+						p = func->op_array.static_variables->pListHead;
+					} else {
+						HashTable *props = Z_OBJPROP_P(pz);
+						if(!props) {
+							return;
+						}
+						p = props->pListHead;
 					}
-					p = props->pListHead;
 				}
 			}
 		} else {
@@ -602,11 +666,20 @@
 
 			if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
 			             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-				HashTable *props = Z_OBJPROP_P(pz);
-				if(!props) {
-					return;
+				if (Z_OBJCE_P(pz) == zend_ce_closure) {
+					const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+					if (func->type != ZEND_USER_FUNCTION || !func->op_array.static_variables) {
+						return;
+					}
+					p = func->op_array.static_variables->pListHead;
+				} else {
+					HashTable *props = Z_OBJPROP_P(pz);
+					if(!props) {
+						return;
+					}
+					p = props->pListHead;
 				}
-				p = props->pListHead;
 				while (p != NULL) {
 					pz = *(zval**)p->pData;
 					if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
Index: php5.4/Zend/zend_gc.c
===================================================================
--- php5.4/Zend/zend_gc.c	(revision 318599)
+++ php5.4/Zend/zend_gc.c	(working copy)
@@ -21,6 +21,7 @@
 
 #include "zend.h"
 #include "zend_API.h"
+#include "zend_closures.h"
 
 #define GC_ROOT_BUFFER_MAX_ENTRIES 10000
 
@@ -286,7 +287,20 @@
 				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));
 
-					if (!zobj->properties) {
+					if (zobj->ce == zend_ce_closure) {
+						const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+						pz = zend_get_closure_this_ptr(pz TSRMLS_CC);
+						if (pz) {
+							pz->refcount__gc++;
+							if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
+								zval_scan_black(pz TSRMLS_CC);
+							}
+						}
+						if (func->type == ZEND_USER_FUNCTION && func->op_array.static_variables) {
+							p = func->op_array.static_variables->pListHead;
+						}
+					} else if (!zobj->properties) {
 						int i;
 						int n = zobj->ce->default_properties_count;
 
@@ -351,7 +365,20 @@
 		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));
 
-			if (!zobj->properties) {
+			if (zobj->ce == zend_ce_closure) {
+				const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+				pz = zend_get_closure_this_ptr(pz TSRMLS_CC);
+				if (pz) {
+					pz->refcount__gc++;
+					if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
+						zval_scan_black(pz TSRMLS_CC);
+					}
+				}
+				if (func->type == ZEND_USER_FUNCTION && func->op_array.static_variables) {
+					p = func->op_array.static_variables->pListHead;
+				}
+			} else if (!zobj->properties) {
 				int i;
 
 				for (i = 0; i < zobj->ce->default_properties_count; i++) {
@@ -412,7 +439,18 @@
 					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));
 
-						if (!zobj->properties) {
+						if (zobj->ce == zend_ce_closure) {
+							const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+							pz = zend_get_closure_this_ptr(pz TSRMLS_CC);
+							if (pz) {
+								pz->refcount__gc--;
+								zval_mark_grey(pz TSRMLS_CC);
+							}
+							if (func->type == ZEND_USER_FUNCTION && func->op_array.static_variables) {
+								p = func->op_array.static_variables->pListHead;
+							}
+						} else if (!zobj->properties) {
 							int i;
 							int n = zobj->ce->default_properties_count;
 
@@ -478,7 +516,18 @@
 			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));
 
-				if (!zobj->properties) {
+				if (zobj->ce == zend_ce_closure) {
+					const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+					pz = zend_get_closure_this_ptr(pz TSRMLS_CC);
+					if (pz) {
+						pz->refcount__gc--;
+						zval_mark_grey(pz TSRMLS_CC);
+					}
+					if (func->type == ZEND_USER_FUNCTION && func->op_array.static_variables) {
+						p = func->op_array.static_variables->pListHead;
+					}
+				} else if (!zobj->properties) {
 					int i;
 
 					for (i = 0; i < zobj->ce->default_properties_count; i++) {
@@ -571,7 +620,17 @@
 							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));
 
-								if (!zobj->properties) {
+								if (zobj->ce == zend_ce_closure) {
+									const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+									pz = zend_get_closure_this_ptr(pz TSRMLS_CC);
+									if (pz) {
+										zval_scan(pz TSRMLS_CC);
+									}
+									if (func->type == ZEND_USER_FUNCTION && func->op_array.static_variables) {
+										p = func->op_array.static_variables->pListHead;
+									}
+								} else if (!zobj->properties) {
 									int i;
 									int n = zobj->ce->default_properties_count;
 
@@ -638,7 +697,17 @@
 					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));
 
-						if (!zobj->properties) {
+						if (zobj->ce == zend_ce_closure) {
+							const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+							pz = zend_get_closure_this_ptr(pz TSRMLS_CC);
+							if (pz) {
+								zval_scan(pz TSRMLS_CC);
+							}
+							if (func->type == ZEND_USER_FUNCTION && func->op_array.static_variables) {
+								p = func->op_array.static_variables->pListHead;
+							}
+						} else if (!zobj->properties) {
 							int i;
 
 							for (i = 0; i < zobj->ce->default_properties_count; i++) {
@@ -708,7 +777,19 @@
 					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));
 
-						if (!zobj->properties) {
+						if (zobj->ce == zend_ce_closure) {
+							const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+							zval *zv;
+
+							zv = zend_get_closure_this_ptr(pz TSRMLS_CC);
+							if (zv) {
+								zv->refcount__gc++;
+								zval_collect_white(zv TSRMLS_CC);
+							}
+							if (func->type == ZEND_USER_FUNCTION && func->op_array.static_variables) {
+								p = func->op_array.static_variables->pListHead;
+							}
+						} else if (!zobj->properties) {
 							int i;
 							int n = zobj->ce->default_properties_count;
 
@@ -787,7 +868,18 @@
 				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));
 
-					if (!zobj->properties) {
+					if (zobj->ce == zend_ce_closure) {
+						const zend_function *func = zend_get_closure_method_def(pz TSRMLS_CC);
+
+						pz = zend_get_closure_this_ptr(pz TSRMLS_CC);
+						if (pz) {
+							pz->refcount__gc++;
+							zval_collect_white(pz TSRMLS_CC);
+						}
+						if (func->type == ZEND_USER_FUNCTION && func->op_array.static_variables) {
+							p = func->op_array.static_variables->pListHead;
+						}
+					} else if (!zobj->properties) {
 						int i;
 
 						for (i = 0; i < zobj->ce->default_properties_count; i++) {
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 05:03:19 2014 UTC