stack = frame->stack;
op_array = p->op_array;
level++;
- ZEND_ASSERT(ssa_vars_count < 0xff);
+ // TODO: remove this restriction ???
+ if (ssa_vars_count >= 0xff) {
+ return NULL;
+ }
p->first_ssa_var = ssa_vars_count;
for (i = 0; i < op_array->last_var; i++) {
SET_STACK_VAR(stack, i, ssa_vars_count++);
frame = zend_jit_trace_ret_frame(frame, op_array);
stack = frame->stack;
if (level == 0) {
- ZEND_ASSERT(ssa_vars_count <= 0xff);
+ // TODO: remove this restriction ???
+ if (ssa_vars_count >= 0xff) {
+ return NULL;
+ }
p->first_ssa_var = ssa_vars_count;
for (i = 0; i < op_array->last_var + op_array->T; i++) {
SET_STACK_VAR(stack, i, ssa_vars_count++);
ssa = zend_jit_trace_build_tssa(trace_buffer, parent_trace, exit_num, script, op_arrays, &num_op_arrays);
+ if (!ssa) {
+ zend_arena_release(&CG(arena), checkpoint);
+ JIT_G(current_trace) = NULL;
+ return NULL;
+ }
+
/* Register allocation */
if (zend_jit_reg_alloc && zend_jit_level >= ZEND_JIT_LEVEL_INLINE) {
ra = zend_jit_trace_allocate_registers(trace_buffer, ssa, parent_trace, exit_num);
t->link = zend_jit_find_trace(p->opline->handler);
zend_jit_trace_link_to_root(&dasm_state, p->opline->handler);
} else if (p->stop == ZEND_JIT_TRACE_STOP_RETURN) {
- zend_jit_trace_return(&dasm_state);
+ zend_jit_trace_return(&dasm_state, 0);
} else {
// TODO: not implemented ???
ZEND_ASSERT(0 && p->stop);
const zend_op *opline;
uint32_t i, stack_size;
zend_jit_trace_stack *stack;
+ zend_bool original_handler = 0;
if (!zend_jit_trace_exit_needs_deoptimization(trace_num, exit_num)) {
return dasm_labels[zend_lbtrace_escape];
opline = (const zend_op*)((uintptr_t)opline & ~(ZEND_JIT_EXIT_JITED|ZEND_JIT_EXIT_BLACKLISTED));
if (opline) {
zend_jit_set_ip(&dasm_state, opline);
+ if (opline == zend_jit_traces[zend_jit_traces[trace_num].root].opline) {
+ /* prevent endless loop */
+ original_handler = 1;
+ }
}
- zend_jit_trace_return(&dasm_state);
+ zend_jit_trace_return(&dasm_state, original_handler);
handler = dasm_link_and_encode(&dasm_state, NULL, NULL, NULL, NULL, name, 1);
t->exit_count = 0;
t->child_count = 0;
t->stack_map_size = 0;
+ t->opline = ((zend_jit_trace_start_rec*)trace_buffer)->opline;
t->exit_info = exit_info;
t->stack_map = NULL;
t->exit_count = 0;
t->child_count = 0;
t->stack_map_size = 0;
+ t->opline = NULL;
t->exit_info = exit_info;
t->stack_map = NULL;
return 1;
}
-static int zend_jit_trace_return(dasm_State **Dst)
+static int zend_jit_trace_return(dasm_State **Dst, zend_bool original_handler)
{
#if 0
| jmp ->trace_escape
#else
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
| add r4, HYBRID_SPAD
- | JMP_IP
+ if (!original_handler) {
+ | JMP_IP
+ } else {
+ | mov r0, EX->func
+ | mov r0, aword [r0 + offsetof(zend_op_array, reserved[zend_func_info_rid])]
+ | mov r0, aword [r0 + offsetof(zend_jit_op_array_trace_extension, offset)]
+ | jmp aword [IP + r0]
+ }
} else if (GCC_GLOBAL_REGS) {
| add r4, SPAD // stack alignment
- | JMP_IP
+ if (!original_handler) {
+ | JMP_IP
+ } else {
+ | mov r0, EX->func
+ | mov r0, aword [r0 + offsetof(zend_op_array, reserved[zend_func_info_rid])]
+ | mov r0, aword [r0 + offsetof(zend_jit_op_array_trace_extension, offset)]
+ | jmp aword [IP + r0]
+ }
} else {
| mov FP, aword T2 // restore FP
| mov RX, aword T3 // restore IP
| add r4, NR_SPAD // stack alignment
| mov r0, 2 // ZEND_VM_LEAVE
| ret
+ // TODO: support for "original_handler" ????
}
#endif
return 1;