Skip to content

Commit 5ef1824

Browse files
authored
JIT: Improve x86_64 code generated for PHP Array Bounds Checks (#14246)
1 parent 0eb68eb commit 5ef1824

File tree

3 files changed

+30
-11
lines changed

3 files changed

+30
-11
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
16991699
if (!zend_jit_assign_dim_op(&ctx, opline,
17001700
OP1_INFO(), OP1_DEF_INFO(), OP1_REG_ADDR(),
17011701
OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
1702+
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
17021703
OP1_DATA_INFO(), OP1_DATA_REG_ADDR(), OP1_DATA_RANGE(), IS_UNKNOWN,
17031704
zend_may_throw(opline, ssa_op, op_array, ssa))) {
17041705
goto jit_failure;
@@ -1714,6 +1715,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
17141715
if (!zend_jit_assign_dim(&ctx, opline,
17151716
OP1_INFO(), OP1_REG_ADDR(),
17161717
OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
1718+
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
17171719
OP1_DATA_INFO(), OP1_DATA_REG_ADDR(),
17181720
(ctx.ra && (ssa_op+1)->op1_def >= 0) ? OP1_DATA_DEF_REG_ADDR() : 0,
17191721
(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
22342236
}
22352237
if (!zend_jit_fetch_dim_read(&ctx, opline, ssa, ssa_op,
22362238
OP1_INFO(), OP1_REG_ADDR(), 0,
2237-
OP2_INFO(), OP2_REG_ADDR(),
2239+
OP2_INFO(), OP2_REG_ADDR(), OP2_RANGE(),
22382240
RES_INFO(), RES_REG_ADDR(), IS_UNKNOWN)) {
22392241
goto jit_failure;
22402242
}
@@ -2252,6 +2254,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
22522254
if (!zend_jit_fetch_dim(&ctx, opline,
22532255
OP1_INFO(), OP1_REG_ADDR(),
22542256
OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
2257+
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : 0,
22552258
RES_REG_ADDR(), IS_UNKNOWN)) {
22562259
goto jit_failure;
22572260
}
@@ -2280,7 +2283,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
22802283
}
22812284
if (!zend_jit_isset_isempty_dim(&ctx, opline,
22822285
OP1_INFO(), OP1_REG_ADDR(), 0,
2283-
OP2_INFO(), OP2_REG_ADDR(), IS_UNKNOWN,
2286+
OP2_INFO(), OP2_REG_ADDR(), OP2_RANGE(), IS_UNKNOWN,
22842287
zend_may_throw(opline, ssa_op, op_array, ssa),
22852288
smart_branch_opcode, target_label, target_label2,
22862289
NULL)) {

ext/opcache/jit/zend_jit_ir.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11389,6 +11389,7 @@ static int zend_jit_fetch_dimension_address_inner(zend_jit_ctx *jit,
1138911389
uint32_t op1_info,
1139011390
uint32_t op2_info,
1139111391
zend_jit_addr op2_addr,
11392+
zend_ssa_range *op2_range,
1139211393
uint8_t dim_type,
1139311394
const void *found_exit_addr,
1139411395
const void *not_found_exit_addr,
@@ -11489,9 +11490,16 @@ static int zend_jit_fetch_dimension_address_inner(zend_jit_ctx *jit,
1148911490
// JIT: if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed))
1149011491
ref = ir_LOAD_U32(ir_ADD_OFFSET(ht_ref, offsetof(zend_array, nNumUsed)));
1149111492
#if SIZEOF_ZEND_LONG == 8
11492-
ref = ir_ZEXT_L(ref);
11493-
#endif
11493+
if ((Z_MODE(op2_addr) == IS_CONST_ZVAL && val >= 0 && val <= UINT32_MAX)
11494+
|| (op2_range && op2_range->min >= 0 && op2_range->max <= UINT32_MAX)) {
11495+
/* comapre only the lower 32-bits to allow load fusion on x86_64 */
11496+
cond = ir_ULT(ir_TRUNC_U32(h), ref);
11497+
} else {
11498+
cond = ir_ULT(h, ir_ZEXT_L(ref));
11499+
}
11500+
#else
1149411501
cond = ir_ULT(h, ref);
11502+
#endif
1149511503
if (type == BP_JIT_IS) {
1149611504
if (not_found_exit_addr) {
1149711505
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,
1198811996
bool op1_avoid_refcounting,
1198911997
uint32_t op2_info,
1199011998
zend_jit_addr op2_addr,
11999+
zend_ssa_range *op2_range,
1199112000
uint32_t res_info,
1199212001
zend_jit_addr res_addr,
1199312002
uint8_t dim_type)
@@ -12108,7 +12117,7 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit,
1210812117

1210912118
if (!zend_jit_fetch_dimension_address_inner(jit, opline,
1211012119
(opline->opcode != ZEND_FETCH_DIM_IS) ? BP_VAR_R : BP_VAR_IS,
12111-
op1_info, op2_info, op2_addr, dim_type, NULL, not_found_exit_addr, exit_addr,
12120+
op1_info, op2_info, op2_addr, op2_range, dim_type, NULL, not_found_exit_addr, exit_addr,
1211212121
result_type_guard, ht_ref, found_inputs, found_vals,
1211312122
&end_inputs, &not_found_inputs)) {
1211412123
return 0;
@@ -12446,6 +12455,7 @@ static int zend_jit_fetch_dim(zend_jit_ctx *jit,
1244612455
zend_jit_addr op1_addr,
1244712456
uint32_t op2_info,
1244812457
zend_jit_addr op2_addr,
12458+
zend_ssa_range *op2_range,
1244912459
zend_jit_addr res_addr,
1245012460
uint8_t dim_type)
1245112461
{
@@ -12510,7 +12520,7 @@ static int zend_jit_fetch_dim(zend_jit_ctx *jit,
1251012520
may_throw = 1;
1251112521
}
1251212522
if (!zend_jit_fetch_dimension_address_inner(jit, opline, type, op1_info,
12513-
op2_info, op2_addr, dim_type, NULL, NULL, NULL,
12523+
op2_info, op2_addr, op2_range, dim_type, NULL, NULL, NULL,
1251412524
0, ht_ref, found_inputs, found_vals, &end_inputs, NULL)) {
1251512525
return 0;
1251612526
}
@@ -12621,6 +12631,7 @@ static int zend_jit_isset_isempty_dim(zend_jit_ctx *jit,
1262112631
bool op1_avoid_refcounting,
1262212632
uint32_t op2_info,
1262312633
zend_jit_addr op2_addr,
12634+
zend_ssa_range *op2_range,
1262412635
uint8_t dim_type,
1262512636
int may_throw,
1262612637
uint8_t smart_branch_opcode,
@@ -12670,7 +12681,7 @@ static int zend_jit_isset_isempty_dim(zend_jit_ctx *jit,
1267012681
}
1267112682
}
1267212683
if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_JIT_IS, op1_info,
12673-
op2_info, op2_addr, dim_type, found_exit_addr, not_found_exit_addr, NULL,
12684+
op2_info, op2_addr, op2_range, dim_type, found_exit_addr, not_found_exit_addr, NULL,
1267412685
0, ht_ref, true_inputs, NULL, &false_inputs, NULL)) {
1267512686
return 0;
1267612687
}
@@ -12814,6 +12825,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit,
1281412825
zend_jit_addr op1_addr,
1281512826
uint32_t op2_info,
1281612827
zend_jit_addr op2_addr,
12828+
zend_ssa_range *op2_range,
1281712829
uint32_t val_info,
1281812830
zend_jit_addr op3_addr,
1281912831
zend_jit_addr op3_def_addr,
@@ -12883,7 +12895,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit,
1288312895
ir_refs_init(found_values, 8);
1288412896

1288512897
if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_VAR_W, op1_info,
12886-
op2_info, op2_addr, dim_type, NULL, NULL, NULL,
12898+
op2_info, op2_addr, op2_range, dim_type, NULL, NULL, NULL,
1288712899
0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) {
1288812900
return 0;
1288912901
}
@@ -12985,6 +12997,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit,
1298512997
zend_jit_addr op1_addr,
1298612998
uint32_t op2_info,
1298712999
zend_jit_addr op2_addr,
13000+
zend_ssa_range *op2_range,
1298813001
uint32_t op1_data_info,
1298913002
zend_jit_addr op3_addr,
1299013003
zend_ssa_range *op1_data_range,
@@ -13054,7 +13067,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit,
1305413067
}
1305513068

1305613069
if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_VAR_RW, op1_info,
13057-
op2_info, op2_addr, dim_type, NULL, not_found_exit_addr, NULL,
13070+
op2_info, op2_addr, op2_range, dim_type, NULL, not_found_exit_addr, NULL,
1305813071
0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) {
1305913072
return 0;
1306013073
}

ext/opcache/jit/zend_jit_trace.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4642,6 +4642,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
46424642
if (!zend_jit_assign_dim_op(&ctx, opline,
46434643
op1_info, op1_def_info, op1_addr,
46444644
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
4645+
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
46454646
op1_data_info, OP1_DATA_REG_ADDR(), OP1_DATA_RANGE(), val_type,
46464647
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
46474648
goto jit_failure;
@@ -4948,6 +4949,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
49484949
if (!zend_jit_assign_dim(&ctx, opline,
49494950
op1_info, op1_addr,
49504951
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
4952+
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
49514953
op1_data_info, OP1_DATA_REG_ADDR(),
49524954
(ctx.ra && (ssa_op+1)->op1_def >= 0) ? OP1_DATA_DEF_REG_ADDR() : 0,
49534955
(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
57315733
}
57325734
if (!zend_jit_fetch_dim_read(&ctx, opline, ssa, ssa_op,
57335735
op1_info, op1_addr, avoid_refcounting,
5734-
op2_info, OP2_REG_ADDR(),
5736+
op2_info, OP2_REG_ADDR(), OP2_RANGE(),
57355737
res_info, RES_REG_ADDR(), val_type)) {
57365738
goto jit_failure;
57375739
}
@@ -5780,6 +5782,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
57805782
if (!zend_jit_fetch_dim(&ctx, opline,
57815783
op1_info, op1_addr,
57825784
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
5785+
(opline->op2_type != IS_UNUSED) ? OP2_RANGE() : NULL,
57835786
RES_REG_ADDR(), val_type)) {
57845787
goto jit_failure;
57855788
}
@@ -5868,7 +5871,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
58685871
}
58695872
if (!zend_jit_isset_isempty_dim(&ctx, opline,
58705873
op1_info, op1_addr, avoid_refcounting,
5871-
op2_info, OP2_REG_ADDR(), val_type,
5874+
op2_info, OP2_REG_ADDR(), OP2_RANGE(), val_type,
58725875
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info),
58735876
smart_branch_opcode, -1, -1,
58745877
exit_addr)) {

0 commit comments

Comments
 (0)