summaryrefslogtreecommitdiff
path: root/ext/opcache
diff options
context:
space:
mode:
Diffstat (limited to 'ext/opcache')
-rw-r--r--ext/opcache/Optimizer/block_pass.c16
-rw-r--r--ext/opcache/Optimizer/compact_literals.c112
-rw-r--r--ext/opcache/Optimizer/dce.c32
-rw-r--r--ext/opcache/Optimizer/dfa_pass.c30
-rw-r--r--ext/opcache/Optimizer/escape_analysis.c38
-rw-r--r--ext/opcache/Optimizer/pass2.c55
-rw-r--r--ext/opcache/Optimizer/pass3.c43
-rw-r--r--ext/opcache/Optimizer/sccp.c86
-rw-r--r--ext/opcache/Optimizer/zend_dfg.c16
-rw-r--r--ext/opcache/Optimizer/zend_dump.c10
-rw-r--r--ext/opcache/Optimizer/zend_inference.c211
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c79
-rw-r--r--ext/opcache/Optimizer/zend_optimizer_internal.h1
-rw-r--r--ext/opcache/Optimizer/zend_ssa.c16
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: