diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index f4d261cd75349..8b85324ef8976 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 || prev_opline->opcode == ZEND_YIELD_FROM) { + 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 || opline->opcode == ZEND_YIELD_FROM) { + 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-001.phpt b/ext/opcache/tests/jit/gh19493-001.phpt new file mode 100644 index 0000000000000..68e5d6e240191 --- /dev/null +++ b/ext/opcache/tests/jit/gh19493-001.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19493 001: Var not stored before YIELD +--FILE-- +getReturn()); + +?> +--EXPECT-- +int(99) diff --git a/ext/opcache/tests/jit/gh19493-002.phpt b/ext/opcache/tests/jit/gh19493-002.phpt new file mode 100644 index 0000000000000..57f2a9826730f --- /dev/null +++ b/ext/opcache/tests/jit/gh19493-002.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19493 002: Var not stored before YIELD_FROM +--FILE-- +getReturn()); + +?> +--EXPECT-- +int(99)