]> granicus.if.org Git - php/commitdiff
Improve fix for #74456
authorXinchen Hui <laruence@gmail.com>
Tue, 18 Apr 2017 04:47:53 +0000 (12:47 +0800)
committerXinchen Hui <laruence@gmail.com>
Tue, 18 Apr 2017 04:47:53 +0000 (12:47 +0800)
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/zend_optimizer.c

index 7f249130d82b12172a050a8d1174fdbe63ad7368..03e157e9c86aff32dbfbfb8d444f8d3348ac71ed 100644 (file)
@@ -186,7 +186,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
                                        COPY_NODE(opline->op1, src->op1);
                                        VAR_SOURCE(op1) = NULL;
                                        MAKE_NOP(src);
-                               } else if (opline->opcode != ZEND_FETCH_LIST && opline->opcode != ZEND_CASE) {
+                               } else {
                                        zval c = ZEND_OP1_LITERAL(src);
                                        zval_copy_ctor(&c);
                                        if (zend_optimizer_update_op1_const(op_array, opline, &c)) {
index 241f594728794255f1e5ece6ab555786f95900d2..c8524f699510f16219bcce4c114446459dd1726d 100644 (file)
@@ -165,6 +165,10 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
                         * zend_optimizer_replace_by_const() supports this. */
                        zval_ptr_dtor(val);
                        return 0;
+               case ZEND_CASE:
+               case ZEND_FETCH_LIST:
+                       zval_ptr_dtor(val);
+                       return 0;
                case ZEND_CONCAT:
                case ZEND_FAST_CONCAT:
                case ZEND_FETCH_R:
@@ -417,16 +421,27 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
                                 */
                                case ZEND_FETCH_LIST: {
                                        zend_op *m = opline;
+
+                                       if (Z_TYPE_P(val) == IS_STRING) {
+                                               zend_string_hash_val(Z_STR_P(val));
+                                       }
+
                                        do {
                                                if (m->opcode == ZEND_FETCH_LIST &&
                                                        ZEND_OP1_TYPE(m) == type &&
                                                        ZEND_OP1(m).var == var) {
-                                                       zend_optimizer_update_op1_const(op_array, m, val);
+                                                       zval v;
+                                                       ZVAL_COPY_VALUE(&v, val);
+                                                       zval_copy_ctor(&v);
+                                                       ZEND_OP1(m).constant = zend_optimizer_add_literal(op_array, &v);
+                                                       ZEND_OP1_TYPE(m) = IS_CONST;
                                                }
                                                m++;
                                        } while (m->opcode != ZEND_FREE || ZEND_OP1_TYPE(m) != type || ZEND_OP1(m).var != var);
+
                                        ZEND_ASSERT(m->opcode == ZEND_FREE && ZEND_OP1_TYPE(m) == type && ZEND_OP1(m).var == var);
                                        MAKE_NOP(m);
+                                       zval_dtor(val);
                                        zend_optimizer_remove_live_range(op_array, var);
                                        return 1;
                                }
@@ -460,17 +475,22 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
                                        } else {
                                                n = op_array->opcodes + op_array->last;
                                        }
+
+                                       if (Z_TYPE_P(val) == IS_STRING) {
+                                               zend_string_hash_val(Z_STR_P(val));
+                                       }
+
                                        while (m < n) {
                                                if (ZEND_OP1_TYPE(m) == type &&
                                                                ZEND_OP1(m).var == var) {
                                                        if (m->opcode == ZEND_CASE
                                                                        || m->opcode == ZEND_SWITCH_LONG
                                                                        || m->opcode == ZEND_SWITCH_STRING) {
-                                                               zval old_val;
-                                                               ZVAL_COPY_VALUE(&old_val, val);
-                                                               zval_copy_ctor(val);
-                                                               zend_optimizer_update_op1_const(op_array, m, val);
-                                                               ZVAL_COPY_VALUE(val, &old_val);
+                                                               zval v;
+                                                               ZVAL_COPY_VALUE(&v, val);
+                                                               zval_copy_ctor(&v);
+                                                               ZEND_OP1(m).constant = zend_optimizer_add_literal(op_array, &v);
+                                                               ZEND_OP1_TYPE(m) = IS_CONST;
                                                        } else if (m->opcode == ZEND_FREE) {
                                                                MAKE_NOP(m);
                                                        } else {