Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions ext/opcache/jit/zend_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1702,7 +1702,12 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
break;
}
if (!zend_jit_assign_dim(&ctx, opline,
OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), OP1_DATA_INFO(), IS_UNKNOWN,
OP1_INFO(), OP1_REG_ADDR(),
OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
OP1_DATA_INFO(), OP1_DATA_REG_ADDR(),
(ctx.ra && (ssa_op+1)->op1_def >= 0) ? OP1_DATA_DEF_REG_ADDR() : 0,
(opline->result_type != IS_UNUSED) ? RES_REG_ADDR() : 0,
IS_UNKNOWN,
zend_may_throw(opline, ssa_op, op_array, ssa))) {
goto jit_failure;
}
Expand Down Expand Up @@ -2008,7 +2013,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
/* For EX variant write into the result of EX opcode. */
if ((opline+1)->opcode == ZEND_JMPZ_EX
|| (opline+1)->opcode == ZEND_JMPNZ_EX) {
res_addr = OP_REG_ADDR(opline + 1, result_type, result, result_def);
res_addr = OP_REG_ADDR(opline + 1, ssa_op + 1, result_type, result, result_def);
}
} else {
smart_branch_opcode = 0;
Expand Down Expand Up @@ -2044,7 +2049,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
/* For EX variant write into the result of EX opcode. */
if ((opline+1)->opcode == ZEND_JMPZ_EX
|| (opline+1)->opcode == ZEND_JMPNZ_EX) {
res_addr = OP_REG_ADDR(opline + 1, result_type, result, result_def);
res_addr = OP_REG_ADDR(opline + 1, ssa_op + 1, result_type, result, result_def);
}
} else {
smart_branch_opcode = 0;
Expand Down
22 changes: 11 additions & 11 deletions ext/opcache/jit/zend_jit_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ typedef uintptr_t zend_jit_addr;
ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline)->op.var))
#endif

