From be3c9b047b4a050006ed3b15b22b70f6e70dfed4 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 18 Aug 2025 15:14:35 +0200 Subject: [PATCH 1/2] Fit JIT variable not stored before YIELD --- ext/opcache/jit/zend_jit_vm_helpers.c | 15 +++++++++++++-- ext/opcache/tests/jit/gh19493.phpt | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/jit/gh19493.phpt diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index f4d261cd75349..955e331351931 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -937,11 +937,18 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, break; } +#ifdef HAVE_GCC_GLOBAL_REGS + const zend_op *prev_opline = opline; +#endif handler = (zend_vm_opcode_handler_t)ZEND_OP_TRACE_INFO(opline, offset)->call_handler; #ifdef HAVE_GCC_GLOBAL_REGS handler(); if (UNEXPECTED(opline == zend_jit_halt_op)) { - stop = ZEND_JIT_TRACE_STOP_RETURN; + if (prev_opline->opcode == ZEND_YIELD) { + stop = ZEND_JIT_TRACE_STOP_INTERPRETER; + } else { + stop = ZEND_JIT_TRACE_STOP_RETURN; + } opline = NULL; halt = ZEND_JIT_TRACE_HALT; break; @@ -951,7 +958,11 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, rc = handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); if (rc != 0) { if (rc < 0) { - stop = ZEND_JIT_TRACE_STOP_RETURN; + if (opline->opcode == ZEND_YIELD) { + stop = ZEND_JIT_TRACE_STOP_INTERPRETER; + } else { + stop = ZEND_JIT_TRACE_STOP_RETURN; + } opline = NULL; halt = ZEND_JIT_TRACE_HALT; break; diff --git a/ext/opcache/tests/jit/gh19493.phpt b/ext/opcache/tests/jit/gh19493.phpt new file mode 100644 index 0000000000000..777c56979ee93 --- /dev/null +++ b/ext/opcache/tests/jit/gh19493.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19493: Var not stored before YIELD +--FILE-- +getReturn()); + +?> +--EXPECT-- +int(99) From 758ae343165b5f1f55688c95d0880e95b6fd1082 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 19 Aug 2025 09:32:32 +0200 Subject: [PATCH 2/2] YIELD_FROM --- ext/opcache/jit/zend_jit_vm_helpers.c | 4 ++-- .../jit/{gh19493.phpt => gh19493-001.phpt} | 2 +- ext/opcache/tests/jit/gh19493-002.phpt | 24 +++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) rename ext/opcache/tests/jit/{gh19493.phpt => gh19493-001.phpt} (88%) create mode 100644 ext/opcache/tests/jit/gh19493-002.phpt diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index 955e331351931..8b85324ef8976 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -944,7 +944,7 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, #ifdef HAVE_GCC_GLOBAL_REGS handler(); if (UNEXPECTED(opline == zend_jit_halt_op)) { - if (prev_opline->opcode == ZEND_YIELD) { + if (prev_opline->opcode == ZEND_YIELD || prev_opline->opcode == ZEND_YIELD_FROM) { stop = ZEND_JIT_TRACE_STOP_INTERPRETER; } else { stop = ZEND_JIT_TRACE_STOP_RETURN; @@ -958,7 +958,7 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, rc = handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); if (rc != 0) { if (rc < 0) { - if (opline->opcode == ZEND_YIELD) { + if (opline->opcode == ZEND_YIELD || opline->opcode == ZEND_YIELD_FROM) { stop = ZEND_JIT_TRACE_STOP_INTERPRETER; } else { stop = ZEND_JIT_TRACE_STOP_RETURN; diff --git a/ext/opcache/tests/jit/gh19493.phpt b/ext/opcache/tests/jit/gh19493-001.phpt similarity index 88% rename from ext/opcache/tests/jit/gh19493.phpt rename to ext/opcache/tests/jit/gh19493-001.phpt index 777c56979ee93..68e5d6e240191 100644 --- a/ext/opcache/tests/jit/gh19493.phpt +++ b/ext/opcache/tests/jit/gh19493-001.phpt @@ -1,5 +1,5 @@ --TEST-- -GH-19493: Var not stored before YIELD +GH-19493 001: Var not stored before YIELD --FILE-- getReturn()); + +?> +--EXPECT-- +int(99)