From e27e79f5f3545dcaaf26bd16adad163513b09628 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 9 Jan 2025 20:14:13 +0100 Subject: [PATCH] Backport fix GH-17307 This is a backport of GH-17319 to fix GH-17307 on lower branches. --- ext/opcache/jit/zend_jit_arm64.dasc | 15 ++++++-------- ext/opcache/jit/zend_jit_x86.dasc | 11 ++++------ ext/opcache/tests/jit/gh17307.phpt | 32 +++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 ext/opcache/tests/jit/gh17307.phpt diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index c351c482d51cb..2cbf68643086a 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -8471,6 +8471,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con { uint32_t used_stack; bool stack_check = 1; + const size_t func_type_offset = is_closure ? offsetof(zend_closure, func.type) : offsetof(zend_function, type); // REG0 -> zend_function // FCARG1 -> used_stack @@ -8484,15 +8485,11 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value + ZEND_OBSERVER_ENABLED) * sizeof(zval); | // if (EXPECTED(ZEND_USER_CODE(func->type))) { - if (!is_closure) { - | LOAD_32BIT_VAL FCARG1w, used_stack - | // Check whether REG0 is an internal function. - | ldrb TMP1w, [REG0, #offsetof(zend_function, type)] - | TST_32_WITH_CONST TMP1w, 1, TMP2w - | bne >1 - } else { - | LOAD_32BIT_VAL FCARG1w, used_stack - } + | LOAD_32BIT_VAL FCARG1w, used_stack + | // Check whether REG0 is an internal function. + | ldrb TMP1w, [REG0, #func_type_offset] + | TST_32_WITH_CONST TMP1w, 1, TMP2w + | bne >1 | // used_stack += (func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args)) * sizeof(zval); | LOAD_32BIT_VAL REG2w, opline->extended_value if (!is_closure) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index f1c52bcc976e3..9cf0c6cd8e881 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -9072,6 +9072,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con { uint32_t used_stack; bool stack_check = 1; + const size_t func_type_offset = is_closure ? offsetof(zend_closure, func.type) : offsetof(zend_function, type); if (func) { used_stack = zend_vm_calc_used_stack(opline->extended_value, func); @@ -9082,13 +9083,9 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value + ZEND_OBSERVER_ENABLED) * sizeof(zval); | // if (EXPECTED(ZEND_USER_CODE(func->type))) { - if (!is_closure) { - | test byte [r0 + offsetof(zend_function, type)], 1 - | mov FCARG1a, used_stack - | jnz >1 - } else { - | mov FCARG1a, used_stack - } + | test byte [r0 + func_type_offset], 1 + | mov FCARG1a, used_stack + | jnz >1 | // used_stack += (func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args)) * sizeof(zval); | mov edx, opline->extended_value if (!is_closure) { diff --git a/ext/opcache/tests/jit/gh17307.phpt b/ext/opcache/tests/jit/gh17307.phpt new file mode 100644 index 0000000000000..292d695963c2e --- /dev/null +++ b/ext/opcache/tests/jit/gh17307.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-17307 (Internal closure causes JIT failure) +--EXTENSIONS-- +opcache +simplexml +bcmath +--INI-- +opcache.jit=1254 +opcache.jit_hot_func=1 +opcache.jit_buffer_size=32M +--FILE-- +"); + +function run_loop($firstTerms, $closure) { + foreach ($firstTerms as $firstTerm) { + \debug_zval_dump($firstTerm); + $closure($firstTerm, "10"); + } +} + +run_loop($simple, bcadd(...)); +echo "Done\n"; + +?> +--EXPECTF-- +object(SimpleXMLElement)#%d (0) refcount(3){ +} +object(SimpleXMLElement)#%d (0) refcount(3){ +} +Done