#define OP_REG_ADDR(opline, type, op, _ssa_op) \
((ctx.ra && ssa_op->_ssa_op >= 0 && ctx.ra[ssa_op->_ssa_op].ref) ? \
ZEND_ADDR_REG(ssa_op->_ssa_op) : \
#define OP_REG_ADDR(opline, ssa_op, type, op, _ssa_op) \
((ctx.ra && (ssa_op)->_ssa_op >= 0 && ctx.ra[(ssa_op)->_ssa_op].ref) ? \
ZEND_ADDR_REG((ssa_op)->_ssa_op) : \
OP_ADDR(opline, type, op))

#define OP1_ADDR() \
Expand All @@ -92,22 +92,22 @@ typedef uintptr_t zend_jit_addr;
OP_ADDR(opline + 1, op1_type, op1)

#define OP1_REG_ADDR() \
OP_REG_ADDR(opline, op1_type, op1, op1_use)
OP_REG_ADDR(opline, ssa_op, op1_type, op1, op1_use)
#define OP2_REG_ADDR() \
OP_REG_ADDR(opline, op2_type, op2, op2_use)
OP_REG_ADDR(opline, ssa_op, op2_type, op2, op2_use)
#define RES_REG_ADDR() \
OP_REG_ADDR(opline, result_type, result, result_def)
OP_REG_ADDR(opline, ssa_op, result_type, result, result_def)
#define OP1_DATA_REG_ADDR() \
OP_REG_ADDR(opline + 1, op1_type, op1, op1_use)
OP_REG_ADDR(opline + 1, ssa_op + 1, op1_type, op1, op1_use)

#define OP1_DEF_REG_ADDR() \
OP_REG_ADDR(opline, op1_type, op1, op1_def)
OP_REG_ADDR(opline, ssa_op, op1_type, op1, op1_def)
#define OP2_DEF_REG_ADDR() \
OP_REG_ADDR(opline, op2_type, op2, op2_def)
OP_REG_ADDR(opline, ssa_op, op2_type, op2, op2_def)
#define RES_USE_REG_ADDR() \
OP_REG_ADDR(opline, result_type, result, result_use)
OP_REG_ADDR(opline, ssa_op, result_type, result, result_use)
#define OP1_DATA_DEF_REG_ADDR() \
OP_REG_ADDR(opline + 1, op1_type, op1, op1_def)
OP_REG_ADDR(opline + 1, ssa_op + 1, op1_type, op1, op1_def)

static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_addr addr2)
{
Expand Down
68 changes: 56 additions & 12 deletions ext/opcache/jit/zend_jit_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -6232,8 +6232,14 @@ static int zend_jit_assign_to_variable(zend_jit_ctx *jit,
ir_IF_TRUE_cold(if_typed);
jit_SET_EX_OPLINE(jit, opline);
if (Z_MODE(val_addr) == IS_REG) {
ZEND_ASSERT(opline->opcode == ZEND_ASSIGN);
zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
zend_jit_addr real_addr;

if (opline->opcode == ZEND_ASSIGN_DIM) {
real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
} else {
ZEND_ASSERT(opline->opcode == ZEND_ASSIGN);
real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
}
if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
return 0;
}
Expand Down Expand Up @@ -12788,18 +12794,29 @@ static int zend_jit_isset_isempty_dim(zend_jit_ctx *jit,
return 1;
}

static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, uint32_t op2_info, uint32_t val_info, uint8_t dim_type, int may_throw)
static int zend_jit_assign_dim(zend_jit_ctx *jit,
const zend_op *opline,
uint32_t op1_info,
zend_jit_addr op1_addr,
uint32_t op2_info,
zend_jit_addr op2_addr,
uint32_t val_info,
zend_jit_addr op3_addr,
zend_jit_addr op3_def_addr,
zend_jit_addr res_addr,
uint8_t dim_type,
int may_throw)
{
zend_jit_addr op2_addr, op3_addr, res_addr;
ir_ref if_type = IR_UNUSED;
ir_ref end_inputs = IR_UNUSED, ht_ref;

op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0;
op3_addr = OP1_DATA_ADDR();
if (opline->result_type == IS_UNUSED) {
res_addr = 0;
} else {
res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
if (op3_addr != op3_def_addr && op3_def_addr) {
if (!zend_jit_update_regs(jit, (opline+1)->op1.var, op3_addr, op3_def_addr, val_info)) {
return 0;
}
if (Z_MODE(op3_def_addr) == IS_REG && Z_MODE(op3_addr) != IS_REG) {
op3_addr = op3_def_addr;
}
}

if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && (val_info & MAY_BE_UNDEF)) {
Expand Down Expand Up @@ -12852,7 +12869,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_
ir_refs_init(found_values, 8);

if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_VAR_W, op1_info,
op2_info, OP2_ADDR(), dim_type, NULL, NULL, NULL,
op2_info, op2_addr, dim_type, NULL, NULL, NULL,
0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) {
return 0;
}
Expand All @@ -12870,7 +12887,9 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_
var_addr = ZEND_ADDR_REF_ZVAL(ref);

// JIT: value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE);
if (opline->op1_type == IS_VAR) {
if (opline->op1_type == IS_VAR
&& Z_MODE(op3_addr) != IS_REG
&& (res_addr == 0 || Z_MODE(res_addr) != IS_REG)) {
ZEND_ASSERT(opline->result_type == IS_UNUSED);
if (!zend_jit_assign_to_variable_call(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0)) {
return 0;
Expand Down Expand Up @@ -16552,6 +16571,31 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa
return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
(((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
case ZEND_ASSIGN_DIM:
op1_info = OP1_INFO();
op2_info = OP2_INFO();
if (trace) {
if (opline->op1_type == IS_CV) {
if ((opline+1)->op1_type == IS_CV
&& (opline+1)->op1.var == opline->op1.var) {
/* skip $a[x] = $a; */
return 0;
}
} else if (opline->op1_type == IS_VAR) {
if (trace->op1_type == IS_UNKNOWN
|| !(trace->op1_type & IS_TRACE_INDIRECT)
|| opline->result_type != IS_UNUSED) {
return 0;
}
}
if (trace->op1_type != IS_UNKNOWN
&& (trace->op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)) == 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) &&
(((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
}
return 0;
}
Expand Down
7 changes: 6 additions & 1 deletion ext/opcache/jit/zend_jit_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -4934,7 +4934,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
op1_data_info = OP1_DATA_INFO();
CHECK_OP1_DATA_TRACE_TYPE();
if (!zend_jit_assign_dim(&ctx, opline,
op1_info, op1_addr, op2_info, op1_data_info, val_type,
op1_info, op1_addr,
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
op1_data_info, OP1_DATA_REG_ADDR(),
(ctx.ra && (ssa_op+1)->op1_def >= 0) ? OP1_DATA_DEF_REG_ADDR() : 0,
(opline->result_type != IS_UNUSED) ? RES_REG_ADDR() : 0,
val_type,
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
goto jit_failure;
}
Expand Down