break;
}
if (!zend_jit_fetch_dim_read(&dasm_state, opline, op_array, ssa, ssa_op,
- OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), RES_INFO(),
+ OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), RES_INFO(), RES_REG_ADDR(),
zend_may_throw(opline, ssa_op, op_array, ssa))) {
goto jit_failure;
}
zend_bool support_opline;
support_opline =
- zend_jit_opline_supports_reg(op_array, ssa, opline, ssa_op);
+ zend_jit_opline_supports_reg(op_array, ssa, opline, ssa_op, p);
if (ssa_op->op1_use >= 0
&& start[ssa_op->op1_use] >= 0
&& !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op1_use)) {
|| opline->opcode == ZEND_POST_DEC
|| opline->opcode == ZEND_ADD
|| opline->opcode == ZEND_SUB
- || opline->opcode == ZEND_MUL) {
+ || opline->opcode == ZEND_MUL
+ || opline->opcode == ZEND_FETCH_DIM_R) {
if (!(ssa->var_info[ssa_op->result_def].type & MAY_BE_DOUBLE)
|| (opline->opcode != ZEND_PRE_INC && opline->opcode != ZEND_PRE_DEC)) {
start[ssa_op->result_def] = idx;
CHECK_OP2_TRACE_TYPE();
res_info = RES_INFO();
if (!zend_jit_fetch_dim_read(&dasm_state, opline, op_array, ssa, ssa_op,
- op1_info, op1_addr, op2_info, res_info,
+ op1_info, op1_addr, op2_info, res_info, RES_REG_ADDR(),
(
(op1_info & MAY_BE_ANY) != MAY_BE_ARRAY ||
(op2_info & (MAY_BE_ANY - (MAY_BE_LONG|MAY_BE_STRING))) != 0 ||
return 0;
}
-static int zend_jit_fetch_dim_read(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, uint32_t op1_info, zend_jit_addr op1_addr, uint32_t op2_info, uint32_t res_info, int may_throw)
+static int zend_jit_fetch_dim_read(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, uint32_t op1_info, zend_jit_addr op1_addr, uint32_t op2_info, uint32_t res_info, zend_jit_addr res_addr, int may_throw)
{
- zend_jit_addr orig_op1_addr, op2_addr, res_addr;
+ zend_jit_addr orig_op1_addr, op2_addr;
const void *exit_addr = NULL;
const void *not_found_exit_addr = NULL;
const void *res_exit_addr = NULL;
orig_op1_addr = OP1_ADDR();
op2_addr = OP2_ADDR();
- res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
if (opline->opcode != ZEND_FETCH_DIM_IS
&& JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
return 0;
}
-static zend_bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op)
+static zend_bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op, zend_jit_trace_rec *trace)
{
uint32_t op1_info, op2_info;
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
return 1;
+ case ZEND_FETCH_DIM_R:
+ op1_info = OP1_INFO();
+ op2_info = OP2_INFO();
+ if (trace
+ && trace->op1_type != IS_UNKNOWN
+ && (trace->op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) == IS_ARRAY) {
+ op1_info &= ~((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_ARRAY);
+ }
+ return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
+ (!(opline->op1_type & (IS_TMP_VAR|IS_VAR)) || !(op1_info & MAY_BE_RC1)) &&
+ (((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
+ (((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING) &&
+ (!(opline->op2_type & (IS_TMP_VAR|IS_VAR)) || !(op2_info & MAY_BE_RC1))));
}
return 0;
}
if (ssa->vars[var].definition >= 0) {
uint32_t def = ssa->vars[var].definition;
- if (!zend_jit_opline_supports_reg(op_array, ssa, op_array->opcodes + def, ssa->ops + def)) {
+ if (!zend_jit_opline_supports_reg(op_array, ssa, op_array->opcodes + def, ssa->ops + def, NULL)) {
return 0;
}
}
do {
if (!zend_ssa_is_no_val_use(op_array->opcodes + use, ssa->ops + use, var) &&
- !zend_jit_opline_supports_reg(op_array, ssa, op_array->opcodes + use, ssa->ops + use)) {
+ !zend_jit_opline_supports_reg(op_array, ssa, op_array->opcodes + use, ssa->ops + use, NULL)) {
return 0;
}
use = zend_ssa_next_use(ssa->ops, var, use);