Optimized FETCH_CLASS before INSTANCEOF out if possible
authorXinchen Hui <laruence@gmail.com>
Fri, 5 Jan 2018 04:58:28 +0000 (12:58 +0800)
committerXinchen Hui <laruence@gmail.com>
Fri, 5 Jan 2018 04:58:28 +0000 (12:58 +0800)
ext/opcache/Optimizer/sccp.c
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/tests/opt/sccp_024.phpt [new file with mode: 0644]

index 3c6c54be7712f52c8dd3f579edd765c2b08e9a74..996eb10ac728157269c0c8e2a01f1b03f6481819 100644 (file)
@@ -329,6 +329,25 @@ static zend_bool try_replace_op2(
                if (zend_optimizer_update_op2_const(ctx->scdf.op_array, opline, &zv)) {
                        return 1;
                } else {
+                       switch (opline->opcode) {
+                               case ZEND_FETCH_CLASS:
+                                       if (Z_TYPE(zv) == IS_STRING) {
+                                               ZEND_ASSERT((opline + 1)->opcode == ZEND_INSTANCEOF);
+                                               ZEND_ASSERT((opline + 1)->op2.var == opline->result.var);
+                                               if (zend_optimizer_update_op2_const(ctx->scdf.op_array, opline + 1, &zv)) {
+                                                       zend_ssa_op *next_op = ssa_op + 1;
+                                                       zend_optimizer_remove_live_range_ex(ctx->scdf.op_array, opline->result.var, ssa_op - ctx->scdf.ssa->ops);
+                                                       zend_ssa_unlink_use_chain(ctx->scdf.ssa, next_op - ctx->scdf.ssa->ops, next_op->op2_use);
+                                                       next_op->op2_use = -1;
+                                                       next_op->op2_use_chain = -1;
+                                                       zend_ssa_remove_result_def(ctx->scdf.ssa, ssa_op);
+                                                       MAKE_NOP(opline);
+                                                       return 1;
+                                               }
+                                       }
+                               default:
+                                       break;
+                       }
                        zval_ptr_dtor_nogc(&zv);
                }
        }
index 97be113f47af36a73cae14348431568657f1053b..d5975f141418244e07becaba2a15fa3fa9ee6a12 100644 (file)
@@ -347,6 +347,10 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
                case ZEND_FAST_CALL:
                        return 0;
                case ZEND_FETCH_CLASS:
+                       if ((opline + 1)->opcode == ZEND_INSTANCEOF &&
+                               (opline + 1)->op2.var == opline->result.var) {
+                               return 0;
+                       }
                case ZEND_INIT_FCALL_BY_NAME:
                /*case ZEND_INIT_NS_FCALL_BY_NAME:*/
                case ZEND_ADD_INTERFACE:
diff --git a/ext/opcache/tests/opt/sccp_024.phpt b/ext/opcache/tests/opt/sccp_024.phpt
new file mode 100644 (file)
index 0000000..f0b34f0
--- /dev/null
@@ -0,0 +1,41 @@
+--TEST--
+SCCP 024: Const replacing to op2 of INSTANCEOF
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.opt_debug_level=0x20000
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+class A {
+       function t($obj) {
+               $a = "A";
+        $b = "self";
+        $c = 1;
+        echo ($obj instanceof $a);
+        echo ($obj instanceof $b);
+        echo ($obj instanceof $c);
+       }
+}
+?>
+--EXPECTF--
+$_main: ; (lines=1, args=0, vars=0, tmps=0)
+    ; (after optimizer)
+    ; %ssccp_024.php:1-13
+L0 (13):    RETURN int(1)
+
+A::t: ; (lines=10, args=1, vars=2, tmps=2)
+    ; (after optimizer)
+    ; %ssccp_024.php:3-10
+L0 (3):     CV0($obj) = RECV 1
+L1 (6):     CV1($c) = QM_ASSIGN int(1)
+L2 (7):     T2 = INSTANCEOF CV0($obj) string("A")
+L3 (7):     ECHO T2
+L4 (8):     T2 = INSTANCEOF CV0($obj) string("self")
+L5 (8):     ECHO T2
+L6 (9):     V3 = FETCH_CLASS (no-autolod) (exception) CV1($c)
+L7 (9):     T2 = INSTANCEOF CV0($obj) V3
+L8 (9):     ECHO T2
+L9 (10):    RETURN null