diff options
Diffstat (limited to 'ext/opcache')
-rw-r--r-- | ext/opcache/Optimizer/block_pass.c | 16 | ||||
-rw-r--r-- | ext/opcache/Optimizer/compact_literals.c | 112 | ||||
-rw-r--r-- | ext/opcache/Optimizer/dce.c | 32 | ||||
-rw-r--r-- | ext/opcache/Optimizer/dfa_pass.c | 30 | ||||
-rw-r--r-- | ext/opcache/Optimizer/escape_analysis.c | 38 | ||||
-rw-r--r-- | ext/opcache/Optimizer/pass2.c | 55 | ||||
-rw-r--r-- | ext/opcache/Optimizer/pass3.c | 43 | ||||
-rw-r--r-- | ext/opcache/Optimizer/sccp.c | 86 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_dfg.c | 16 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_dump.c | 10 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_inference.c | 211 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 79 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer_internal.h | 1 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_ssa.c | 16 |
14 files changed, 224 insertions, 521 deletions
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index a635c55571..e5f12dfa32 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -1723,18 +1723,10 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use if (opline->result_type == IS_VAR) { if (!zend_bitset_in(usage, VAR_NUM(opline->result.var))) { switch (opline->opcode) { - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_POW: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_PRE_INC: case ZEND_PRE_DEC: case ZEND_ASSIGN: diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c index 6c5512fd72..0078600b52 100644 --- a/ext/opcache/Optimizer/compact_literals.c +++ b/ext/opcache/Optimizer/compact_literals.c @@ -197,7 +197,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx case ZEND_PRE_DEC_STATIC_PROP: case ZEND_POST_INC_STATIC_PROP: case ZEND_POST_DEC_STATIC_PROP: -literals_handle_static_prop: + case ZEND_ASSIGN_STATIC_PROP_OP: if (opline->op2_type == IS_CONST) { LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 2); } @@ -230,39 +230,11 @@ literals_handle_static_prop: case ZEND_POST_INC_OBJ: case ZEND_POST_DEC_OBJ: case ZEND_ISSET_ISEMPTY_PROP_OBJ: + case ZEND_ASSIGN_OBJ_OP: if (opline->op2_type == IS_CONST) { LITERAL_INFO(opline->op2.constant, LITERAL_PROPERTY, 1); } break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_POW: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) { - goto literals_handle_static_prop; - } - if (opline->op2_type == IS_CONST) { - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - LITERAL_INFO(opline->op2.constant, LITERAL_PROPERTY, 1); - } else if (opline->extended_value == ZEND_ASSIGN_DIM) { - if (Z_EXTRA(op_array->literals[opline->op2.constant]) == ZEND_EXTRA_VALUE) { - LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 2); - } else { - LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); - } - } else { - LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); - } - } - break; case ZEND_BIND_GLOBAL: LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 1); break; @@ -290,6 +262,7 @@ literals_handle_static_prop: case ZEND_FETCH_DIM_UNSET: case ZEND_FETCH_LIST_R: case ZEND_FETCH_LIST_W: + case ZEND_ASSIGN_DIM_OP: if (opline->op1_type == IS_CONST) { LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1); } @@ -548,54 +521,41 @@ literals_handle_static_prop: cache_size += sizeof(void *); } break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_POW: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) { - if (opline->op1_type == IS_CONST) { - // op1 static property - if (opline->op2_type == IS_CONST) { - (opline+1)->extended_value = add_static_slot(&hash, op_array, - opline->op2.constant, - opline->op1.constant, - LITERAL_STATIC_PROPERTY, - &cache_size); - } else { - (opline+1)->extended_value = cache_size; - cache_size += 3 * sizeof(void *); - } - } else if (opline->op2_type == IS_CONST) { - // op2 class - if (class_slot[opline->op2.constant] >= 0) { - (opline+1)->extended_value = class_slot[opline->op2.constant]; - } else { - (opline+1)->extended_value = cache_size; - class_slot[opline->op2.constant] = cache_size; - cache_size += sizeof(void *); - } + case ZEND_ASSIGN_STATIC_PROP_OP: + if (opline->op1_type == IS_CONST) { + // op1 static property + if (opline->op2_type == IS_CONST) { + (opline+1)->extended_value = add_static_slot(&hash, op_array, + opline->op2.constant, + opline->op1.constant, + LITERAL_STATIC_PROPERTY, + &cache_size); + } else { + (opline+1)->extended_value = cache_size; + cache_size += 3 * sizeof(void *); + } + } else if (opline->op2_type == IS_CONST) { + // op2 class + if (class_slot[opline->op2.constant] >= 0) { + (opline+1)->extended_value = class_slot[opline->op2.constant]; + } else { + (opline+1)->extended_value = cache_size; + class_slot[opline->op2.constant] = cache_size; + cache_size += sizeof(void *); } } - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - if (opline->op2_type == IS_CONST) { - // op2 property - if (opline->op1_type == IS_UNUSED && - property_slot[opline->op2.constant] >= 0) { - (opline+1)->extended_value = property_slot[opline->op2.constant]; - } else { - (opline+1)->extended_value = cache_size; - cache_size += 3 * sizeof(void *); - if (opline->op1_type == IS_UNUSED) { - property_slot[opline->op2.constant] = (opline+1)->extended_value; - } + break; + case ZEND_ASSIGN_OBJ_OP: + if (opline->op2_type == IS_CONST) { + // op2 property + if (opline->op1_type == IS_UNUSED && + property_slot[opline->op2.constant] >= 0) { + (opline+1)->extended_value = property_slot[opline->op2.constant]; + } else { + (opline+1)->extended_value = cache_size; + cache_size += 3 * sizeof(void *); + if (opline->op1_type == IS_UNUSED) { + property_slot[opline->op2.constant] = (opline+1)->extended_value; } } } diff --git a/ext/opcache/Optimizer/dce.c b/ext/opcache/Optimizer/dce.c index c9ef7111ca..8370bdc779 100644 --- a/ext/opcache/Optimizer/dce.c +++ b/ext/opcache/Optimizer/dce.c @@ -201,21 +201,9 @@ static inline zend_bool may_have_side_effects( case ZEND_PRE_DEC: case ZEND_POST_DEC: return is_bad_mod(ssa, ssa_op->op1_use, ssa_op->op1_def); - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: + case ZEND_ASSIGN_OP: return is_bad_mod(ssa, ssa_op->op1_use, ssa_op->op1_def) - || (opline->extended_value - && ssa->vars[ssa_op->op1_def].escape_state != ESCAPE_STATE_NO_ESCAPE); + || ssa->vars[ssa_op->op1_def].escape_state != ESCAPE_STATE_NO_ESCAPE; case ZEND_ASSIGN_DIM: case ZEND_ASSIGN_OBJ: if (is_bad_mod(ssa, ssa_op->op1_use, ssa_op->op1_def) @@ -349,18 +337,10 @@ static zend_bool try_remove_var_def(context *ctx, int free_var, int use_chain, z case ZEND_ASSIGN_OBJ_REF: case ZEND_ASSIGN_STATIC_PROP: case ZEND_ASSIGN_STATIC_PROP_REF: - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_PRE_INC: case ZEND_PRE_DEC: case ZEND_PRE_INC_OBJ: diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index c9528918e3..b0d58f9566 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -1180,8 +1180,8 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx } } - } else if (opline->opcode == ZEND_ASSIGN_ADD - && opline->extended_value == 0 + } else if (opline->opcode == ZEND_ASSIGN_OP + && opline->extended_value == ZEND_ADD && ssa->ops[op_1].op1_def == v && opline->op2_type == IS_CONST && Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) == IS_LONG @@ -1192,10 +1192,11 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx // op_1: ASSIGN_ADD #?.CV [undef,null,int,foat] ->#v.CV, int(1) => PRE_INC #?.CV ->#v.CV opline->opcode = ZEND_PRE_INC; + opline->extended_value = 0; SET_UNUSED(opline->op2); - } else if (opline->opcode == ZEND_ASSIGN_SUB - && opline->extended_value == 0 + } else if (opline->opcode == ZEND_ASSIGN_OP + && opline->extended_value == ZEND_SUB && ssa->ops[op_1].op1_def == v && opline->op2_type == IS_CONST && Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) == IS_LONG @@ -1206,6 +1207,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx // op_1: ASSIGN_SUB #?.CV [undef,null,int,foat] -> #v.CV, int(1) => PRE_DEC #?.CV ->#v.CV opline->opcode = ZEND_PRE_DEC; + opline->extended_value = 0; SET_UNUSED(opline->op2); } else if (opline->opcode == ZEND_VERIFY_RETURN_TYPE @@ -1240,26 +1242,18 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx && !RETURN_VALUE_USED(opline) && ssa->ops[op_1].op1_use >= 0 && !(ssa->var_info[ssa->ops[op_1].op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) - && (opline->opcode == ZEND_ASSIGN_ADD - || opline->opcode == ZEND_ASSIGN_SUB - || opline->opcode == ZEND_ASSIGN_MUL - || opline->opcode == ZEND_ASSIGN_DIV - || opline->opcode == ZEND_ASSIGN_MOD - || opline->opcode == ZEND_ASSIGN_SL - || opline->opcode == ZEND_ASSIGN_SR - || opline->opcode == ZEND_ASSIGN_BW_OR - || opline->opcode == ZEND_ASSIGN_BW_AND - || opline->opcode == ZEND_ASSIGN_BW_XOR) - && opline->extended_value == 0) { - -// op_1: ASSIGN_ADD #orig_var.CV [undef,null,bool,int,double] -> #v.CV, ? => #v.CV = ADD #orig_var.CV, ? + && opline->opcode == ZEND_ASSIGN_OP + && opline->extended_value != ZEND_CONCAT) { + +// op_1: ASSIGN_OP #orig_var.CV [undef,null,bool,int,double] -> #v.CV, ? => #v.CV = ADD #orig_var.CV, ? /* Reconstruct SSA */ ssa->ops[op_1].result_def = ssa->ops[op_1].op1_def; ssa->ops[op_1].op1_def = -1; /* Update opcode */ - opline->opcode -= (ZEND_ASSIGN_ADD - ZEND_ADD); + opline->opcode = opline->extended_value; + opline->extended_value = 0; opline->result_type = opline->op1_type; opline->result.var = opline->op1.var; diff --git a/ext/opcache/Optimizer/escape_analysis.c b/ext/opcache/Optimizer/escape_analysis.c index 948feeef84..c561bec9dc 100644 --- a/ext/opcache/Optimizer/escape_analysis.c +++ b/ext/opcache/Optimizer/escape_analysis.c @@ -257,24 +257,11 @@ static int is_local_def(zend_op_array *op_array, zend_ssa *ssa, int def, int var } else if (op->op1_def == var) { switch (opline->opcode) { case ZEND_ASSIGN: - return 1; case ZEND_ASSIGN_DIM: case ZEND_ASSIGN_OBJ: case ZEND_ASSIGN_OBJ_REF: - return 1; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: - return (opline->extended_value != 0); + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: case ZEND_PRE_INC_OBJ: case ZEND_PRE_DEC_OBJ: case ZEND_POST_INC_OBJ: @@ -312,22 +299,11 @@ static int is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int va case ZEND_FETCH_DIM_IS: case ZEND_FETCH_OBJ_IS: break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: - if (!opline->extended_value) { - return 1; - } - /* break missing intentionally */ + case ZEND_ASSIGN_OP: + return 1; + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_ASSIGN_DIM: case ZEND_ASSIGN_OBJ: case ZEND_ASSIGN_OBJ_REF: diff --git a/ext/opcache/Optimizer/pass2.c b/ext/opcache/Optimizer/pass2.c index 3613fd57de..01e118e7e3 100644 --- a/ext/opcache/Optimizer/pass2.c +++ b/ext/opcache/Optimizer/pass2.c @@ -53,16 +53,6 @@ void zend_optimizer_pass2(zend_op_array *op_array) } } } - /* break missing *intentionally* - the assign_op's may only optimize op2 */ - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_POW: - if (opline->extended_value != 0) { - /* object tristate op - don't attempt to optimize it! */ - break; - } if (opline->op2_type == IS_CONST) { if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { /* don't optimise if it should produce a runtime numeric string error */ @@ -85,14 +75,6 @@ void zend_optimizer_pass2(zend_op_array *op_array) } } } - /* break missing *intentionally - the assign_op's may only optimize op2 */ - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - if (opline->extended_value != 0) { - /* object tristate op - don't attempt to optimize it! */ - break; - } if (opline->op2_type == IS_CONST) { if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) { /* don't optimise if it should produce a runtime numeric string error */ @@ -111,12 +93,6 @@ void zend_optimizer_pass2(zend_op_array *op_array) convert_to_string(&ZEND_OP1_LITERAL(opline)); } } - /* break missing *intentionally - the assign_op's may only optimize op2 */ - case ZEND_ASSIGN_CONCAT: - if (opline->extended_value != 0) { - /* object tristate op - don't attempt to optimize it! */ - break; - } if (opline->op2_type == IS_CONST) { if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) { convert_to_string(&ZEND_OP2_LITERAL(opline)); @@ -124,6 +100,37 @@ void zend_optimizer_pass2(zend_op_array *op_array) } break; + case ZEND_ASSIGN_OP: + if (opline->op2_type == IS_CONST) { + if (opline->extended_value == ZEND_ADD + || opline->extended_value == ZEND_SUB + || opline->extended_value == ZEND_MUL + || opline->extended_value == ZEND_DIV + || opline->extended_value == ZEND_POW) { + if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { + /* don't optimise if it should produce a runtime numeric string error */ + if (is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0)) { + convert_scalar_to_number(&ZEND_OP2_LITERAL(opline)); + } + } + } else if (opline->extended_value == ZEND_MOD + || opline->extended_value == ZEND_SL + || opline->extended_value == ZEND_SR) { + if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) { + /* don't optimise if it should produce a runtime numeric string error */ + if (!(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING + && !is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0))) { + convert_to_long(&ZEND_OP2_LITERAL(opline)); + } + } + } else if (opline->extended_value == ZEND_CONCAT) { + if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) { + convert_to_string(&ZEND_OP2_LITERAL(opline)); + } + } + } + break; + case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: /* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */ diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c index a700893cee..5bbb2b0854 100644 --- a/ext/opcache/Optimizer/pass3.c +++ b/ext/opcache/Optimizer/pass3.c @@ -113,47 +113,12 @@ void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx) } } - if ((opline->op1_type & (IS_VAR | IS_CV)) + if (ZEND_IS_BINARY_ASSIGN_OP_OPCODE(opline->opcode) + && (opline->op1_type & (IS_VAR | IS_CV)) && opline->op1.var == next_opline->op1.var && opline->op1_type == next_opline->op1_type) { - switch (opline->opcode) { - case ZEND_ADD: - opline->opcode = ZEND_ASSIGN_ADD; - break; - case ZEND_SUB: - opline->opcode = ZEND_ASSIGN_SUB; - break; - case ZEND_MUL: - opline->opcode = ZEND_ASSIGN_MUL; - break; - case ZEND_DIV: - opline->opcode = ZEND_ASSIGN_DIV; - break; - case ZEND_MOD: - opline->opcode = ZEND_ASSIGN_MOD; - break; - case ZEND_POW: - opline->opcode = ZEND_ASSIGN_POW; - break; - case ZEND_CONCAT: - opline->opcode = ZEND_ASSIGN_CONCAT; - break; - case ZEND_SL: - opline->opcode = ZEND_ASSIGN_SL; - break; - case ZEND_SR: - opline->opcode = ZEND_ASSIGN_SR; - break; - case ZEND_BW_OR: - opline->opcode = ZEND_ASSIGN_BW_OR; - break; - case ZEND_BW_AND: - opline->opcode = ZEND_ASSIGN_BW_AND; - break; - case ZEND_BW_XOR: - opline->opcode = ZEND_ASSIGN_BW_XOR; - break; - } + opline->extended_value = opline->opcode; + opline->opcode = ZEND_ASSIGN_OP; COPY_NODE(opline->result, next_opline->result); MAKE_NOP(next_opline); opline++; diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c index 6cec35449c..bb3eebe183 100644 --- a/ext/opcache/Optimizer/sccp.c +++ b/ext/opcache/Optimizer/sccp.c @@ -222,18 +222,10 @@ static zend_bool can_replace_op1( case ZEND_ASSIGN_DIM: case ZEND_ASSIGN_OBJ: case ZEND_ASSIGN_OBJ_REF: - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_FETCH_DIM_W: case ZEND_FETCH_DIM_RW: case ZEND_FETCH_DIM_UNSET: @@ -1492,32 +1484,24 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o } SET_RESULT_BOT(result); break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: if (op1) { SKIP_IF_TOP(op1); } if (op2) { SKIP_IF_TOP(op2); } - if (opline->extended_value == 0) { - if (ct_eval_binary_op(&zv, zend_compound_assign_to_binary_op(opline->opcode), op1, op2) == SUCCESS) { + if (opline->opcode == ZEND_ASSIGN_OP) { + if (ct_eval_binary_op(&zv, opline->extended_value, op1, op2) == SUCCESS) { SET_RESULT(op1, &zv); SET_RESULT(result, &zv); zval_ptr_dtor_nogc(&zv); break; } - } else if (opline->extended_value == ZEND_ASSIGN_DIM) { + } else if (opline->opcode == ZEND_ASSIGN_DIM_OP) { if ((IS_PARTIAL_ARRAY(op1) || Z_TYPE_P(op1) == IS_ARRAY) && ssa_op->op1_def >= 0 && op2) { zval tmp; @@ -1536,7 +1520,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o break; } - if (ct_eval_binary_op(&tmp, zend_compound_assign_to_binary_op(opline->opcode), &tmp, data) != SUCCESS) { + if (ct_eval_binary_op(&tmp, opline->extended_value, &tmp, data) != SUCCESS) { SET_RESULT_BOT(result); SET_RESULT_BOT(op1); zval_ptr_dtor_nogc(&tmp); @@ -1561,7 +1545,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o zval_ptr_dtor_nogc(&zv); } } - } else if (opline->extended_value == ZEND_ASSIGN_OBJ) { + } else if (opline->opcode == ZEND_ASSIGN_OBJ_OP) { if (op1 && IS_PARTIAL_OBJECT(op1) && ssa_op->op1_def >= 0 && ctx->scdf.ssa->vars[ssa_op->op1_def].escape_state == ESCAPE_STATE_NO_ESCAPE) { @@ -1581,7 +1565,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o break; } - if (ct_eval_binary_op(&tmp, zend_compound_assign_to_binary_op(opline->opcode), &tmp, data) != SUCCESS) { + if (ct_eval_binary_op(&tmp, opline->extended_value, &tmp, data) != SUCCESS) { SET_RESULT_BOT(result); SET_RESULT_BOT(op1); zval_ptr_dtor_nogc(&tmp); @@ -1602,11 +1586,6 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o zval_ptr_dtor_nogc(&zv); } } - } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) { - SET_RESULT_BOT(result); - break; - } else { - ZEND_ASSERT(0 && "Invalid compound assignment kind"); } SET_RESULT_BOT(result); SET_RESULT_BOT(op1); @@ -2350,18 +2329,10 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, switch (opline->opcode) { case ZEND_ASSIGN_DIM: case ZEND_ASSIGN_OBJ: - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: if ((ssa_op->op2_use >= 0 && !value_known(&ctx->values[ssa_op->op2_use])) || ((ssa_op+1)->op1_use >= 0 &&!value_known(&ctx->values[(ssa_op+1)->op1_use]))) { return 0; @@ -2414,22 +2385,11 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, removed_ops++; zend_ssa_remove_instr(ssa, opline + 1, ssa_op + 1); break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: - if (opline->extended_value) { - removed_ops++; - zend_ssa_remove_instr(ssa, opline + 1, ssa_op + 1); - } + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: + removed_ops++; + zend_ssa_remove_instr(ssa, opline + 1, ssa_op + 1); break; default: break; diff --git a/ext/opcache/Optimizer/zend_dfg.c b/ext/opcache/Optimizer/zend_dfg.c index a1104614f2..e995b673b7 100644 --- a/ext/opcache/Optimizer/zend_dfg.c +++ b/ext/opcache/Optimizer/zend_dfg.c @@ -107,18 +107,10 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg case ZEND_SEND_VAR_NO_REF: case ZEND_SEND_VAR_NO_REF_EX: case ZEND_FE_RESET_RW: - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_PRE_INC: case ZEND_PRE_DEC: case ZEND_POST_INC: diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index 2ed208b779..d6ef63415a 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -446,14 +446,8 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * if (ZEND_VM_EXT_NUM == (flags & ZEND_VM_EXT_MASK)) { fprintf(stderr, " %u", opline->extended_value); - } else if (ZEND_VM_EXT_DIM_OBJ == (flags & ZEND_VM_EXT_MASK)) { - if (opline->extended_value == ZEND_ASSIGN_DIM) { - fprintf(stderr, " (dim)"); - } else if (opline->extended_value == ZEND_ASSIGN_OBJ) { - fprintf(stderr, " (obj)"); - } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) { - fprintf(stderr, " (static prop)"); - } + } else if (ZEND_VM_EXT_OP == (flags & ZEND_VM_EXT_MASK)) { + fprintf(stderr, " (%s)", zend_get_opcode_name(opline->extended_value) + 5); } else if (ZEND_VM_EXT_TYPE == (flags & ZEND_VM_EXT_MASK)) { switch (opline->extended_value) { case IS_NULL: diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index ea28311f70..ed9fc4878c 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -548,25 +548,6 @@ static inline zend_bool shift_left_overflows(zend_long n, zend_long s) { } } -/* Get the normal op corresponding to a compound assignment op */ -static inline zend_uchar get_compound_assign_op(zend_uchar opcode) { - switch (opcode) { - case ZEND_ASSIGN_ADD: return ZEND_ADD; - case ZEND_ASSIGN_SUB: return ZEND_SUB; - case ZEND_ASSIGN_MUL: return ZEND_MUL; - case ZEND_ASSIGN_DIV: return ZEND_DIV; - case ZEND_ASSIGN_MOD: return ZEND_MOD; - case ZEND_ASSIGN_SL: return ZEND_SL; - case ZEND_ASSIGN_SR: return ZEND_SR; - case ZEND_ASSIGN_CONCAT: return ZEND_CONCAT; - case ZEND_ASSIGN_BW_OR: return ZEND_BW_OR; - case ZEND_ASSIGN_BW_AND: return ZEND_BW_AND; - case ZEND_ASSIGN_BW_XOR: return ZEND_BW_XOR; - case ZEND_ASSIGN_POW: return ZEND_POW; - EMPTY_SWITCH_DEFAULT_CASE() - } -} - static int zend_inference_calc_binary_op_range( const zend_op_array *op_array, zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op, zend_uchar opcode, zend_ssa_range *tmp) { @@ -1381,23 +1362,20 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int } } break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - if (opline->extended_value == 0) { + case ZEND_ASSIGN_OP: + if (opline->extended_value != ZEND_CONCAT + && opline->extended_value != ZEND_POW) { if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { return zend_inference_calc_binary_op_range( op_array, ssa, opline, &ssa->ops[line], - get_compound_assign_op(opline->opcode), tmp); + opline->extended_value, tmp); } - } else if ((opline+1)->opcode == ZEND_OP_DATA) { + } + break; + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: + if ((opline+1)->opcode == ZEND_OP_DATA) { if (ssa->ops[line+1].op1_def == var) { opline++; if (OP1_HAS_RANGE()) { @@ -1410,13 +1388,13 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int } } break; -// case ZEND_ASSIGN_CONCAT: case ZEND_OP_DATA: if ((opline-1)->opcode == ZEND_ASSIGN_DIM || (opline-1)->opcode == ZEND_ASSIGN_OBJ || - (opline-1)->opcode == ZEND_ASSIGN_ADD || - (opline-1)->opcode == ZEND_ASSIGN_SUB || - (opline-1)->opcode == ZEND_ASSIGN_MUL) { + ((opline-1)->opcode == ZEND_ASSIGN_OP && + ((opline-1)->extended_value == ZEND_ADD || + (opline-1)->extended_value == ZEND_SUB || + (opline-1)->extended_value == ZEND_MUL))) { if (ssa->ops[line].op1_def == var) { if (OP1_HAS_RANGE()) { tmp->min = OP1_MIN_RANGE(); @@ -2601,34 +2579,27 @@ static int zend_update_type_info(const zend_op_array *op_array, UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def); COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].result_def); break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_POW: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_CONCAT: { + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: + { zend_property_info *prop_info = NULL; orig = 0; tmp = 0; - if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (opline->opcode == ZEND_ASSIGN_OBJ_OP) { prop_info = zend_fetch_prop_info(op_array, ssa, opline, i); orig = t1; t1 = zend_fetch_prop_type(script, prop_info, &ce); t2 = OP1_DATA_INFO(); - } else if (opline->extended_value == ZEND_ASSIGN_DIM) { + } else if (opline->opcode == ZEND_ASSIGN_DIM_OP) { if (t1 & MAY_BE_ARRAY_OF_REF) { tmp |= MAY_BE_REF; } orig = t1; t1 = zend_array_element_type(t1, 1, 0); t2 = OP1_DATA_INFO(); - } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) { + } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) { prop_info = zend_fetch_static_prop_info(script, op_array, ssa, opline); t1 = zend_fetch_prop_type(script, prop_info, &ce); t2 = OP1_DATA_INFO(); @@ -2639,7 +2610,7 @@ static int zend_update_type_info(const zend_op_array *op_array, } tmp |= binary_op_result_type( - ssa, get_compound_assign_op(opline->opcode), t1, t2, ssa_ops[i].op1_def, optimization_level); + ssa, opline->extended_value, t1, t2, ssa_ops[i].op1_def, optimization_level); if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY)) { tmp |= MAY_BE_RC1; } @@ -2647,13 +2618,13 @@ static int zend_update_type_info(const zend_op_array *op_array, tmp |= MAY_BE_RC1 | MAY_BE_RCN; } - if (opline->extended_value == ZEND_ASSIGN_DIM) { + if (opline->opcode == ZEND_ASSIGN_DIM_OP) { if (opline->op1_type == IS_CV) { orig = assign_dim_result_type(orig, OP2_INFO(), tmp, opline->op2_type); UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def); COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def); } - } else if (opline->extended_value == ZEND_ASSIGN_OBJ) { + } else if (opline->opcode == ZEND_ASSIGN_OBJ_OP) { if (opline->op1_type == IS_CV) { if (!(orig & MAY_BE_REF)) { if (orig & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { @@ -2667,14 +2638,14 @@ static int zend_update_type_info(const zend_op_array *op_array, UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def); COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def); } - } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) { + } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP) { /* Nothing to do */ } else { UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def); } if (ssa_ops[i].result_def >= 0) { ce = NULL; - if (opline->extended_value == ZEND_ASSIGN_DIM) { + if (opline->opcode == ZEND_ASSIGN_DIM_OP) { if (opline->op2_type == IS_UNUSED) { /* When appending to an array and the LONG_MAX key is already used * null will be returned. */ @@ -2689,7 +2660,7 @@ static int zend_update_type_info(const zend_op_array *op_array, * results in a null return value. */ tmp |= MAY_BE_NULL; } - } else if (opline->extended_value == ZEND_ASSIGN_OBJ) { + } else if (opline->opcode == ZEND_ASSIGN_OBJ_OP) { if (orig & (MAY_BE_ANY - (MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_OBJECT))) { /* null and false (and empty string) are implicitly converted to object, * anything else results in a null return value. */ @@ -2700,7 +2671,7 @@ static int zend_update_type_info(const zend_op_array *op_array, if (prop_info) { tmp &= zend_fetch_prop_type(script, prop_info, NULL); } - } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) { + } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) { /* The return value must also satisfy the property type */ if (prop_info) { tmp &= zend_fetch_prop_type(script, prop_info, NULL); @@ -3443,18 +3414,10 @@ static int zend_update_type_info(const zend_op_array *op_array, case ZEND_FETCH_DIM_RW: case ZEND_FETCH_DIM_FUNC_ARG: case ZEND_FETCH_LIST_W: - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_ASSIGN_DIM: tmp |= MAY_BE_ARRAY | MAY_BE_ARRAY_OF_ARRAY; break; @@ -3959,13 +3922,19 @@ static zend_bool can_convert_to_double( return 0; } } else { + zend_uchar opcode = opline->opcode; + + if (opcode == ZEND_ASSIGN_OP) { + opcode = opline->extended_value; + } + /* Avoid division by zero */ - if (opline->opcode == ZEND_DIV && zval_get_double(&orig_op2) == 0.0) { + if (opcode == ZEND_DIV && zval_get_double(&orig_op2) == 0.0) { return 0; } - get_binary_op(opline->opcode)(&orig_result, &orig_op1, &orig_op2); - get_binary_op(opline->opcode)(&dval_result, &dval_op1, &dval_op2); + get_binary_op(opcode)(&orig_result, &orig_op1, &orig_op2); + get_binary_op(opcode)(&dval_result, &dval_op1, &dval_op2); ZEND_ASSERT(Z_TYPE(dval_result) == IS_DOUBLE); if (zval_get_double(&orig_result) != Z_DVAL(dval_result)) { return 0; @@ -4573,62 +4542,48 @@ int zend_may_throw(const zend_op *opline, zend_op_array *op_array, zend_ssa *ssa return 0; } return (t1 & (MAY_BE_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT)) || (t2 & (MAY_BE_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT)); - case ZEND_ASSIGN_ADD: - if (opline->extended_value != 0) { - return 1; - } - if ((t1 & MAY_BE_ANY) == MAY_BE_ARRAY - && (t2 & MAY_BE_ANY) == MAY_BE_ARRAY) { - return 0; - } - return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || - (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)); - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - if (opline->extended_value != 0) { - return 1; - } - if (!OP2_HAS_RANGE() || - (OP2_MIN_RANGE() <= 0 && OP2_MAX_RANGE() >= 0)) { - /* Division by zero */ - return 1; - } - /* break missing intentionally */ - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_POW: - if (opline->extended_value != 0) { - return 1; - } - return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || - (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)); - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - if (opline->extended_value != 0) { - return 1; - } - return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || - (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || - !OP2_HAS_RANGE() || - OP2_MIN_RANGE() < 0; - case ZEND_ASSIGN_CONCAT: - if (opline->extended_value != 0) { - return 1; - } - return (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) || - (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT)); - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - if (opline->extended_value != 0) { - return 1; - } - if ((t1 & MAY_BE_ANY) == MAY_BE_STRING - && (t2 & MAY_BE_ANY) == MAY_BE_STRING) { - return 0; + case ZEND_ASSIGN_OP: + if (opline->extended_value == ZEND_ADD) { + if ((t1 & MAY_BE_ANY) == MAY_BE_ARRAY + && (t2 & MAY_BE_ANY) == MAY_BE_ARRAY) { + return 0; + } + return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || + (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)); + } else if (opline->extended_value == ZEND_DIV || + opline->extended_value == ZEND_MOD) { + if (!OP2_HAS_RANGE() || + (OP2_MIN_RANGE() <= 0 && OP2_MAX_RANGE() >= 0)) { + /* Division by zero */ + return 1; + } + return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || + (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)); + } else if (opline->extended_value == ZEND_SUB || + opline->extended_value == ZEND_MUL || + opline->extended_value == ZEND_POW) { + return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || + (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)); + } else if (opline->extended_value == ZEND_SL || + opline->extended_value == ZEND_SR) { + return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || + (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || + !OP2_HAS_RANGE() || + OP2_MIN_RANGE() < 0; + } else if (opline->extended_value == ZEND_CONCAT) { + return (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) || + (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT)); + } else if (opline->extended_value == ZEND_BW_OR || + opline->extended_value == ZEND_BW_AND || + opline->extended_value == ZEND_BW_XOR) { + if ((t1 & MAY_BE_ANY) == MAY_BE_STRING + && (t2 & MAY_BE_ANY) == MAY_BE_STRING) { + return 0; + } + return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || + (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)); } - return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) || - (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)); + return 1; case ZEND_ASSIGN: if (t1 & MAY_BE_REF) { return 1; diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index bf7aa614d4..683ea2548d 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -53,25 +53,6 @@ void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* zend_hash_add(ctx->constants, Z_STR_P(name), &val); } -zend_uchar zend_compound_assign_to_binary_op(zend_uchar opcode) -{ - switch (opcode) { - case ZEND_ASSIGN_ADD: return ZEND_ADD; - case ZEND_ASSIGN_SUB: return ZEND_SUB; - case ZEND_ASSIGN_MUL: return ZEND_MUL; - case ZEND_ASSIGN_DIV: return ZEND_DIV; - case ZEND_ASSIGN_MOD: return ZEND_MOD; - case ZEND_ASSIGN_SL: return ZEND_SL; - case ZEND_ASSIGN_SR: return ZEND_SR; - case ZEND_ASSIGN_CONCAT: return ZEND_CONCAT; - case ZEND_ASSIGN_BW_OR: return ZEND_BW_OR; - case ZEND_ASSIGN_BW_AND: return ZEND_BW_AND; - case ZEND_ASSIGN_BW_XOR: return ZEND_BW_XOR; - case ZEND_ASSIGN_POW: return ZEND_POW; - EMPTY_SWITCH_DEFAULT_CASE() - } -} - int zend_optimizer_eval_binary_op(zval *result, zend_uchar opcode, zval *op1, zval *op2) /* {{{ */ { binary_op_type binary_op = get_binary_op(opcode); @@ -320,21 +301,11 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array, } zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: - if (opline->extended_value != ZEND_ASSIGN_STATIC_PROP) { - break; - } + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + break; + case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_ASSIGN_STATIC_PROP: case ZEND_ASSIGN_STATIC_PROP_REF: case ZEND_FETCH_STATIC_PROP_R: @@ -440,7 +411,7 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array, case ZEND_PRE_DEC_STATIC_PROP: case ZEND_POST_INC_STATIC_PROP: case ZEND_POST_DEC_STATIC_PROP: -handle_static_prop: + case ZEND_ASSIGN_STATIC_PROP_OP: REQUIRES_STRING(val); drop_leading_backslash(val); opline->op2.constant = zend_optimizer_add_literal(op_array, val); @@ -509,6 +480,7 @@ handle_static_prop: case ZEND_PRE_DEC_OBJ: case ZEND_POST_INC_OBJ: case ZEND_POST_DEC_OBJ: + case ZEND_ASSIGN_OBJ_OP: TO_STRING_NOWARN(val); opline->op2.constant = zend_optimizer_add_literal(op_array, val); opline->extended_value = alloc_cache_slots(op_array, 3); @@ -518,42 +490,7 @@ handle_static_prop: opline->op2.constant = zend_optimizer_add_literal(op_array, val); opline->extended_value = alloc_cache_slots(op_array, 3) | (opline->extended_value & ZEND_ISEMPTY); break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_POW: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - if (opline->extended_value == ZEND_ASSIGN_OBJ) { - TO_STRING_NOWARN(val); - opline->op2.constant = zend_optimizer_add_literal(op_array, val); - (opline+1)->extended_value = alloc_cache_slots(op_array, 3); - } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) { - goto handle_static_prop; - } else if (opline->extended_value == ZEND_ASSIGN_DIM) { - if (Z_TYPE_P(val) == IS_STRING) { - zend_ulong index; - - if (ZEND_HANDLE_NUMERIC(Z_STR_P(val), index)) { - ZVAL_LONG(&tmp, index); - opline->op2.constant = zend_optimizer_add_literal(op_array, &tmp); - zend_string_hash_val(Z_STR_P(val)); - zend_optimizer_add_literal(op_array, val); - Z_EXTRA(op_array->literals[opline->op2.constant]) = ZEND_EXTRA_VALUE; - break; - } - } - opline->op2.constant = zend_optimizer_add_literal(op_array, val); - } else { - opline->op2.constant = zend_optimizer_add_literal(op_array, val); - } - break; + case ZEND_ASSIGN_DIM_OP: case ZEND_ISSET_ISEMPTY_DIM_OBJ: case ZEND_ASSIGN_DIM: case ZEND_UNSET_DIM: diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index 9997506bf0..9ab18f6398 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -110,7 +110,6 @@ zend_function *zend_optimizer_get_called_func( uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args); void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, zend_op *opline); void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_t *shiftlist); -zend_uchar zend_compound_assign_to_binary_op(zend_uchar opcode); int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_arrya, zend_ssa *ssa, zend_call_info **call_map); int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reorder_dtor_effects); int zend_ssa_escape_analysis(const zend_script *script, zend_op_array *op_array, zend_ssa *ssa); diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c index 32ead3f20c..9d3b81ca83 100644 --- a/ext/opcache/Optimizer/zend_ssa.c +++ b/ext/opcache/Optimizer/zend_ssa.c @@ -716,18 +716,10 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, //NEW_SSA_VAR(opline->op1.var) } break; - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: + case ZEND_ASSIGN_OP: + case ZEND_ASSIGN_DIM_OP: + case ZEND_ASSIGN_OBJ_OP: + case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_PRE_INC: case ZEND_PRE_DEC: case ZEND_POST_INC: |