dmitry                                   Fri, 15 Apr 2011 09:57:43 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=310232

Log:
Improved GC to avaid reconstruction of HashTables for object properties

Changed paths:
    U   php/php-src/trunk/Zend/zend_gc.c

Modified: php/php-src/trunk/Zend/zend_gc.c
===================================================================
--- php/php-src/trunk/Zend/zend_gc.c	2011-04-15 09:09:37 UTC (rev 310231)
+++ php/php-src/trunk/Zend/zend_gc.c	2011-04-15 09:57:43 UTC (rev 310232)
@@ -275,18 +275,48 @@
 	GC_ZVAL_SET_BLACK(pz);

 	if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+		zend_object_get_properties_t get_props;
 		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 &&
-			             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-				HashTable *props = Z_OBJPROP_P(pz);
-				if(!props) {
-					return;
+			             (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));
+
+					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);
+									}
+								}
+							}
+						}
+						return;
+					} else {
+						p = zobj->properties->pListHead;
+					}
+				} else {
+					HashTable *props = get_props(pz);
+					if(!props) {
+						return;
+					}
+					p = props->pListHead;
 				}
-				p = props->pListHead;
 			}
 		}
 	} else if (Z_TYPE_P(pz) == IS_ARRAY) {
@@ -313,15 +343,39 @@
 static void zobj_scan_black(struct _store_object *obj, zval *pz TSRMLS_DC)
 {
 	Bucket *p;
+	zend_object_get_properties_t get_props;

 	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;
+	             (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));
+
+			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);
+						}
+                    }
+				}
+				return;
+			} else {
+				p = zobj->properties->pListHead;
+			}
+		} else {
+			HashTable *props = get_props(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)) {
@@ -346,6 +400,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;
 			struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;

 			obj->refcount--;
@@ -353,12 +408,39 @@
 				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 &&
-				             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-					HashTable *props = Z_OBJPROP_P(pz);
-					if(!props) {
-						return;
+				             (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));
+
+						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);
+									}
+								}
+							}
+							return;
+						} else {
+							p = zobj->properties->pListHead;
+						}
+					} else {
+						HashTable *props = get_props(pz);
+						if(!props) {
+							return;
+						}
+						p = props->pListHead;
 					}
-					p = props->pListHead;
 				}
 			}
 		} else if (Z_TYPE_P(pz) == IS_ARRAY) {
@@ -386,17 +468,39 @@
 static void zobj_mark_grey(struct _store_object *obj, zval *pz TSRMLS_DC)
 {
 	Bucket *p;
+	zend_object_get_properties_t get_props;

 	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 &&
-		             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-			HashTable *props = Z_OBJPROP_P(pz);
-			if(!props) {
-				return;
+		             (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));
+
+				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);
+    	                }
+					}
+					return;
+				} else {
+					p = zobj->properties->pListHead;
+				}
+			} else {
+				HashTable *props = get_props(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)) {
@@ -442,7 +546,7 @@
 	}
 }

-static int zval_scan(zval *pz TSRMLS_DC)
+static void zval_scan(zval *pz TSRMLS_DC)
 {
 	Bucket *p;

@@ -454,6 +558,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;
 				struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;

 				if (GC_GET_COLOR(obj->buffered) == GC_GREY) {
@@ -462,12 +567,36 @@
 					} else {
 						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;
+						             (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));
+
+								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);
+											}
+										}
+									}
+									return;
+								} else {
+									p = zobj->properties->pListHead;
+								}
+							} else {
+								HashTable *props = get_props(pz);
+								if(!props) {
+									return;
+								}
+								p = props->pListHead;
 							}
-							p = props->pListHead;
 						}
 					}
 				}
@@ -489,12 +618,12 @@
 			p = p->pListNext;
 		}
 	}
-	return 0;
 }

 static void zobj_scan(zval *pz TSRMLS_DC)
 {
 	Bucket *p;
+	zend_object_get_properties_t get_props;

 	if (EG(objects_store).object_buckets) {
 		struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
@@ -505,12 +634,30 @@
 			} else {
 				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;
+				             (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));
+
+						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);
+						if(!props) {
+							return;
+						}
+						p = props->pListHead;
 					}
-					p = props->pListHead;
 					while (p != NULL) {
 						zval_scan(*(zval**)p->pData TSRMLS_CC);
 						p = p->pListNext;
@@ -550,18 +697,52 @@
 		GC_ZVAL_SET_BLACK(pz);

 		if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+			zend_object_get_properties_t get_props;
 			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 &&
-				             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-					HashTable *props = Z_OBJPROP_P(pz);
-					if(!props) {
-						return;
+				             (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));
+
+						if (!zobj->properties) {
+							int i;
+							int n = zobj->ce->default_properties_count;
+
+							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);
+									}
+								}
+							}
+							return;
+						} else {
+							p = zobj->properties->pListHead;
+						}
+					} else {
+						HashTable *props = get_props(pz);
+						if(!props) {
+							return;
+						}
+						p = props->pListHead;
 					}
-					p = props->pListHead;
 				}
 			}
 		} else {
@@ -595,18 +776,40 @@
 	Bucket *p;

 	if (EG(objects_store).object_buckets) {
+		zend_object_get_properties_t get_props;
 		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 &&
-			             Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
-				HashTable *props = Z_OBJPROP_P(pz);
-				if(!props) {
-					return;
+			             (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));
+
+					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);
+							}
+						}
+						return;
+					} else {
+						p = zobj->properties->pListHead;
+					}
+				} else {
+					HashTable *props = get_props(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)) {
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to