|
version 1.1.1.1, 2012/02/21 23:47:52
|
version 1.1.1.4, 2014/06/15 20:04:03
|
|
Line 2
|
Line 2
|
| +----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| | Zend Engine | |
| 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, | |
| 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 | |
| that is bundled with this package in the file LICENSE, and is | |
|
Line 194 ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC
|
Line 194 ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC
|
| { |
{ |
| struct _store_object *obj; |
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)) { |
EG(objects_store).object_buckets == NULL)) { |
| return; |
return; |
| } |
} |
|
Line 275 tail_call:
|
Line 275 tail_call:
|
| GC_ZVAL_SET_BLACK(pz); |
GC_ZVAL_SET_BLACK(pz); |
| |
|
| if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { |
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; |
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj; |
| |
|
| obj->refcount++; |
obj->refcount++; |
| if (GC_GET_COLOR(obj->buffered) != GC_BLACK) { |
if (GC_GET_COLOR(obj->buffered) != GC_BLACK) { |
| GC_SET_BLACK(obj->buffered); |
GC_SET_BLACK(obj->buffered); |
| if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
| Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { | (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { |
| HashTable *props = Z_OBJPROP_P(pz); | int i, n; |
| if(!props) { | 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; |
return; |
| } |
} |
| p = props->pListHead; |
p = props->pListHead; |
|
Line 313 tail_call:
|
Line 333 tail_call:
|
| static void zobj_scan_black(struct _store_object *obj, zval *pz TSRMLS_DC) |
static void zobj_scan_black(struct _store_object *obj, zval *pz TSRMLS_DC) |
| { |
{ |
| Bucket *p; |
Bucket *p; |
| |
zend_object_get_gc_t get_gc; |
| |
|
| GC_SET_BLACK(obj->buffered); |
GC_SET_BLACK(obj->buffered); |
| if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
| Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { | (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { |
| HashTable *props = Z_OBJPROP_P(pz); | int i, n; |
| if(!props) { | 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; |
return; |
| } |
} |
| p = props->pListHead; |
p = props->pListHead; |
|
Line 346 tail_call:
|
Line 381 tail_call:
|
| GC_ZVAL_SET_COLOR(pz, GC_GREY); |
GC_ZVAL_SET_COLOR(pz, GC_GREY); |
| |
|
| if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { |
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; |
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj; |
| |
|
| obj->refcount--; |
obj->refcount--; |
|
Line 353 tail_call:
|
Line 389 tail_call:
|
| GC_BENCH_INC(zobj_marked_grey); |
GC_BENCH_INC(zobj_marked_grey); |
| GC_SET_COLOR(obj->buffered, GC_GREY); |
GC_SET_COLOR(obj->buffered, GC_GREY); |
| if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
| Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { | (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { |
| HashTable *props = Z_OBJPROP_P(pz); | int i, n; |
| if(!props) { | 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; |
return; |
| } |
} |
| p = props->pListHead; |
p = props->pListHead; |
|
Line 386 tail_call:
|
Line 439 tail_call:
|
| static void zobj_mark_grey(struct _store_object *obj, zval *pz TSRMLS_DC) |
static void zobj_mark_grey(struct _store_object *obj, zval *pz TSRMLS_DC) |
| { |
{ |
| Bucket *p; |
Bucket *p; |
| |
zend_object_get_gc_t get_gc; |
| |
|
| if (GC_GET_COLOR(obj->buffered) != GC_GREY) { |
if (GC_GET_COLOR(obj->buffered) != GC_GREY) { |
| GC_BENCH_INC(zobj_marked_grey); |
GC_BENCH_INC(zobj_marked_grey); |
| GC_SET_COLOR(obj->buffered, GC_GREY); |
GC_SET_COLOR(obj->buffered, GC_GREY); |
| if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
| Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { | (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { |
| HashTable *props = Z_OBJPROP_P(pz); | int i, n; |
| if(!props) { | 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; |
return; |
| } |
} |
| p = props->pListHead; |
p = props->pListHead; |
|
Line 442 static void gc_mark_roots(TSRMLS_D)
|
Line 508 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; |
Bucket *p; |
| |
|
|
Line 454 tail_call:
|
Line 520 tail_call:
|
| } else { |
} else { |
| GC_ZVAL_SET_COLOR(pz, GC_WHITE); |
GC_ZVAL_SET_COLOR(pz, GC_WHITE); |
| if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { |
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; |
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj; |
| |
|
| if (GC_GET_COLOR(obj->buffered) == GC_GREY) { |
if (GC_GET_COLOR(obj->buffered) == GC_GREY) { |
|
Line 462 tail_call:
|
Line 529 tail_call:
|
| } else { |
} else { |
| GC_SET_COLOR(obj->buffered, GC_WHITE); |
GC_SET_COLOR(obj->buffered, GC_WHITE); |
| if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
| Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { | (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { |
| HashTable *props = Z_OBJPROP_P(pz); | int i, n; |
| if(!props) { | zval **table; |
| return 0; | 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; |
p = props->pListHead; |
| } |
} |
| } |
} |
|
Line 489 tail_call:
|
Line 570 tail_call:
|
| p = p->pListNext; |
p = p->pListNext; |
| } |
} |
| } |
} |
| return 0; |
|
| } |
} |
| |
|
| static void zobj_scan(zval *pz TSRMLS_DC) |
static void zobj_scan(zval *pz TSRMLS_DC) |
| { |
{ |
| Bucket *p; |
Bucket *p; |
| |
zend_object_get_gc_t get_gc; |
| |
|
| if (EG(objects_store).object_buckets) { |
if (EG(objects_store).object_buckets) { |
| struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj; |
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj; |
|
Line 505 static void zobj_scan(zval *pz TSRMLS_DC)
|
Line 586 static void zobj_scan(zval *pz TSRMLS_DC)
|
| } else { |
} else { |
| GC_SET_COLOR(obj->buffered, GC_WHITE); |
GC_SET_COLOR(obj->buffered, GC_WHITE); |
| if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
| Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { | (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { |
| HashTable *props = Z_OBJPROP_P(pz); | int i, n; |
| if(!props) { | 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; |
return; |
| } |
} |
| p = props->pListHead; |
p = props->pListHead; |
|
Line 550 tail_call:
|
Line 640 tail_call:
|
| GC_ZVAL_SET_BLACK(pz); |
GC_ZVAL_SET_BLACK(pz); |
| |
|
| if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { |
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; |
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj; |
| |
|
| if (obj->buffered == (gc_root_buffer*)GC_WHITE) { |
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 && |
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
| Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { | (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { |
| HashTable *props = Z_OBJPROP_P(pz); | int i, n; |
| if(!props) { | 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; |
return; |
| } |
} |
| p = props->pListHead; |
p = props->pListHead; |
|
Line 595 static void zobj_collect_white(zval *pz TSRMLS_DC)
|
Line 712 static void zobj_collect_white(zval *pz TSRMLS_DC)
|
| Bucket *p; |
Bucket *p; |
| |
|
| if (EG(objects_store).object_buckets) { |
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; |
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj; |
| |
|
| if (obj->buffered == (gc_root_buffer*)GC_WHITE) { |
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 && |
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
| Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) { | (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) { |
| HashTable *props = Z_OBJPROP_P(pz); | int i, n; |
| if(!props) { | 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; |
return; |
| } |
} |
| p = props->pListHead; |
p = props->pListHead; |