From e18f631abe329cd5466700fd67565c69012c5816 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 20 May 2020 00:12:24 +0300 Subject: [PATCH] Use light version of zend_array_destroy() to free arrays without refcounted elements and string indexes. --- ext/opcache/jit/zend_jit_helpers.c | 27 +++++++++++++++++++++++++++ ext/opcache/jit/zend_jit_x86.dasc | 10 +++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index ed7708126c..29f5d5f68e 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1537,3 +1537,30 @@ static void ZEND_FASTCALL zend_jit_pre_dec(zval *var_ptr, zval *ret) decrement_function(var_ptr); ZVAL_COPY(ret, var_ptr); } + +#define HT_POISONED_PTR ((HashTable *) (intptr_t) -1) + +static zend_never_inline void ZEND_FASTCALL _zend_hash_iterators_remove(HashTable *ht) +{ + HashTableIterator *iter = EG(ht_iterators); + HashTableIterator *end = iter + EG(ht_iterators_used); + + while (iter != end) { + if (iter->ht == ht) { + iter->ht = HT_POISONED_PTR; + } + iter++; + } +} + +static void ZEND_FASTCALL zend_jit_array_free(HashTable *ht) +{ + GC_REMOVE_FROM_BUFFER(ht); + if (UNEXPECTED(HT_HAS_ITERATORS(ht))) { + _zend_hash_iterators_remove(ht); + } + if (!(EXPECTED(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED))) { + efree(HT_GET_DATA_ADDR(ht)); + } + FREE_HASHTABLE(ht); +} diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 87b10f7122..217c5d141a 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -1316,10 +1316,14 @@ static void* dasm_labels[zend_lb_MAX]; | EXT_CALL _efree, r0 || break; || } else if (type == IS_ARRAY) { -|| if (opline) { -| SAVE_VALID_OPLINE opline, r0 +|| if ((var_info) & (MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_REF)) { +|| if (opline && ((var_info) & (MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_REF))) { +| SAVE_VALID_OPLINE opline, r0 +|| } +| EXT_CALL zend_array_destroy, r0 +|| } else { +| EXT_CALL zend_jit_array_free, r0| || } -| EXT_CALL zend_array_destroy, r0 || break; || } else if (type == IS_OBJECT) { || if (opline) { -- 2.40.0