From: Xinchen Hui Date: Mon, 13 Feb 2017 11:17:09 +0000 (+0800) Subject: Merge branch 'PHP-7.0' into PHP-7.1 X-Git-Tag: php-7.1.3RC1~35 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9df7cc3e68a327ad6fb38cecb55ca151a033695d;p=php Merge branch 'PHP-7.0' into PHP-7.1 * PHP-7.0: Fixed bug #73989 (PHP 7.1 Segfaults within Symfony test suite) --- 9df7cc3e68a327ad6fb38cecb55ca151a033695d diff --cc Zend/zend_gc.c index a125c44ae4,0b9ce8ccc5..087f04bc3f --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@@ -714,27 -678,26 +728,25 @@@ static void gc_add_garbage(zend_refcoun #endif } else { /* If we don't have free slots in the buffer, allocate a new one and - * set it's address to GC_ROOT_BUFFER_MAX_ENTRIES that have special + * set it's address above GC_ROOT_BUFFER_MAX_ENTRIES that have special * meaning. */ - if (!*additional_buffer || (*additional_buffer)->used == GC_NUM_ADDITIONAL_ENTRIES) { + if (!GC_G(additional_buffer) || GC_G(additional_buffer)->used == GC_NUM_ADDITIONAL_ENTRIES) { gc_additional_buffer *new_buffer = emalloc(sizeof(gc_additional_buffer)); new_buffer->used = 0; - new_buffer->next = *additional_buffer; - *additional_buffer = new_buffer; + new_buffer->next = GC_G(additional_buffer); + GC_G(additional_buffer) = new_buffer; } - buf = (*additional_buffer)->buf + (*additional_buffer)->used; - (*additional_buffer)->used++; + buf = GC_G(additional_buffer)->buf + GC_G(additional_buffer)->used; #if 1 /* optimization: color is already GC_BLACK (0) */ - GC_INFO(ref) = GC_ROOT_BUFFER_MAX_ENTRIES; + GC_INFO(ref) = GC_ROOT_BUFFER_MAX_ENTRIES + GC_G(additional_buffer)->used; #else - GC_REF_SET_ADDRESS(ref, GC_ROOT_BUFFER_MAX_ENTRIES); + GC_REF_SET_ADDRESS(ref, GC_ROOT_BUFFER_MAX_ENTRIES) + GC_G(additional_buffer)->used; #endif - /* modify type to prevent indirect destruction */ - GC_TYPE(ref) |= GC_FAKE_BUFFER_FLAG; + GC_G(additional_buffer)->used++; } if (buf) { - GC_REFCOUNT(ref)++; buf->ref = ref; buf->next = GC_G(roots).next; buf->prev = &GC_G(roots); @@@ -897,8 -864,9 +913,8 @@@ static int gc_collect_roots(uint32_t *f current = GC_G(roots).next; while (current != &GC_G(roots)) { - GC_REFCOUNT(current->ref)++; if (GC_REF_GET_COLOR(current->ref) == GC_WHITE) { - count += gc_collect_white(current->ref, flags, additional_buffer); + count += gc_collect_white(current->ref, flags); } current = current->next; } @@@ -934,12 -902,16 +950,15 @@@ static void gc_remove_nested_data_from_ tail_call: if (root || (GC_ADDRESS(GC_INFO(ref)) != 0 && - GC_REF_GET_COLOR(ref) == GC_BLACK && - GC_ADDRESS(GC_INFO(ref)) != GC_ROOT_BUFFER_MAX_ENTRIES)) { + GC_REF_GET_COLOR(ref) == GC_BLACK)) { GC_TRACE_REF(ref, "removing from buffer"); - GC_REFCOUNT(ref)--; if (root) { + if (EXPECTED(GC_ADDRESS(GC_INFO(root->ref)) < GC_ROOT_BUFFER_MAX_ENTRIES)) { + gc_remove_from_roots(root); + } else { + gc_remove_from_additional_roots(root); + } GC_INFO(ref) = 0; - GC_REMOVE_FROM_ROOTS(root); root = NULL; } else { GC_REMOVE_FROM_BUFFER(ref);