summaryrefslogtreecommitdiff
path: root/Zend/zend_gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_gc.c')
-rw-r--r--Zend/zend_gc.c187
1 files changed, 158 insertions, 29 deletions
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index dd64fefa1d..e877eab75d 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
+ | Copyright (c) 1998-2012 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 |
@@ -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,10 +529,24 @@ 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,6 +640,7 @@ 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) {
@@ -557,9 +648,34 @@ tail_call:
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;
@@ -596,6 +712,7 @@ 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) {
@@ -603,9 +720,21 @@ static void zobj_collect_white(zval *pz TSRMLS_DC)
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;