mirror of
https://github.com/php/php-src.git
synced 2024-11-24 18:34:21 +08:00
Improved GC to avaid reconstruction of HashTables for object properties
This commit is contained in:
parent
07f60310b2
commit
e623543452
287
Zend/zend_gc.c
287
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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user