diff options
-rw-r--r-- | ext/opcache/Optimizer/zend_dump.c | 10 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_inference.c | 19 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_ssa.h | 4 |
3 files changed, 23 insertions, 10 deletions
diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index d224000066..ba5fb8a0ce 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -182,11 +182,13 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst if (first) first = 0; else fprintf(stderr, ", "); fprintf(stderr, "null"); } - if (info & MAY_BE_FALSE) { + if ((info & MAY_BE_FALSE) && (info & MAY_BE_TRUE)) { + if (first) first = 0; else fprintf(stderr, ", "); + fprintf(stderr, "bool"); + } else if (info & MAY_BE_FALSE) { if (first) first = 0; else fprintf(stderr, ", "); fprintf(stderr, "false"); - } - if (info & MAY_BE_TRUE) { + } else if (info & MAY_BE_TRUE) { if (first) first = 0; else fprintf(stderr, ", "); fprintf(stderr, "true"); } @@ -788,7 +790,7 @@ static void zend_dump_block_header(const zend_cfg *cfg, const zend_op_array *op_ } fprintf(stderr, ")\n"); } else { - fprintf(stderr, " = Pi("); + fprintf(stderr, " = Pi<BB%d>(", p->pi); zend_dump_ssa_var(op_array, ssa, p->sources[0], 0, p->var, dump_flags); fprintf(stderr, " &"); zend_dump_pi_constraint(op_array, ssa, &p->constraint, dump_flags); diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index affdaf7aac..a1e2335fa9 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -962,7 +962,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int op2_max = OP2_MAX_RANGE(); tmp->min = (op1_min == op1_max && - op2_min == op2_min && + op2_min == op2_max && op1_min == op2_max); tmp->max = (op1_min <= op2_max && op1_max >= op2_min); return 1; @@ -984,7 +984,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int tmp->min = (op1_min > op2_max || op1_max < op2_min); tmp->max = (op1_min != op1_max || - op2_min != op2_min || + op2_min != op2_max || op1_min != op2_max); return 1; } else { @@ -2359,6 +2359,14 @@ static void zend_update_type_info(const zend_op_array *op_array, if (opline->op1_type & (IS_CV|IS_VAR)) { tmp |= MAY_BE_RCN; } + if (opline->opcode != ZEND_QM_ASSIGN) { + /* COALESCE and JMP_SET result can't be null */ + tmp &= ~MAY_BE_NULL; + if (opline->opcode == ZEND_JMP_SET) { + /* JMP_SET result can't be false either */ + tmp &= ~MAY_BE_FALSE; + } + } UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def); if ((t1 & MAY_BE_OBJECT) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) { UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].result_def); @@ -3438,6 +3446,7 @@ static void zend_update_type_info(const zend_op_array *op_array, case ZEND_FETCH_DIM_W: case ZEND_FETCH_DIM_UNSET: case ZEND_FETCH_DIM_FUNC_ARG: + case ZEND_FETCH_LIST: if (ssa_ops[i].op1_def >= 0) { tmp = t1; if (opline->opcode == ZEND_FETCH_DIM_W || @@ -3520,9 +3529,11 @@ static void zend_update_type_info(const zend_op_array *op_array, UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].op1_def); } } + /* FETCH_LIST on a string behaves like FETCH_R on null */ tmp = zend_array_element_type( - t1, - (opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS), + opline->opcode != ZEND_FETCH_LIST ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL), + opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS + && opline->opcode != ZEND_FETCH_LIST, opline->op2_type == IS_UNUSED); if (opline->opcode == ZEND_FETCH_DIM_W || opline->opcode == ZEND_FETCH_DIM_RW || diff --git a/ext/opcache/Optimizer/zend_ssa.h b/ext/opcache/Optimizer/zend_ssa.h index 00d6875dfd..dbf260c4d8 100644 --- a/ext/opcache/Optimizer/zend_ssa.h +++ b/ext/opcache/Optimizer/zend_ssa.h @@ -122,7 +122,7 @@ int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var); END_EXTERN_C() -static zend_always_inline int zend_ssa_next_use(zend_ssa_op *ssa_op, int var, int use) +static zend_always_inline int zend_ssa_next_use(const zend_ssa_op *ssa_op, int var, int use) { ssa_op += use; if (ssa_op->result_use == var) { @@ -131,7 +131,7 @@ static zend_always_inline int zend_ssa_next_use(zend_ssa_op *ssa_op, int var, in return (ssa_op->op1_use == var) ? ssa_op->op1_use_chain : ssa_op->op2_use_chain; } -static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(zend_ssa *ssa, int var, zend_ssa_phi *p) +static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(const zend_ssa *ssa, int var, const zend_ssa_phi *p) { if (p->pi >= 0) { return p->use_chains[0]; |