mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
JIT: Improve x86_64 code generated for PHP Array Bounds Checks (#14246)
This commit is contained in:
@@ -1699,6 +1699,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
|
||||
if (!zend_jit_assign_dim_op(&ctx, opline,
|
||||
OP1_INFO(), OP1_DEF_INFO(), OP1_REG_ADDR(),
|
||||
OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
|
||||
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
|
||||
OP1_DATA_INFO(), OP1_DATA_REG_ADDR(), OP1_DATA_RANGE(), IS_UNKNOWN,
|
||||
zend_may_throw(opline, ssa_op, op_array, ssa))) {
|
||||
goto jit_failure;
|
||||
@@ -1714,6 +1715,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
|
||||
if (!zend_jit_assign_dim(&ctx, opline,
|
||||
OP1_INFO(), OP1_REG_ADDR(),
|
||||
OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
|
||||
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
|
||||
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,
|
||||
@@ -2234,7 +2236,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
|
||||
}
|
||||
if (!zend_jit_fetch_dim_read(&ctx, opline, ssa, ssa_op,
|
||||
OP1_INFO(), OP1_REG_ADDR(), 0,
|
||||
OP2_INFO(), OP2_REG_ADDR(),
|
||||
OP2_INFO(), OP2_REG_ADDR(), OP2_RANGE(),
|
||||
RES_INFO(), RES_REG_ADDR(), IS_UNKNOWN)) {
|
||||
goto jit_failure;
|
||||
}
|
||||
@@ -2252,6 +2254,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
|
||||
if (!zend_jit_fetch_dim(&ctx, opline,
|
||||
OP1_INFO(), OP1_REG_ADDR(),
|
||||
OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
|
||||
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : 0,
|
||||
RES_REG_ADDR(), IS_UNKNOWN)) {
|
||||
goto jit_failure;
|
||||
}
|
||||
@@ -2280,7 +2283,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
|
||||
}
|
||||
if (!zend_jit_isset_isempty_dim(&ctx, opline,
|
||||
OP1_INFO(), OP1_REG_ADDR(), 0,
|
||||
OP2_INFO(), OP2_REG_ADDR(), IS_UNKNOWN,
|
||||
OP2_INFO(), OP2_REG_ADDR(), OP2_RANGE(), IS_UNKNOWN,
|
||||
zend_may_throw(opline, ssa_op, op_array, ssa),
|
||||
smart_branch_opcode, target_label, target_label2,
|
||||
NULL)) {
|
||||
|
||||
@@ -11389,6 +11389,7 @@ static int zend_jit_fetch_dimension_address_inner(zend_jit_ctx *jit,
|
||||
uint32_t op1_info,
|
||||
uint32_t op2_info,
|
||||
zend_jit_addr op2_addr,
|
||||
zend_ssa_range *op2_range,
|
||||
uint8_t dim_type,
|
||||
const void *found_exit_addr,
|
||||
const void *not_found_exit_addr,
|
||||
@@ -11489,9 +11490,16 @@ static int zend_jit_fetch_dimension_address_inner(zend_jit_ctx *jit,
|
||||
// JIT: if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed))
|
||||
ref = ir_LOAD_U32(ir_ADD_OFFSET(ht_ref, offsetof(zend_array, nNumUsed)));
|
||||
#if SIZEOF_ZEND_LONG == 8
|
||||
ref = ir_ZEXT_L(ref);
|
||||
#endif
|
||||
if ((Z_MODE(op2_addr) == IS_CONST_ZVAL && val >= 0 && val <= UINT32_MAX)
|
||||
|| (op2_range && op2_range->min >= 0 && op2_range->max <= UINT32_MAX)) {
|
||||
/* comapre only the lower 32-bits to allow load fusion on x86_64 */
|
||||
cond = ir_ULT(ir_TRUNC_U32(h), ref);
|
||||
} else {
|
||||
cond = ir_ULT(h, ir_ZEXT_L(ref));
|
||||
}
|
||||
#else
|
||||
cond = ir_ULT(h, ref);
|
||||
#endif
|
||||
if (type == BP_JIT_IS) {
|
||||
if (not_found_exit_addr) {
|
||||
ir_GUARD(cond, ir_CONST_ADDR(not_found_exit_addr));
|
||||
@@ -11988,6 +11996,7 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit,
|
||||
bool op1_avoid_refcounting,
|
||||
uint32_t op2_info,
|
||||
zend_jit_addr op2_addr,
|
||||
zend_ssa_range *op2_range,
|
||||
uint32_t res_info,
|
||||
zend_jit_addr res_addr,
|
||||
uint8_t dim_type)
|
||||
@@ -12108,7 +12117,7 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit,
|
||||
|
||||
if (!zend_jit_fetch_dimension_address_inner(jit, opline,
|
||||
(opline->opcode != ZEND_FETCH_DIM_IS) ? BP_VAR_R : BP_VAR_IS,
|
||||
op1_info, op2_info, op2_addr, dim_type, NULL, not_found_exit_addr, exit_addr,
|
||||
op1_info, op2_info, op2_addr, op2_range, dim_type, NULL, not_found_exit_addr, exit_addr,
|
||||
result_type_guard, ht_ref, found_inputs, found_vals,
|
||||
&end_inputs, ¬_found_inputs)) {
|
||||
return 0;
|
||||
@@ -12446,6 +12455,7 @@ static int zend_jit_fetch_dim(zend_jit_ctx *jit,
|
||||
zend_jit_addr op1_addr,
|
||||
uint32_t op2_info,
|
||||
zend_jit_addr op2_addr,
|
||||
zend_ssa_range *op2_range,
|
||||
zend_jit_addr res_addr,
|
||||
uint8_t dim_type)
|
||||
{
|
||||
@@ -12510,7 +12520,7 @@ static int zend_jit_fetch_dim(zend_jit_ctx *jit,
|
||||
may_throw = 1;
|
||||
}
|
||||
if (!zend_jit_fetch_dimension_address_inner(jit, opline, type, op1_info,
|
||||
op2_info, op2_addr, dim_type, NULL, NULL, NULL,
|
||||
op2_info, op2_addr, op2_range, dim_type, NULL, NULL, NULL,
|
||||
0, ht_ref, found_inputs, found_vals, &end_inputs, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -12621,6 +12631,7 @@ static int zend_jit_isset_isempty_dim(zend_jit_ctx *jit,
|
||||
bool op1_avoid_refcounting,
|
||||
uint32_t op2_info,
|
||||
zend_jit_addr op2_addr,
|
||||
zend_ssa_range *op2_range,
|
||||
uint8_t dim_type,
|
||||
int may_throw,
|
||||
uint8_t smart_branch_opcode,
|
||||
@@ -12670,7 +12681,7 @@ static int zend_jit_isset_isempty_dim(zend_jit_ctx *jit,
|
||||
}
|
||||
}
|
||||
if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_JIT_IS, op1_info,
|
||||
op2_info, op2_addr, dim_type, found_exit_addr, not_found_exit_addr, NULL,
|
||||
op2_info, op2_addr, op2_range, dim_type, found_exit_addr, not_found_exit_addr, NULL,
|
||||
0, ht_ref, true_inputs, NULL, &false_inputs, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -12814,6 +12825,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit,
|
||||
zend_jit_addr op1_addr,
|
||||
uint32_t op2_info,
|
||||
zend_jit_addr op2_addr,
|
||||
zend_ssa_range *op2_range,
|
||||
uint32_t val_info,
|
||||
zend_jit_addr op3_addr,
|
||||
zend_jit_addr op3_def_addr,
|
||||
@@ -12883,7 +12895,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit,
|
||||
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, op2_range, dim_type, NULL, NULL, NULL,
|
||||
0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -12985,6 +12997,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit,
|
||||
zend_jit_addr op1_addr,
|
||||
uint32_t op2_info,
|
||||
zend_jit_addr op2_addr,
|
||||
zend_ssa_range *op2_range,
|
||||
uint32_t op1_data_info,
|
||||
zend_jit_addr op3_addr,
|
||||
zend_ssa_range *op1_data_range,
|
||||
@@ -13054,7 +13067,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit,
|
||||
}
|
||||
|
||||
if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_VAR_RW, op1_info,
|
||||
op2_info, op2_addr, dim_type, NULL, not_found_exit_addr, NULL,
|
||||
op2_info, op2_addr, op2_range, dim_type, NULL, not_found_exit_addr, NULL,
|
||||
0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4642,6 +4642,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
|
||||
if (!zend_jit_assign_dim_op(&ctx, opline,
|
||||
op1_info, op1_def_info, op1_addr,
|
||||
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
|
||||
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
|
||||
op1_data_info, OP1_DATA_REG_ADDR(), OP1_DATA_RANGE(), val_type,
|
||||
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
|
||||
goto jit_failure;
|
||||
@@ -4948,6 +4949,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
|
||||
if (!zend_jit_assign_dim(&ctx, opline,
|
||||
op1_info, op1_addr,
|
||||
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
|
||||
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
|
||||
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,
|
||||
@@ -5731,7 +5733,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
|
||||
}
|
||||
if (!zend_jit_fetch_dim_read(&ctx, opline, ssa, ssa_op,
|
||||
op1_info, op1_addr, avoid_refcounting,
|
||||
op2_info, OP2_REG_ADDR(),
|
||||
op2_info, OP2_REG_ADDR(), OP2_RANGE(),
|
||||
res_info, RES_REG_ADDR(), val_type)) {
|
||||
goto jit_failure;
|
||||
}
|
||||
@@ -5780,6 +5782,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
|
||||
if (!zend_jit_fetch_dim(&ctx, opline,
|
||||
op1_info, op1_addr,
|
||||
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
|
||||
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
|
||||
RES_REG_ADDR(), val_type)) {
|
||||
goto jit_failure;
|
||||
}
|
||||
@@ -5868,7 +5871,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
|
||||
}
|
||||
if (!zend_jit_isset_isempty_dim(&ctx, opline,
|
||||
op1_info, op1_addr, avoid_refcounting,
|
||||
op2_info, OP2_REG_ADDR(), val_type,
|
||||
op2_info, OP2_REG_ADDR(), OP2_RANGE(), val_type,
|
||||
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info),
|
||||
smart_branch_opcode, -1, -1,
|
||||
exit_addr)) {
|
||||
|
||||
Reference in New Issue
Block a user