]> granicus.if.org Git - php/commitdiff
Fixed incorrect optimizaton (update of jump instructions should be also reflected...
authorDmitry Stogov <dmitry@zend.com>
Mon, 4 Sep 2017 11:07:37 +0000 (14:07 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 4 Sep 2017 11:07:37 +0000 (14:07 +0300)
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/zend_optimizer.c

index 41934f192b6012ed36e589d12c87be6bae97f537..c43ff29f34e8cd81122d7890775930f840b769f4 100644 (file)
@@ -174,7 +174,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
        while (opline < end) {
                /* Constant Propagation: strip X = QM_ASSIGN(const) */
                if ((opline->op1_type & (IS_TMP_VAR|IS_VAR)) &&
-                   opline->opcode != ZEND_FREE) {
+                   opline->opcode != ZEND_FREE &&
+                   !zend_bitset_in(used_ext, VAR_NUM(opline->op1.var))) {
                        src = VAR_SOURCE(opline->op1);
                        if (src &&
                            src->opcode == ZEND_QM_ASSIGN &&
@@ -196,6 +197,56 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
                                                literal_dtor(&ZEND_OP1_LITERAL(src));
                                                MAKE_NOP(src);
                                        } else {
+                                               zend_op *target_opline;
+
+                                               switch (opline->opcode) {
+                                                       case ZEND_JMPZ:
+                                                               if (zend_is_true(&c)) {
+                                                                       MAKE_NOP(opline);
+                                                                       DEL_SOURCE(block, block->successors[0]);
+                                                                       block->successors_count = 1;
+                                                                       block->successors[0] = block->successors[1];
+                                                               } else {
+                                                                       opline->opcode = ZEND_JMP;
+                                                                       COPY_NODE(opline->op1, opline->op2);
+                                                                       opline->op2_type = IS_UNUSED;
+                                                                       DEL_SOURCE(block, block->successors[1]);
+                                                                       block->successors_count = 1;
+                                                               }
+                                                               break;
+                                                       case ZEND_JMPNZ:
+                                                               if (zend_is_true(&c)) {
+                                                                       opline->opcode = ZEND_JMP;
+                                                                       COPY_NODE(opline->op1, opline->op2);
+                                                                       opline->op2_type = IS_UNUSED;
+                                                                       DEL_SOURCE(block, block->successors[1]);
+                                                                       block->successors_count = 1;
+                                                               } else {
+                                                                       MAKE_NOP(opline);
+                                                                       DEL_SOURCE(block, block->successors[0]);
+                                                                       block->successors_count = 1;
+                                                                       block->successors[0] = block->successors[1];
+                                                               }
+                                                               break;
+                                                       case ZEND_JMPZNZ:
+                                                               if (zend_is_true(&c)) {
+                                                                       target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
+                                                                       DEL_SOURCE(block, block->successors[0]);
+                                                                       block->successors_count = 1;
+                                                                       block->successors[0] = block->successors[1];
+                                                               } else {
+                                                                       target_opline = ZEND_OP2_JMP_ADDR(opline);
+                                                                       DEL_SOURCE(block, block->successors[1]);
+                                                                       block->successors_count = 1;
+                                                               }
+                                                               ZEND_SET_OP_JMP_ADDR(opline, opline->op1, target_opline);
+                                                               opline->op1_type = IS_UNUSED;
+                                                               opline->extended_value = 0;
+                                                               opline->opcode = ZEND_JMP;
+                                                               break;
+                                                       default:
+                                                               break;
+                                               }
                                                zval_ptr_dtor_nogc(&c);
                                        }
                                }
@@ -203,7 +254,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
                }
 
                /* Constant Propagation: strip X = QM_ASSIGN(const) */
-               if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
+               if ((opline->op2_type & (IS_TMP_VAR|IS_VAR)) &&
+                   !zend_bitset_in(used_ext, VAR_NUM(opline->op2.var))) {
                        src = VAR_SOURCE(opline->op2);
                        if (src &&
                            src->opcode == ZEND_QM_ASSIGN &&
index f8f42a127704b67715561a838e70be651437b917..cc197c0e5206d2f42316b46a50c9faac505900b8 100644 (file)
@@ -258,41 +258,7 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
                                     zend_op       *opline,
                                     zval          *val)
 {
-       zend_op *target_opline;
-
        switch (opline->opcode) {
-               case ZEND_JMPZ:
-                       if (zend_is_true(val)) {
-                               MAKE_NOP(opline);
-                       } else {
-                               opline->opcode = ZEND_JMP;
-                               COPY_NODE(opline->op1, opline->op2);
-                               opline->op2_type = IS_UNUSED;
-                       }
-                       zval_ptr_dtor_nogc(val);
-                       return 1;
-               case ZEND_JMPNZ:
-                       if (zend_is_true(val)) {
-                               opline->opcode = ZEND_JMP;
-                               COPY_NODE(opline->op1, opline->op2);
-                               opline->op2_type = IS_UNUSED;
-                       } else {
-                               MAKE_NOP(opline);
-                       }
-                       zval_ptr_dtor_nogc(val);
-                       return 1;
-               case ZEND_JMPZNZ:
-                       if (zend_is_true(val)) {
-                               target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
-                       } else {
-                               target_opline = ZEND_OP2_JMP_ADDR(opline);
-                       }
-                       ZEND_SET_OP_JMP_ADDR(opline, opline->op1, target_opline);
-                       opline->op1_type = IS_UNUSED;
-                       opline->extended_value = 0;
-                       opline->opcode = ZEND_JMP;
-                       zval_ptr_dtor_nogc(val);
-                       return 1;
                case ZEND_FREE:
                        MAKE_NOP(opline);
                        zval_ptr_dtor_nogc(val);