--- embedaddon/php/Zend/zend_gc.c 2012/02/21 23:47:52 1.1.1.1 +++ embedaddon/php/Zend/zend_gc.c 2014/06/15 20:04:03 1.1.1.4 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_gc.c,v 1.1.1.1 2012/02/21 23:47:52 misho Exp $ */ +/* $Id: zend_gc.c,v 1.1.1.4 2014/06/15 20:04:03 misho Exp $ */ #include "zend.h" #include "zend_API.h" @@ -194,7 +194,7 @@ ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC { 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,15 +275,35 @@ tail_call: GC_ZVAL_SET_BLACK(pz); if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { + 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 && - Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { - HashTable *props = Z_OBJPROP_P(pz); - if(!props) { + (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { + int i, n; + zval **table; + HashTable *props = get_gc(pz, &table, &n 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); + } + } + } + } + if (!props) { return; } p = props->pListHead; @@ -313,12 +333,27 @@ tail_call: static void zobj_scan_black(struct _store_object *obj, zval *pz TSRMLS_DC) { Bucket *p; + 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 && - Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { - HashTable *props = Z_OBJPROP_P(pz); - if(!props) { + (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { + int i, n; + zval **table; + HashTable *props = get_gc(pz, &table, &n 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++; + } + if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) { + zval_scan_black(pz TSRMLS_CC); + } + } + } + if (!props) { return; } p = props->pListHead; @@ -346,6 +381,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_gc_t get_gc; struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj; obj->refcount--; @@ -353,9 +389,26 @@ 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) { + (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { + int i, n; + zval **table; + HashTable *props = get_gc(pz, &table, &n 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 (!props && i == n - 1) { + goto tail_call; + } else { + zval_mark_grey(pz TSRMLS_CC); + } + } + } + if (!props) { return; } p = props->pListHead; @@ -386,14 +439,27 @@ tail_call: static void zobj_mark_grey(struct _store_object *obj, zval *pz TSRMLS_DC) { Bucket *p; + 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 && - Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { - HashTable *props = Z_OBJPROP_P(pz); - if(!props) { + (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { + int i, n; + zval **table; + HashTable *props = get_gc(pz, &table, &n 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--; + } + zval_mark_grey(pz TSRMLS_CC); + } + } + if (!props) { return; } p = props->pListHead; @@ -442,7 +508,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 +520,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_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) { @@ -462,11 +529,25 @@ 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_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { + int i, n; + zval **table; + HashTable *props = get_gc(pz, &table, &n 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); + } + } } + if (!props) { + return; + } p = props->pListHead; } } @@ -489,12 +570,12 @@ tail_call: p = p->pListNext; } } - return 0; } static void zobj_scan(zval *pz TSRMLS_DC) { Bucket *p; + 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; @@ -505,9 +586,18 @@ 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) { + (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { + int i, n; + zval **table; + HashTable *props = get_gc(pz, &table, &n TSRMLS_CC); + + for (i = 0; i < n; i++) { + if (table[i]) { + pz = table[i]; + zval_scan(pz TSRMLS_CC); + } + } + if (!props) { return; } p = props->pListHead; @@ -550,15 +640,42 @@ tail_call: GC_ZVAL_SET_BLACK(pz); if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { + 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); + /* PURPLE instead of BLACK to prevent buffering in nested gc calls */ + GC_SET_PURPLE(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) { + (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 (!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 && !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++; + } + if (!props && i == n - 1) { + pz = zv; + goto tail_call; + } else { + zval_collect_white(zv TSRMLS_CC); + } + } + } + if (!props) { return; } p = props->pListHead; @@ -595,15 +712,29 @@ static void zobj_collect_white(zval *pz TSRMLS_DC) Bucket *p; if (EG(objects_store).object_buckets) { + 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); + /* PURPLE instead of BLACK to prevent buffering in nested gc calls */ + GC_SET_PURPLE(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) { + (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { + int i, n; + zval **table; + HashTable *props = get_gc(pz, &table, &n 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++; + } + zval_collect_white(pz TSRMLS_CC); + } + } + if (!props) { return; } p = props->pListHead;