Skip to content

Commit 1ffbb73

Browse files
committed
Better specialization for packed/hash arrays
- improved packed/hash inference. - added hash guards for ASSIGN_DIM, ASSIGN_DIM_OP, FETCH_DIM_W* instructions - more accurate invariant type guards motion - invariant packed/hash guards motion - rename MAY_BE_ARRAY_HASH into MAY_BE_ARRAY_NUMERIC_HASH and add MAY_BE_ARRAY_STRING_HASH - cleanup
1 parent eb6c9eb commit 1ffbb73

File tree

7 files changed

+149
-51
lines changed

7 files changed

+149
-51
lines changed

Zend/Optimizer/zend_dump.c

+13
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,19 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst
239239
}
240240
if (info & MAY_BE_ARRAY) {
241241
if (first) first = 0; else fprintf(stderr, ", ");
242+
if (!(info & MAY_BE_ARRAY_KEY_STRING) || (info & MAY_BE_PACKED_GUARD)) {
243+
if (MAY_BE_PACKED_ONLY(info)) {
244+
if (info & MAY_BE_PACKED_GUARD) {
245+
fprintf(stderr, "!");
246+
}
247+
fprintf(stderr, "packed ");
248+
} else if (MAY_BE_HASH_ONLY(info)) {
249+
if (info & MAY_BE_PACKED_GUARD) {
250+
fprintf(stderr, "!");
251+
}
252+
fprintf(stderr, "hash ");
253+
}
254+
}
242255
fprintf(stderr, "array");
243256
if ((info & MAY_BE_ARRAY_KEY_ANY) != 0 &&
244257
((info & MAY_BE_ARRAY_KEY_LONG) == 0 ||

Zend/Optimizer/zend_inference.c

+16-9
Original file line numberDiff line numberDiff line change
@@ -2107,16 +2107,16 @@ static uint32_t assign_dim_result_type(
21072107
tmp |= MAY_BE_ARRAY_OF_NULL;
21082108
}
21092109
if (dim_op_type == IS_UNUSED) {
2110-
tmp |= MAY_BE_ARRAY_KEY_LONG;
2110+
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
21112111
} else {
21122112
if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
2113-
tmp |= MAY_BE_ARRAY_KEY_LONG;
2113+
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
21142114
}
21152115
if (dim_type & MAY_BE_STRING) {
21162116
tmp |= MAY_BE_ARRAY_KEY_STRING;
21172117
if (dim_op_type != IS_CONST) {
21182118
// FIXME: numeric string
2119-
tmp |= MAY_BE_ARRAY_KEY_LONG;
2119+
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
21202120
}
21212121
}
21222122
if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) {
@@ -3179,6 +3179,13 @@ static zend_always_inline int _zend_update_type_info(
31793179
UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
31803180
}
31813181
if (ssa_op->result_def >= 0) {
3182+
uint32_t arr_type;
3183+
3184+
if (opline->opcode == ZEND_INIT_ARRAY) {
3185+
arr_type = 0;
3186+
} else {
3187+
arr_type = RES_USE_INFO();
3188+
}
31823189
tmp = MAY_BE_RC1|MAY_BE_ARRAY;
31833190
if (ssa_op->result_use >= 0) {
31843191
tmp |= ssa_var_info[ssa_op->result_use].type;
@@ -3192,16 +3199,16 @@ static zend_always_inline int _zend_update_type_info(
31923199
tmp |= MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
31933200
}
31943201
if (opline->op2_type == IS_UNUSED) {
3195-
tmp |= MAY_BE_ARRAY_KEY_LONG;
3202+
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
31963203
} else {
31973204
if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_DOUBLE|MAY_BE_RESOURCE)) {
3198-
tmp |= MAY_BE_ARRAY_KEY_LONG;
3205+
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
31993206
}
32003207
if (t2 & (MAY_BE_STRING)) {
32013208
tmp |= MAY_BE_ARRAY_KEY_STRING;
32023209
if (opline->op2_type != IS_CONST) {
32033210
// FIXME: numeric string
3204-
tmp |= MAY_BE_ARRAY_KEY_LONG;
3211+
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
32053212
}
32063213
}
32073214
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
@@ -3343,16 +3350,16 @@ static zend_always_inline int _zend_update_type_info(
33433350
tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN);
33443351
}
33453352
if (opline->op2_type == IS_UNUSED) {
3346-
key_type |= MAY_BE_ARRAY_KEY_LONG;
3353+
key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
33473354
} else {
33483355
if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
3349-
key_type |= MAY_BE_ARRAY_KEY_LONG;
3356+
key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
33503357
}
33513358
if (t2 & MAY_BE_STRING) {
33523359
key_type |= MAY_BE_ARRAY_KEY_STRING;
33533360
if (opline->op2_type != IS_CONST) {
33543361
// FIXME: numeric string
3355-
key_type |= MAY_BE_ARRAY_KEY_LONG;
3362+
key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
33563363
}
33573364
}
33583365
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {

Zend/Optimizer/zend_inference.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ static zend_always_inline uint32_t _const_op_type(const zval *zv) {
176176
tmp |= 1 << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT);
177177
} ZEND_HASH_FOREACH_END();
178178
if (HT_IS_PACKED(ht)) {
179-
tmp &= ~MAY_BE_ARRAY_HASH;
179+
tmp &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
180180
}
181181
return tmp;
182182
} else {

Zend/zend_type_info.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,18 @@
5858
#define MAY_BE_ARRAY_OF_REF (MAY_BE_REF << MAY_BE_ARRAY_SHIFT)
5959

6060
#define MAY_BE_ARRAY_PACKED (1<<21)
61-
#define MAY_BE_ARRAY_HASH (1<<22) /* hash with numeric keys */
61+
#define MAY_BE_ARRAY_NUMERIC_HASH (1<<22) /* hash with numeric keys */
62+
#define MAY_BE_ARRAY_STRING_HASH (1<<23) /* hash with string keys */
6263

63-
#define MAY_BE_ARRAY_KEY_LONG (MAY_BE_ARRAY_PACKED | MAY_BE_ARRAY_HASH)
64-
#define MAY_BE_ARRAY_KEY_STRING (1<<23)
64+
#define MAY_BE_ARRAY_KEY_LONG (MAY_BE_ARRAY_PACKED | MAY_BE_ARRAY_NUMERIC_HASH)
65+
#define MAY_BE_ARRAY_KEY_STRING MAY_BE_ARRAY_STRING_HASH
6566
#define MAY_BE_ARRAY_KEY_ANY (MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_KEY_STRING)
6667

68+
#define MAY_BE_PACKED(t) ((t) & MAY_BE_ARRAY_PACKED)
69+
#define MAY_BE_HASH(t) ((t) & (MAY_BE_ARRAY_NUMERIC_HASH | MAY_BE_ARRAY_KEY_STRING))
70+
#define MAY_BE_PACKED_ONLY(t) (MAY_BE_PACKED(t) && !MAY_BE_HASH(t))
71+
#define MAY_BE_HASH_ONLY(t) (MAY_BE_HASH(t) && !MAY_BE_PACKED(t))
72+
6773
#define MAY_BE_CLASS (1<<24)
6874
#define MAY_BE_INDIRECT (1<<25)
6975

ext/opcache/jit/zend_jit_arm64.dasc

+7-7
Original file line numberDiff line numberDiff line change
@@ -4923,7 +4923,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
49234923
}
49244924
if (packed_loaded) {
49254925
| // ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
4926-
if (op1_info & MAY_BE_ARRAY_HASH) {
4926+
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
49274927
| ldr TMP1w, [FCARG1x, #offsetof(zend_array, u.flags)]
49284928
| TST_32_WITH_CONST TMP1w, HASH_FLAG_PACKED, TMP2w
49294929
| beq >4 // HASH_FIND
@@ -4968,7 +4968,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
49684968
}
49694969
switch (type) {
49704970
case BP_JIT_IS:
4971-
if (op1_info & MAY_BE_ARRAY_HASH) {
4971+
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
49724972
if (packed_loaded) {
49734973
| b >5
49744974
}
@@ -5001,11 +5001,11 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
50015001
case BP_VAR_IS:
50025002
case BP_VAR_UNSET:
50035003
if (packed_loaded) {
5004-
if (op1_info & MAY_BE_ARRAY_HASH) {
5004+
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
50055005
| IF_NOT_Z_TYPE REG0, IS_UNDEF, >8, TMP1w
50065006
} else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
50075007
/* perform IS_UNDEF check only after result type guard (during deoptimization) */
5008-
if (!found_exit_addr || (op1_info & MAY_BE_ARRAY_HASH)) {
5008+
if (!found_exit_addr || (op1_info & MAY_BE_ARRAY_NUMERIC_HASH)) {
50095009
| IF_Z_TYPE REG0, IS_UNDEF, &exit_addr, TMP1w
50105010
}
50115011
} else if (type == BP_VAR_IS && not_found_exit_addr) {
@@ -5016,7 +5016,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
50165016
| IF_Z_TYPE REG0, IS_UNDEF, >2, TMP1w // NOT_FOUND
50175017
}
50185018
}
5019-
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (packed_loaded && (op1_info & MAY_BE_ARRAY_HASH))) {
5019+
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (packed_loaded && (op1_info & MAY_BE_ARRAY_NUMERIC_HASH))) {
50205020
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
50215021
| b &exit_addr
50225022
} else if (type == BP_VAR_IS && not_found_exit_addr) {
@@ -5027,7 +5027,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
50275027
| b >2 // NOT_FOUND
50285028
}
50295029
}
5030-
if (op1_info & MAY_BE_ARRAY_HASH) {
5030+
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
50315031
|4:
50325032
if (!op2_loaded) {
50335033
| // hval = Z_LVAL_P(dim);
@@ -5088,7 +5088,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
50885088
if (packed_loaded) {
50895089
| IF_NOT_Z_TYPE REG0, IS_UNDEF, >8, TMP1w
50905090
}
5091-
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (op1_info & MAY_BE_ARRAY_HASH) || packed_loaded) {
5091+
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) || packed_loaded) {
50925092
|2:
50935093
|4:
50945094
if (!op2_loaded) {

ext/opcache/jit/zend_jit_trace.c

+96-24
Original file line numberDiff line numberDiff line change
@@ -1587,6 +1587,20 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
15871587
}
15881588
ADD_OP2_TRACE_GUARD();
15891589
}
1590+
if (op1_type == IS_ARRAY
1591+
&& !(orig_op1_type & IS_TRACE_PACKED)
1592+
&& ((opline->op2_type == IS_CONST
1593+
&& Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
1594+
|| (opline->op2_type != IS_CONST
1595+
&& op2_type == IS_LONG))) {
1596+
1597+
zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
1598+
1599+
if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
1600+
info->type |= MAY_BE_PACKED_GUARD;
1601+
info->type &= ~MAY_BE_ARRAY_PACKED;
1602+
}
1603+
}
15901604
break;
15911605
case ZEND_ASSIGN_OBJ_OP:
15921606
if (opline->extended_value == ZEND_POW
@@ -1734,22 +1748,19 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
17341748
ADD_OP1_TRACE_GUARD();
17351749
ADD_OP2_TRACE_GUARD();
17361750

1737-
if (opline->op1_type != IS_CONST
1738-
&& op1_type == IS_ARRAY
1751+
if (op1_type == IS_ARRAY
1752+
&& opline->op1_type != IS_CONST
17391753
&& ((opline->op2_type == IS_CONST
17401754
&& Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
17411755
|| (opline->op2_type != IS_CONST
17421756
&& op2_type == IS_LONG))) {
17431757

17441758
zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
17451759

1746-
if ((info->type & MAY_BE_ARRAY_PACKED)
1747-
&& (info->type & MAY_BE_ARRAY_HASH)
1748-
&& orig_op1_type != IS_UNKNOWN
1749-
&& !(orig_op1_type & IS_TRACE_REFERENCE)) {
1760+
if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
17501761
info->type |= MAY_BE_PACKED_GUARD;
17511762
if (orig_op1_type & IS_TRACE_PACKED) {
1752-
info->type &= ~MAY_BE_ARRAY_HASH;
1763+
info->type &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
17531764
} else {
17541765
info->type &= ~MAY_BE_ARRAY_PACKED;
17551766
}
@@ -1767,6 +1778,20 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
17671778
}
17681779
ADD_OP1_TRACE_GUARD();
17691780
ADD_OP2_TRACE_GUARD();
1781+
if (op1_type == IS_ARRAY
1782+
&& !(orig_op1_type & IS_TRACE_PACKED)
1783+
&& ((opline->op2_type == IS_CONST
1784+
&& Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
1785+
|| (opline->op2_type != IS_CONST
1786+
&& op2_type == IS_LONG))) {
1787+
1788+
zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
1789+
1790+
if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
1791+
info->type |= MAY_BE_PACKED_GUARD;
1792+
info->type &= ~MAY_BE_ARRAY_PACKED;
1793+
}
1794+
}
17701795
break;
17711796
case ZEND_SEND_VAL_EX:
17721797
case ZEND_SEND_VAR_EX:
@@ -2293,35 +2318,80 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
22932318
ssa = &jit_extension->func_info.ssa;
22942319

22952320
while (phi) {
2296-
uint32_t t = ssa_var_info[phi->ssa_var].type;
2297-
uint32_t t0 = ssa_var_info[phi->sources[0]].type;
2298-
uint32_t t1 = ssa_var_info[phi->sources[1]].type;
2321+
uint32_t t = ssa_var_info[phi->ssa_var].type;
22992322

2300-
if (t & MAY_BE_GUARD) {
2301-
if (tssa->vars[phi->ssa_var].alias != NO_ALIAS) {
2302-
/* pass */
2303-
} else if (((t0 | t1) & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
2323+
if ((t & MAY_BE_GUARD) && tssa->vars[phi->ssa_var].alias == NO_ALIAS) {
2324+
uint32_t t0 = ssa_var_info[phi->sources[0]].type;
2325+
uint32_t t1 = ssa_var_info[phi->sources[1]].type;
2326+
2327+
if (((t0 | t1) & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
23042328
if (!((t0 | t1) & MAY_BE_GUARD)) {
23052329
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_GUARD;
23062330
}
23072331
} else if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
23082332
if (!(t1 & MAY_BE_GUARD)
23092333
|| is_checked_guard(tssa, ssa_opcodes, phi->sources[1], phi->ssa_var)) {
23102334
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_GUARD;
2311-
ssa_var_info[phi->sources[0]].type = t | MAY_BE_GUARD;
2335+
t0 = (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
2336+
(t0 & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
2337+
MAY_BE_GUARD;
2338+
if (!(t0 & MAY_BE_ARRAY)) {
2339+
t0 &= ~(MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY);
2340+
}
2341+
if (!(t0 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
2342+
t0 &= ~(MAY_BE_RC1|MAY_BE_RCN);
2343+
}
2344+
ssa_var_info[phi->sources[0]].type = t0;
2345+
ssa_var_info[phi->sources[0]].type = t0;
23122346
}
23132347
} else {
23142348
if ((t0 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
2315-
ssa_var_info[phi->sources[0]].type = MAY_BE_GUARD | (t & t0);
2349+
t0 = (t & t0 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
2350+
(t0 & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
2351+
MAY_BE_GUARD;
2352+
if (!(t0 & MAY_BE_ARRAY)) {
2353+
t0 &= ~(MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY);
2354+
}
2355+
if (!(t0 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
2356+
t0 &= ~(MAY_BE_RC1|MAY_BE_RCN);
2357+
}
2358+
ssa_var_info[phi->sources[0]].type = t0;
23162359
}
23172360
if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
23182361
if (((t & t1) & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != 0
23192362
&& is_checked_guard(tssa, ssa_opcodes, phi->sources[1], phi->ssa_var)) {
2320-
ssa_var_info[phi->sources[1]].type = MAY_BE_GUARD | (t & t1);
2363+
t1 = (t & t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
2364+
(t1 & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
2365+
MAY_BE_GUARD;
2366+
if (!(t1 & MAY_BE_ARRAY)) {
2367+
t1 &= ~(MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY);
2368+
}
2369+
if (!(t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
2370+
t1 &= ~(MAY_BE_RC1|MAY_BE_RCN);
2371+
}
2372+
ssa_var_info[phi->sources[1]].type = t1;
23212373
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_GUARD;
23222374
}
23232375
}
23242376
}
2377+
t = ssa_var_info[phi->ssa_var].type;
2378+
}
2379+
2380+
if ((t & MAY_BE_PACKED_GUARD) && tssa->vars[phi->ssa_var].alias == NO_ALIAS) {
2381+
uint32_t t0 = ssa_var_info[phi->sources[0]].type;
2382+
uint32_t t1 = ssa_var_info[phi->sources[1]].type;
2383+
2384+
if (((t0 | t1) & MAY_BE_ARRAY_KEY_ANY) == (t & MAY_BE_ARRAY_KEY_ANY)) {
2385+
if (!((t0 | t1) & MAY_BE_PACKED_GUARD)) {
2386+
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_PACKED_GUARD;
2387+
}
2388+
} else if ((t1 & MAY_BE_ARRAY_KEY_ANY) == (t & MAY_BE_ARRAY_KEY_ANY)) {
2389+
if (!(t1 & MAY_BE_PACKED_GUARD)) {
2390+
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_PACKED_GUARD;
2391+
ssa_var_info[phi->sources[0]].type =
2392+
(t0 & ~MAY_BE_ARRAY_KEY_ANY) | (t & MAY_BE_ARRAY_KEY_ANY) | MAY_BE_PACKED_GUARD;
2393+
}
2394+
}
23252395
}
23262396
phi = phi->next;
23272397
}
@@ -3825,7 +3895,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
38253895
&& (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
38263896
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
38273897
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET)
3828-
&& ssa->vars[i].use_chain != -1) {
3898+
&& (ssa->vars[i].use_chain != -1
3899+
|| (ssa->vars[i].phi_use_chain
3900+
&& !(ssa->var_info[ssa->vars[i].phi_use_chain->ssa_var].type & MAY_BE_PACKED_GUARD)))) {
38293901
if (!zend_jit_packed_guard(&dasm_state, opline, EX_NUM_TO_VAR(i), info)) {
38303902
goto jit_failure;
38313903
}
@@ -5170,12 +5242,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
51705242
ssa->var_info[ssa_op->op1_use].type &= ~MAY_BE_PACKED_GUARD;
51715243
} else if ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG
51725244
&& (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY
5173-
&& (op1_info & MAY_BE_ARRAY_PACKED)
5174-
&& (op1_info & MAY_BE_ARRAY_HASH)
5245+
&& MAY_BE_PACKED(op1_info)
5246+
&& MAY_BE_HASH(op1_info)
51755247
&& orig_op1_type != IS_UNKNOWN) {
51765248
op1_info |= MAY_BE_PACKED_GUARD;
51775249
if (orig_op1_type & IS_TRACE_PACKED) {
5178-
op1_info &= ~MAY_BE_ARRAY_HASH;
5250+
op1_info &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
51795251
} else {
51805252
op1_info &= ~MAY_BE_ARRAY_PACKED;
51815253
}
@@ -5313,12 +5385,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
53135385
ssa->var_info[ssa_op->op1_use].type &= ~MAY_BE_PACKED_GUARD;
53145386
} else if ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG
53155387
&& (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY
5316-
&& (op1_info & MAY_BE_ARRAY_PACKED)
5317-
&& (op1_info & MAY_BE_ARRAY_HASH)
5388+
&& MAY_BE_PACKED(op1_info)
5389+
&& MAY_BE_HASH(op1_info)
53185390
&& orig_op1_type != IS_UNKNOWN) {
53195391
op1_info |= MAY_BE_PACKED_GUARD;
53205392
if (orig_op1_type & IS_TRACE_PACKED) {
5321-
op1_info &= ~MAY_BE_ARRAY_HASH;
5393+
op1_info &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
53225394
} else {
53235395
op1_info &= ~MAY_BE_ARRAY_PACKED;
53245396
}

0 commit comments

Comments
 (0)