From: Dmitry Stogov Date: Fri, 15 Apr 2011 09:57:43 +0000 (+0000) Subject: Improved GC to avaid reconstruction of HashTables for object properties X-Git-Tag: php-5.4.0alpha1~191^2~68 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e6235434524dc1062a0cd856c2be47ca3a5b376a;p=php Improved GC to avaid reconstruction of HashTables for object properties --- diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 66a1c74651..9de471286d 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -275,18 +275,48 @@ tail_call: 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 @@ tail_call: 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 @@ tail_call: 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 @@ tail_call: 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 @@ tail_call: 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 void gc_mark_roots(TSRMLS_D) } } -static int zval_scan(zval *pz TSRMLS_DC) +static void zval_scan(zval *pz TSRMLS_DC) { Bucket *p; @@ -454,6 +558,7 @@ tail_call: } 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 @@ tail_call: } 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 @@ tail_call: 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 @@ static void zobj_scan(zval *pz TSRMLS_DC) } 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 @@ tail_call: 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 @@ static void zobj_collect_white(zval *pz TSRMLS_DC) 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)) {