{
uint32_t trace_num = (uint32_t)(uintptr_t)EG(reserved)[zend_func_info_rid];
zend_execute_data *execute_data = EG(current_execute_data);
+ const zend_op *orig_opline = EX(opline);
const zend_op *opline;
zend_jit_trace_info *t = &zend_jit_traces[trace_num];
}
if (EG(vm_interrupt)) {
- return 0;
+ return 1;
/* Lock-free check if the side trace was already JIT-ed or blacklist-ed in another process */
} else if (t->exit_info[exit_num].flags & (ZEND_JIT_EXIT_JITED|ZEND_JIT_EXIT_BLACKLISTED)) {
return 0;
fprintf(stderr, "---- EXIT %d/%d blacklisted\n",
trace_num, exit_num);
}
+ return 0;
}
} else if (zend_jit_trace_exit_is_hot(trace_num, exit_num)) {
return zend_jit_trace_hot_side(execute_data, trace_num, exit_num);
}
- return 0;
+ /* Return 1 to call original handler instead of the same JIT-ed trace */
+ return (orig_opline == t->opline && EX(opline) == orig_opline);
}
static zend_always_inline uint8_t zend_jit_trace_supported(const zend_op *opline)
| add r4, 8*4+8*8 /* CPU regs + SSE regs */
|.endif
- | // check for interrupt (try to avoid this ???)
- | MEM_OP2_1_ZTS cmp, byte, executor_globals, vm_interrupt, 0, r0
- | jne ->interrupt_handler
+ | test eax, eax
+ | jne >1
| // execute_data = EG(current_execute_data)
| MEM_OP2_2_ZTS mov, FP, aword, executor_globals, current_execute_data, r0
- | test eax, eax
- | jl ->trace_halt
| // opline = EX(opline)
| LOAD_OPLINE
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
-#if 1
- //TODO: this doesn't work for exit from first instruction ???
| add r4, HYBRID_SPAD
| JMP_IP
-#else
- | mov r0, EX->func
- | mov r1, aword [r0 + offsetof(zend_op_array, reserved[zend_func_info_rid])]
- | mov r1, aword [r1 + offsetof(zend_jit_op_array_trace_extension, offset)]
- | jmp aword [IP + r1]
-#endif
} else if (GCC_GLOBAL_REGS) {
| add r4, SPAD // stack alignment
| JMP_IP
| ret
}
+ |1:
+ | jl ->trace_halt
+
+ | // execute_data = EG(current_execute_data)
+ | MEM_OP2_2_ZTS mov, FP, aword, executor_globals, current_execute_data, r0
+ | // opline = EX(opline)
+ | LOAD_OPLINE
+
+ | // check for interrupt (try to avoid this ???)
+ | MEM_OP2_1_ZTS cmp, byte, executor_globals, vm_interrupt, 0, r0
+ | jne ->interrupt_handler
+
+ if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
+ | add r4, HYBRID_SPAD
+ | 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
+ | 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 IP, aword EX->opline
+ | mov FCARG1a, FP
+ | 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)]
+ | call aword [IP + r0]
+ | mov FP, aword T2 // restore FP
+ | mov RX, aword T3 // restore IP
+ | add r4, NR_SPAD // stack alignment
+ | mov r0, 1 // ZEND_VM_ENTER
+ | ret
+ }
+
return 1;
}