}
}
}
- if (!zend_jit_leave_func(&dasm_state, opline, op_array, NULL)) {
+ if (!zend_jit_leave_func(&dasm_state, opline, op_array, NULL, NULL)) {
goto jit_failure;
}
}
/* trace info flags */
#define ZEND_JIT_TRACE_CHECK_INTERRUPT (1<<0)
+#define ZEND_JIT_TRACE_LOOP (1<<1)
typedef struct _zend_jit_trace_info {
uint32_t id; /* trace id */
}
}
}
- if (!zend_jit_leave_func(&dasm_state, opline, op_array, p + 1)) {
+ if (!zend_jit_leave_func(&dasm_state, opline, op_array, p + 1, &zend_jit_traces[ZEND_JIT_TRACE_NUM])) {
goto jit_failure;
}
}
if (p->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
t->flags |= ZEND_JIT_TRACE_CHECK_INTERRUPT;
}
- zend_jit_trace_end_loop(&dasm_state, 0, timeout_exit_addr); /* jump back to start of the trace loop */
+ if (!(t->flags & ZEND_JIT_TRACE_LOOP)) {
+ t->flags |= ZEND_JIT_TRACE_LOOP;
+ zend_jit_trace_end_loop(&dasm_state, 0, timeout_exit_addr); /* jump back to start of the trace loop */
+ }
} else if (p->stop == ZEND_JIT_TRACE_STOP_LINK) {
if (ra) {
/* Generate code for trace deoptimization */
return 1;
}
-static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_jit_trace_rec *trace)
+static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_jit_trace_rec *trace, zend_jit_trace_info *trace_info)
{
/* ZEND_CALL_FAKE_CLOSURE handled on slow path to eliminate check for ZEND_CALL_CLOSURE on fast path */
| mov FCARG1d, dword [FP + offsetof(zend_execute_data, This.u1.type_info)]
return 0;
}
| // TODO: exception handling ???
- | CMP_IP next_opline
- | jne &exit_addr
+ if (trace->op == ZEND_JIT_TRACE_END
+ && trace->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
+ trace_info->flags |= ZEND_JIT_TRACE_LOOP;
+ | CMP_IP next_opline
+ | je =>0 // LOOP
+ | jmp &exit_addr
+ } else {
+ | CMP_IP next_opline
+ | jne &exit_addr
+ }
last_valid_opline = trace->opline;