mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
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:
parent
eb6c9eb936
commit
1ffbb7372a
7 changed files with 149 additions and 51 deletions
|
@ -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 (info & MAY_BE_ARRAY) {
|
||||||
if (first) first = 0; else fprintf(stderr, ", ");
|
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");
|
fprintf(stderr, "array");
|
||||||
if ((info & MAY_BE_ARRAY_KEY_ANY) != 0 &&
|
if ((info & MAY_BE_ARRAY_KEY_ANY) != 0 &&
|
||||||
((info & MAY_BE_ARRAY_KEY_LONG) == 0 ||
|
((info & MAY_BE_ARRAY_KEY_LONG) == 0 ||
|
||||||
|
|
|
@ -2107,16 +2107,16 @@ static uint32_t assign_dim_result_type(
|
||||||
tmp |= MAY_BE_ARRAY_OF_NULL;
|
tmp |= MAY_BE_ARRAY_OF_NULL;
|
||||||
}
|
}
|
||||||
if (dim_op_type == IS_UNUSED) {
|
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 {
|
} else {
|
||||||
if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
|
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) {
|
if (dim_type & MAY_BE_STRING) {
|
||||||
tmp |= MAY_BE_ARRAY_KEY_STRING;
|
tmp |= MAY_BE_ARRAY_KEY_STRING;
|
||||||
if (dim_op_type != IS_CONST) {
|
if (dim_op_type != IS_CONST) {
|
||||||
// FIXME: numeric string
|
// 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)) {
|
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);
|
UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
|
||||||
}
|
}
|
||||||
if (ssa_op->result_def >= 0) {
|
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;
|
tmp = MAY_BE_RC1|MAY_BE_ARRAY;
|
||||||
if (ssa_op->result_use >= 0) {
|
if (ssa_op->result_use >= 0) {
|
||||||
tmp |= ssa_var_info[ssa_op->result_use].type;
|
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;
|
tmp |= MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
|
||||||
}
|
}
|
||||||
if (opline->op2_type == IS_UNUSED) {
|
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 {
|
} else {
|
||||||
if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_DOUBLE|MAY_BE_RESOURCE)) {
|
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)) {
|
if (t2 & (MAY_BE_STRING)) {
|
||||||
tmp |= MAY_BE_ARRAY_KEY_STRING;
|
tmp |= MAY_BE_ARRAY_KEY_STRING;
|
||||||
if (opline->op2_type != IS_CONST) {
|
if (opline->op2_type != IS_CONST) {
|
||||||
// FIXME: numeric string
|
// 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)) {
|
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);
|
tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN);
|
||||||
}
|
}
|
||||||
if (opline->op2_type == IS_UNUSED) {
|
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 {
|
} else {
|
||||||
if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
|
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) {
|
if (t2 & MAY_BE_STRING) {
|
||||||
key_type |= MAY_BE_ARRAY_KEY_STRING;
|
key_type |= MAY_BE_ARRAY_KEY_STRING;
|
||||||
if (opline->op2_type != IS_CONST) {
|
if (opline->op2_type != IS_CONST) {
|
||||||
// FIXME: numeric string
|
// 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)) {
|
if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
|
||||||
|
|
|
@ -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);
|
tmp |= 1 << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT);
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
if (HT_IS_PACKED(ht)) {
|
if (HT_IS_PACKED(ht)) {
|
||||||
tmp &= ~MAY_BE_ARRAY_HASH;
|
tmp &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
|
||||||
}
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -58,12 +58,18 @@
|
||||||
#define MAY_BE_ARRAY_OF_REF (MAY_BE_REF << MAY_BE_ARRAY_SHIFT)
|
#define MAY_BE_ARRAY_OF_REF (MAY_BE_REF << MAY_BE_ARRAY_SHIFT)
|
||||||
|
|
||||||
#define MAY_BE_ARRAY_PACKED (1<<21)
|
#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_LONG (MAY_BE_ARRAY_PACKED | MAY_BE_ARRAY_NUMERIC_HASH)
|
||||||
#define MAY_BE_ARRAY_KEY_STRING (1<<23)
|
#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_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_CLASS (1<<24)
|
||||||
#define MAY_BE_INDIRECT (1<<25)
|
#define MAY_BE_INDIRECT (1<<25)
|
||||||
|
|
||||||
|
|
|
@ -4923,7 +4923,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
|
||||||
}
|
}
|
||||||
if (packed_loaded) {
|
if (packed_loaded) {
|
||||||
| // ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
|
| // 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)]
|
| ldr TMP1w, [FCARG1x, #offsetof(zend_array, u.flags)]
|
||||||
| TST_32_WITH_CONST TMP1w, HASH_FLAG_PACKED, TMP2w
|
| TST_32_WITH_CONST TMP1w, HASH_FLAG_PACKED, TMP2w
|
||||||
| beq >4 // HASH_FIND
|
| beq >4 // HASH_FIND
|
||||||
|
@ -4968,7 +4968,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BP_JIT_IS:
|
case BP_JIT_IS:
|
||||||
if (op1_info & MAY_BE_ARRAY_HASH) {
|
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
|
||||||
if (packed_loaded) {
|
if (packed_loaded) {
|
||||||
| b >5
|
| 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_IS:
|
||||||
case BP_VAR_UNSET:
|
case BP_VAR_UNSET:
|
||||||
if (packed_loaded) {
|
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
|
| IF_NOT_Z_TYPE REG0, IS_UNDEF, >8, TMP1w
|
||||||
} else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
|
} 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) */
|
/* 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
|
| IF_Z_TYPE REG0, IS_UNDEF, &exit_addr, TMP1w
|
||||||
}
|
}
|
||||||
} else if (type == BP_VAR_IS && not_found_exit_addr) {
|
} 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_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) {
|
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
|
||||||
| b &exit_addr
|
| b &exit_addr
|
||||||
} else if (type == BP_VAR_IS && not_found_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
|
| b >2 // NOT_FOUND
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (op1_info & MAY_BE_ARRAY_HASH) {
|
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
|
||||||
|4:
|
|4:
|
||||||
if (!op2_loaded) {
|
if (!op2_loaded) {
|
||||||
| // hval = Z_LVAL_P(dim);
|
| // 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 (packed_loaded) {
|
||||||
| IF_NOT_Z_TYPE REG0, IS_UNDEF, >8, TMP1w
|
| 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:
|
|2:
|
||||||
|4:
|
|4:
|
||||||
if (!op2_loaded) {
|
if (!op2_loaded) {
|
||||||
|
|
|
@ -1587,6 +1587,20 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
|
||||||
}
|
}
|
||||||
ADD_OP2_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;
|
break;
|
||||||
case ZEND_ASSIGN_OBJ_OP:
|
case ZEND_ASSIGN_OBJ_OP:
|
||||||
if (opline->extended_value == ZEND_POW
|
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_OP1_TRACE_GUARD();
|
||||||
ADD_OP2_TRACE_GUARD();
|
ADD_OP2_TRACE_GUARD();
|
||||||
|
|
||||||
if (opline->op1_type != IS_CONST
|
if (op1_type == IS_ARRAY
|
||||||
&& op1_type == IS_ARRAY
|
&& opline->op1_type != IS_CONST
|
||||||
&& ((opline->op2_type == IS_CONST
|
&& ((opline->op2_type == IS_CONST
|
||||||
&& Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
|
&& Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG)
|
||||||
|| (opline->op2_type != IS_CONST
|
|| (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];
|
zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
|
||||||
|
|
||||||
if ((info->type & MAY_BE_ARRAY_PACKED)
|
if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
|
||||||
&& (info->type & MAY_BE_ARRAY_HASH)
|
|
||||||
&& orig_op1_type != IS_UNKNOWN
|
|
||||||
&& !(orig_op1_type & IS_TRACE_REFERENCE)) {
|
|
||||||
info->type |= MAY_BE_PACKED_GUARD;
|
info->type |= MAY_BE_PACKED_GUARD;
|
||||||
if (orig_op1_type & IS_TRACE_PACKED) {
|
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 {
|
} else {
|
||||||
info->type &= ~MAY_BE_ARRAY_PACKED;
|
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_OP1_TRACE_GUARD();
|
||||||
ADD_OP2_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;
|
break;
|
||||||
case ZEND_SEND_VAL_EX:
|
case ZEND_SEND_VAL_EX:
|
||||||
case ZEND_SEND_VAR_EX:
|
case ZEND_SEND_VAR_EX:
|
||||||
|
@ -2294,13 +2319,12 @@ propagate_arg:
|
||||||
|
|
||||||
while (phi) {
|
while (phi) {
|
||||||
uint32_t t = ssa_var_info[phi->ssa_var].type;
|
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 t0 = ssa_var_info[phi->sources[0]].type;
|
||||||
uint32_t t1 = ssa_var_info[phi->sources[1]].type;
|
uint32_t t1 = ssa_var_info[phi->sources[1]].type;
|
||||||
|
|
||||||
if (t & MAY_BE_GUARD) {
|
if (((t0 | t1) & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
|
||||||
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_GUARD)) {
|
if (!((t0 | t1) & MAY_BE_GUARD)) {
|
||||||
ssa_var_info[phi->ssa_var].type = t & ~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)
|
if (!(t1 & MAY_BE_GUARD)
|
||||||
|| is_checked_guard(tssa, ssa_opcodes, phi->sources[1], phi->ssa_var)) {
|
|| 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->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 {
|
} else {
|
||||||
if ((t0 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != (t & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF))) {
|
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 ((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
|
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)) {
|
&& 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;
|
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;
|
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_LOOP
|
||||||
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
|
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
|
||||||
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET)
|
|| 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)) {
|
if (!zend_jit_packed_guard(&dasm_state, opline, EX_NUM_TO_VAR(i), info)) {
|
||||||
goto jit_failure;
|
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;
|
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
|
} 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_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY
|
||||||
&& (op1_info & MAY_BE_ARRAY_PACKED)
|
&& MAY_BE_PACKED(op1_info)
|
||||||
&& (op1_info & MAY_BE_ARRAY_HASH)
|
&& MAY_BE_HASH(op1_info)
|
||||||
&& orig_op1_type != IS_UNKNOWN) {
|
&& orig_op1_type != IS_UNKNOWN) {
|
||||||
op1_info |= MAY_BE_PACKED_GUARD;
|
op1_info |= MAY_BE_PACKED_GUARD;
|
||||||
if (orig_op1_type & IS_TRACE_PACKED) {
|
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 {
|
} else {
|
||||||
op1_info &= ~MAY_BE_ARRAY_PACKED;
|
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;
|
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
|
} 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_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY
|
||||||
&& (op1_info & MAY_BE_ARRAY_PACKED)
|
&& MAY_BE_PACKED(op1_info)
|
||||||
&& (op1_info & MAY_BE_ARRAY_HASH)
|
&& MAY_BE_HASH(op1_info)
|
||||||
&& orig_op1_type != IS_UNKNOWN) {
|
&& orig_op1_type != IS_UNKNOWN) {
|
||||||
op1_info |= MAY_BE_PACKED_GUARD;
|
op1_info |= MAY_BE_PACKED_GUARD;
|
||||||
if (orig_op1_type & IS_TRACE_PACKED) {
|
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 {
|
} else {
|
||||||
op1_info &= ~MAY_BE_ARRAY_PACKED;
|
op1_info &= ~MAY_BE_ARRAY_PACKED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5381,7 +5381,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
|
||||||
}
|
}
|
||||||
if (packed_loaded) {
|
if (packed_loaded) {
|
||||||
| // ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
|
| // 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
|
| test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED
|
||||||
| jz >4 // HASH_FIND
|
| jz >4 // HASH_FIND
|
||||||
}
|
}
|
||||||
|
@ -5436,7 +5436,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BP_JIT_IS:
|
case BP_JIT_IS:
|
||||||
if (op1_info & MAY_BE_ARRAY_HASH) {
|
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
|
||||||
if (packed_loaded) {
|
if (packed_loaded) {
|
||||||
| jmp >5
|
| 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_IS:
|
||||||
case BP_VAR_UNSET:
|
case BP_VAR_UNSET:
|
||||||
if (packed_loaded) {
|
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
|
| IF_NOT_Z_TYPE r0, IS_UNDEF, >8
|
||||||
} else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
|
} 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) */
|
/* 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
|
| IF_Z_TYPE r0, IS_UNDEF, &exit_addr
|
||||||
}
|
}
|
||||||
} else if (type == BP_VAR_IS && not_found_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_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) {
|
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
|
||||||
| jmp &exit_addr
|
| jmp &exit_addr
|
||||||
} else if (type == BP_VAR_IS && not_found_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
|
| jmp >2 // NOT_FOUND
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (op1_info & MAY_BE_ARRAY_HASH) {
|
if (op1_info & MAY_BE_ARRAY_NUMERIC_HASH) {
|
||||||
|4:
|
|4:
|
||||||
if (!op2_loaded) {
|
if (!op2_loaded) {
|
||||||
| // hval = Z_LVAL_P(dim);
|
| // 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 (packed_loaded) {
|
||||||
| IF_NOT_Z_TYPE r0, IS_UNDEF, >8
|
| 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:
|
|2:
|
||||||
|4:
|
|4:
|
||||||
if (!op2_loaded) {
|
if (!op2_loaded) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue