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
This commit is contained in:
Dmitry Stogov 2021-08-13 14:30:41 +03:00
parent eb6c9eb936
commit 1ffbb7372a
7 changed files with 149 additions and 51 deletions

View file

@ -239,6 +239,19 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst
}
if (info & MAY_BE_ARRAY) {
if (first) first = 0; else fprintf(stderr, ", ");
if (!(info & MAY_BE_ARRAY_KEY_STRING) || (info & MAY_BE_PACKED_GUARD)) {
if (MAY_BE_PACKED_ONLY(info)) {
if (info & MAY_BE_PACKED_GUARD) {
fprintf(stderr, "!");
}
fprintf(stderr, "packed ");
} else if (MAY_BE_HASH_ONLY(info)) {
if (info & MAY_BE_PACKED_GUARD) {
fprintf(stderr, "!");
}
fprintf(stderr, "hash ");
}
}
fprintf(stderr, "array");
if ((info & MAY_BE_ARRAY_KEY_ANY) != 0 &&
((info & MAY_BE_ARRAY_KEY_LONG) == 0 ||

View file

@ -2107,16 +2107,16 @@ static uint32_t assign_dim_result_type(
tmp |= MAY_BE_ARRAY_OF_NULL;
}
if (dim_op_type == IS_UNUSED) {
tmp |= MAY_BE_ARRAY_KEY_LONG;
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
} else {
if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
tmp |= MAY_BE_ARRAY_KEY_LONG;
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
}
if (dim_type & MAY_BE_STRING) {
tmp |= MAY_BE_ARRAY_KEY_STRING;
if (dim_op_type != IS_CONST) {
// FIXME: numeric string
tmp |= MAY_BE_ARRAY_KEY_LONG;
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
}
}
if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) {
@ -3179,6 +3179,13 @@ static zend_always_inline int _zend_update_type_info(
UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
}
if (ssa_op->result_def >= 0) {
uint32_t arr_type;
if (opline->opcode == ZEND_INIT_ARRAY) {
arr_type = 0;
} else {
arr_type = RES_USE_INFO();
}
tmp = MAY_BE_RC1|MAY_BE_ARRAY;
if (ssa_op->result_use >= 0) {
tmp |= ssa_var_info[ssa_op->result_use].type;
@ -3192,16 +3199,16 @@ static zend_always_inline int _zend_update_type_info(
tmp |= MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
}
if (opline->op2_type == IS_UNUSED) {
tmp |= MAY_BE_ARRAY_KEY_LONG;
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
} else {
if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_DOUBLE|MAY_BE_RESOURCE)) {
tmp |= MAY_BE_ARRAY_KEY_LONG;
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
}
if (t2 & (MAY_BE_STRING)) {
tmp |= MAY_BE_ARRAY_KEY_STRING;
if (opline->op2_type != IS_CONST) {
// FIXME: numeric string
tmp |= MAY_BE_ARRAY_KEY_LONG;
tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
}
}
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
@ -3343,16 +3350,16 @@ static zend_always_inline int _zend_update_type_info(
tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN);
}
if (opline->op2_type == IS_UNUSED) {
key_type |= MAY_BE_ARRAY_KEY_LONG;
key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
} else {
if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
key_type |= MAY_BE_ARRAY_KEY_LONG;
key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
}
if (t2 & MAY_BE_STRING) {
key_type |= MAY_BE_ARRAY_KEY_STRING;
if (opline->op2_type != IS_CONST) {
// FIXME: numeric string
key_type |= MAY_BE_ARRAY_KEY_LONG;
key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG;
}
}
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {

View file

@ -176,7 +176,7 @@ static zend_always_inline uint32_t _const_op_type(const zval *zv) {
tmp |= 1 << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT);
} ZEND_HASH_FOREACH_END();
if (HT_IS_PACKED(ht)) {
tmp &= ~MAY_BE_ARRAY_HASH;
tmp &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
}
return tmp;
} else {

View file

@ -58,12 +58,18 @@
#define MAY_BE_ARRAY_OF_REF (MAY_BE_REF << MAY_BE_ARRAY_SHIFT)
#define MAY_BE_ARRAY_PACKED (1<<21)
#define MAY_BE_ARRAY_HASH (1<<22) /* hash with numeric keys */
#define MAY_BE_ARRAY_NUMERIC_HASH (1<<22) /* hash with numeric keys */
#define MAY_BE_ARRAY_STRING_HASH (1<<23) /* hash with string keys */
#define MAY_BE_ARRAY_KEY_LONG (MAY_BE_ARRAY_PACKED | MAY_BE_ARRAY_HASH)
#define MAY_BE_ARRAY_KEY_STRING (1<<23)
#define MAY_BE_ARRAY_KEY_LONG (MAY_BE_ARRAY_PACKED | MAY_BE_ARRAY_NUMERIC_HASH)
#define MAY_BE_ARRAY_KEY_STRING MAY_BE_ARRAY_STRING_HASH
#define MAY_BE_ARRAY_KEY_ANY (MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_KEY_STRING)
#define MAY_BE_PACKED(t) ((t) & MAY_BE_ARRAY_PACKED)
#define MAY_BE_HASH(t) ((t) & (MAY_BE_ARRAY_NUMERIC_HASH | MAY_BE_ARRAY_KEY_STRING))
#define MAY_BE_PACKED_ONLY(t) (MAY_BE_PACKED(t) && !MAY_BE_HASH(t))
#define MAY_BE_HASH_ONLY(t) (MAY_BE_HASH(t) && !MAY_BE_PACKED(t))
#define MAY_BE_CLASS (1<<24)
#define MAY_BE_INDIRECT (1<<25)

View file

@ -4923,7 +4923,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
}
if (packed_loaded) {
| // ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
if (op1_info & MAY_BE_ARRAY_HASH) {
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
| ldr TMP1w, [FCARG1x, #offsetof(zend_array, u.flags)]
| TST_32_WITH_CONST TMP1w, HASH_FLAG_PACKED, TMP2w
| beq >4 // HASH_FIND
@ -4968,7 +4968,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
}
switch (type) {
case BP_JIT_IS:
if (op1_info & MAY_BE_ARRAY_HASH) {
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
if (packed_loaded) {
| b >5
}
@ -5001,11 +5001,11 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
case BP_VAR_IS:
case BP_VAR_UNSET:
if (packed_loaded) {
if (op1_info & MAY_BE_ARRAY_HASH) {
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
| IF_NOT_Z_TYPE REG0, IS_UNDEF, >8, TMP1w
} else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
/* perform IS_UNDEF check only after result type guard (during deoptimization) */
if (!found_exit_addr || (op1_info & MAY_BE_ARRAY_HASH)) {
if (!found_exit_addr || (op1_info & MAY_BE_ARRAY_NUMERIC_HASH)) {
| IF_Z_TYPE REG0, IS_UNDEF, &exit_addr, TMP1w
}
} 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
| IF_Z_TYPE REG0, IS_UNDEF, >2, TMP1w // NOT_FOUND
}
}
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (packed_loaded && (op1_info & MAY_BE_ARRAY_HASH))) {
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (packed_loaded && (op1_info & MAY_BE_ARRAY_NUMERIC_HASH))) {
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
| b &exit_addr
} 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
| b >2 // NOT_FOUND
}
}
if (op1_info & MAY_BE_ARRAY_HASH) {
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
|4:
if (!op2_loaded) {
| // hval = Z_LVAL_P(dim);
@ -5088,7 +5088,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
if (packed_loaded) {
| IF_NOT_Z_TYPE REG0, IS_UNDEF, >8, TMP1w
}
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (op1_info & MAY_BE_ARRAY_HASH) || packed_loaded) {
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) || packed_loaded) {
|2:
|4:
if (!op2_loaded) {

View file

@ -1587,6 +1587,20 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
}
ADD_OP2_TRACE_GUARD();
}
if (op1_type == IS_ARRAY
&& !(orig_op1_type & IS_TRACE_PACKED)
&& ((opline->op2_type == IS_CONST
&& Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
|| (opline->op2_type != IS_CONST
&& op2_type == IS_LONG))) {
zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
info->type |= MAY_BE_PACKED_GUARD;
info->type &= ~MAY_BE_ARRAY_PACKED;
}
}
break;
case ZEND_ASSIGN_OBJ_OP:
if (opline->extended_value == ZEND_POW
@ -1734,8 +1748,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
ADD_OP1_TRACE_GUARD();
ADD_OP2_TRACE_GUARD();
if (opline->op1_type != IS_CONST
&& op1_type == IS_ARRAY
if (op1_type == IS_ARRAY
&& opline->op1_type != IS_CONST
&& ((opline->op2_type == IS_CONST
&& Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
|| (opline->op2_type != IS_CONST
@ -1743,13 +1757,10 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
if ((info->type & MAY_BE_ARRAY_PACKED)
&& (info->type & MAY_BE_ARRAY_HASH)
&& orig_op1_type != IS_UNKNOWN
&& !(orig_op1_type & IS_TRACE_REFERENCE)) {
if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
info->type |= MAY_BE_PACKED_GUARD;
if (orig_op1_type & IS_TRACE_PACKED) {
info->type &= ~MAY_BE_ARRAY_HASH;
info->type &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
} else {
info->type &= ~MAY_BE_ARRAY_PACKED;
}
@ -1767,6 +1778,20 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
}
ADD_OP1_TRACE_GUARD();
ADD_OP2_TRACE_GUARD();
if (op1_type == IS_ARRAY
&& !(orig_op1_type & IS_TRACE_PACKED)
&& ((opline->op2_type == IS_CONST
&& Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
|| (opline->op2_type != IS_CONST
&& op2_type == IS_LONG))) {
zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
info->type |= MAY_BE_PACKED_GUARD;
info->type &= ~MAY_BE_ARRAY_PACKED;
}
}
break;
case ZEND_SEND_VAL_EX:
case ZEND_SEND_VAR_EX:
@ -2294,13 +2319,12 @@ propagate_arg:
while (phi) {
uint32_t t = ssa_var_info[phi->ssa_var].type;
if ((t & MAY_BE_GUARD) && tssa->vars[phi->ssa_var].alias == NO_ALIAS) {
uint32_t t0 = ssa_var_info[phi->sources[0]].type;
uint32_t t1 = ssa_var_info[phi->sources[1]].type;
if (t & MAY_BE_GUARD) {
if (tssa->vars[phi->ssa_var].alias != NO_ALIAS) {
/* pass */
} else if (((t0 | t1) & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
if (((t0 | t1) & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
if (!((t0 | t1) & MAY_BE_GUARD)) {
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_GUARD;
}
@ -2308,20 +2332,66 @@ propagate_arg:
if (!(t1 & MAY_BE_GUARD)
|| is_checked_guard(tssa, ssa_opcodes, phi->sources[1], phi->ssa_var)) {
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_GUARD;
ssa_var_info[phi->sources[0]].type = t | MAY_BE_GUARD;
t0 = (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
(t0 & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
MAY_BE_GUARD;
if (!(t0 & MAY_BE_ARRAY)) {
t0 &= ~(MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY);
}
if (!(t0 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
t0 &= ~(MAY_BE_RC1|MAY_BE_RCN);
}
ssa_var_info[phi->sources[0]].type = t0;
ssa_var_info[phi->sources[0]].type = t0;
}
} else {
if ((t0 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
ssa_var_info[phi->sources[0]].type = MAY_BE_GUARD | (t & t0);
t0 = (t & t0 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
(t0 & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
MAY_BE_GUARD;
if (!(t0 & MAY_BE_ARRAY)) {
t0 &= ~(MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY);
}
if (!(t0 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
t0 &= ~(MAY_BE_RC1|MAY_BE_RCN);
}
ssa_var_info[phi->sources[0]].type = t0;
}
if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
if (((t & t1) & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != 0
&& is_checked_guard(tssa, ssa_opcodes, phi->sources[1], phi->ssa_var)) {
ssa_var_info[phi->sources[1]].type = MAY_BE_GUARD | (t & t1);
t1 = (t & t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
(t1 & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) |
MAY_BE_GUARD;
if (!(t1 & MAY_BE_ARRAY)) {
t1 &= ~(MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY);
}
if (!(t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
t1 &= ~(MAY_BE_RC1|MAY_BE_RCN);
}
ssa_var_info[phi->sources[1]].type = t1;
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_GUARD;
}
}
}
t = ssa_var_info[phi->ssa_var].type;
}
if ((t & MAY_BE_PACKED_GUARD) && tssa->vars[phi->ssa_var].alias == NO_ALIAS) {
uint32_t t0 = ssa_var_info[phi->sources[0]].type;
uint32_t t1 = ssa_var_info[phi->sources[1]].type;
if (((t0 | t1) & MAY_BE_ARRAY_KEY_ANY) == (t & MAY_BE_ARRAY_KEY_ANY)) {
if (!((t0 | t1) & MAY_BE_PACKED_GUARD)) {
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_PACKED_GUARD;
}
} else if ((t1 & MAY_BE_ARRAY_KEY_ANY) == (t & MAY_BE_ARRAY_KEY_ANY)) {
if (!(t1 & MAY_BE_PACKED_GUARD)) {
ssa_var_info[phi->ssa_var].type = t & ~MAY_BE_PACKED_GUARD;
ssa_var_info[phi->sources[0]].type =
(t0 & ~MAY_BE_ARRAY_KEY_ANY) | (t & MAY_BE_ARRAY_KEY_ANY) | MAY_BE_PACKED_GUARD;
}
}
}
phi = phi->next;
}
@ -3825,7 +3895,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
&& (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET)
&& ssa->vars[i].use_chain != -1) {
&& (ssa->vars[i].use_chain != -1
|| (ssa->vars[i].phi_use_chain
&& !(ssa->var_info[ssa->vars[i].phi_use_chain->ssa_var].type & MAY_BE_PACKED_GUARD)))) {
if (!zend_jit_packed_guard(&dasm_state, opline, EX_NUM_TO_VAR(i), info)) {
goto jit_failure;
}
@ -5170,12 +5242,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
ssa->var_info[ssa_op->op1_use].type &= ~MAY_BE_PACKED_GUARD;
} else if ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG
&& (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY
&& (op1_info & MAY_BE_ARRAY_PACKED)
&& (op1_info & MAY_BE_ARRAY_HASH)
&& MAY_BE_PACKED(op1_info)
&& MAY_BE_HASH(op1_info)
&& orig_op1_type != IS_UNKNOWN) {
op1_info |= MAY_BE_PACKED_GUARD;
if (orig_op1_type & IS_TRACE_PACKED) {
op1_info &= ~MAY_BE_ARRAY_HASH;
op1_info &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
} else {
op1_info &= ~MAY_BE_ARRAY_PACKED;
}
@ -5313,12 +5385,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
ssa->var_info[ssa_op->op1_use].type &= ~MAY_BE_PACKED_GUARD;
} else if ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG
&& (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY
&& (op1_info & MAY_BE_ARRAY_PACKED)
&& (op1_info & MAY_BE_ARRAY_HASH)
&& MAY_BE_PACKED(op1_info)
&& MAY_BE_HASH(op1_info)
&& orig_op1_type != IS_UNKNOWN) {
op1_info |= MAY_BE_PACKED_GUARD;
if (orig_op1_type & IS_TRACE_PACKED) {
op1_info &= ~MAY_BE_ARRAY_HASH;
op1_info &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
} else {
op1_info &= ~MAY_BE_ARRAY_PACKED;
}

View file

@ -5381,7 +5381,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
}
if (packed_loaded) {
| // ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
if (op1_info & MAY_BE_ARRAY_HASH) {
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
| test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED
| jz >4 // HASH_FIND
}
@ -5436,7 +5436,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
}
switch (type) {
case BP_JIT_IS:
if (op1_info & MAY_BE_ARRAY_HASH) {
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
if (packed_loaded) {
| jmp >5
}
@ -5469,11 +5469,11 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
case BP_VAR_IS:
case BP_VAR_UNSET:
if (packed_loaded) {
if (op1_info & MAY_BE_ARRAY_HASH) {
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
| IF_NOT_Z_TYPE r0, IS_UNDEF, >8
} else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
/* perform IS_UNDEF check only after result type guard (during deoptimization) */
if (!found_exit_addr || (op1_info & MAY_BE_ARRAY_HASH)) {
if (!found_exit_addr || (op1_info & MAY_BE_ARRAY_NUMERIC_HASH)) {
| IF_Z_TYPE r0, IS_UNDEF, &exit_addr
}
} else if (type == BP_VAR_IS && not_found_exit_addr) {
@ -5484,7 +5484,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
| IF_Z_TYPE r0, IS_UNDEF, >2 // NOT_FOUND
}
}
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (packed_loaded && (op1_info & MAY_BE_ARRAY_HASH))) {
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (packed_loaded && (op1_info & MAY_BE_ARRAY_NUMERIC_HASH))) {
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
| jmp &exit_addr
} else if (type == BP_VAR_IS && not_found_exit_addr) {
@ -5495,7 +5495,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
| jmp >2 // NOT_FOUND
}
}
if (op1_info & MAY_BE_ARRAY_HASH) {
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
|4:
if (!op2_loaded) {
| // hval = Z_LVAL_P(dim);
@ -5556,7 +5556,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
if (packed_loaded) {
| IF_NOT_Z_TYPE r0, IS_UNDEF, >8
}
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (op1_info & MAY_BE_ARRAY_HASH) || packed_loaded) {
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) || packed_loaded) {
|2:
|4:
if (!op2_loaded) {