diff options
author | Dmitry Stogov <dmitry@zend.com> | 2020-11-23 12:07:05 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2020-11-23 12:07:05 +0300 |
commit | 4cf3da73839b1ef3ab1fc8f74aee3a00237ad6b5 (patch) | |
tree | 6574a8c3496a848f5aa8660d44a06e7b3d9aaba7 /ext/opcache | |
parent | 9b1c02c2df5df2801e546fd5d164c724e5c5ec23 (diff) | |
download | php-git-4cf3da73839b1ef3ab1fc8f74aee3a00237ad6b5.tar.gz |
Keep value of register before possible side exit
Diffstat (limited to 'ext/opcache')
-rw-r--r-- | ext/opcache/jit/zend_jit_x86.dasc | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index c979ea060d..787294cdc7 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -4162,6 +4162,22 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op return 1; } +static int zend_jit_opline_uses_reg(const zend_op *opline, int8_t reg) +{ + if ((opline+1)->opcode == ZEND_OP_DATA + && ((opline+1)->op1_type & (IS_VAR|IS_TMP_VAR|IS_CV)) + && JIT_G(current_frame)->stack[EX_VAR_TO_NUM((opline+1)->op1.var)].reg == reg) { + return 1; + } + return + ((opline->result_type & (IS_VAR|IS_TMP_VAR|IS_CV)) && + JIT_G(current_frame)->stack[EX_VAR_TO_NUM(opline->result.var)].reg == reg) || + ((opline->op1_type & (IS_VAR|IS_TMP_VAR|IS_CV)) && + JIT_G(current_frame)->stack[EX_VAR_TO_NUM(opline->op1.var)].reg == reg) || + ((opline->op2_type & (IS_VAR|IS_TMP_VAR|IS_CV)) && + JIT_G(current_frame)->stack[EX_VAR_TO_NUM(opline->op2.var)].reg == reg); +} + static int zend_jit_math_long_long(dasm_State **Dst, const zend_op *opline, zend_uchar opcode, @@ -4176,7 +4192,14 @@ static int zend_jit_math_long_long(dasm_State **Dst, zend_reg result_reg; if (Z_MODE(res_addr) == IS_REG && (res_info & MAY_BE_LONG)) { - result_reg = Z_REG(res_addr); + if (may_overflow && (res_info & MAY_BE_GUARD) + && JIT_G(current_frame) + && JIT_G(current_frame)->stack + && zend_jit_opline_uses_reg(opline, Z_REG(res_addr))) { + result_reg = ZREG_R0; + } else { + result_reg = Z_REG(res_addr); + } } else if (Z_MODE(op1_addr) == IS_REG && Z_LAST_USE(op1_addr)) { result_reg = Z_REG(op1_addr); } else if (Z_REG(res_addr) != ZREG_R0) { @@ -4247,6 +4270,9 @@ static int zend_jit_math_long_long(dasm_State **Dst, const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); if ((res_info & MAY_BE_ANY) == MAY_BE_LONG) { | jo &exit_addr + if (Z_MODE(res_addr) == IS_REG && result_reg != Z_REG(res_addr)) { + | mov Ra(Z_REG(res_addr)), Ra(result_reg) + } } else if ((res_info & MAY_BE_ANY) == MAY_BE_DOUBLE) { | jno &exit_addr } else { |