]> granicus.if.org Git - php/commitdiff
Added call-graph analyses
authorDmitry Stogov <dmitry@zend.com>
Thu, 24 Dec 2015 11:30:41 +0000 (14:30 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 24 Dec 2015 11:30:41 +0000 (14:30 +0300)
ext/opcache/Optimizer/dfa_pass.c
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/Optimizer/zend_optimizer.h
ext/opcache/ZendAccelerator.c

index ac7a193675ab616d30b9a18a9681ea79b5f0d030..a2a94af073a84fefec27b98a2fc55603af4e54ff 100644 (file)
 #include "zend_inference.h"
 #include "zend_dump.h"
 
-#ifndef HAVE_DFA_PASS
-# define HAVE_DFA_PASS 0
-#endif
-
 void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
 {
        void *checkpoint;
@@ -41,10 +37,6 @@ void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
        uint32_t flags = 0;
        zend_ssa ssa;
 
-#if !HAVE_DFA_PASS
-       return;
-#endif
-
     /* Build SSA */
        memset(&ssa, 0, sizeof(ssa));
        checkpoint = zend_arena_checkpoint(ctx->arena);
index 443410108192c3d4672bfbeb3157e570514398d9..01d56b3c3394b8ba4d4697948709817801b5af4c 100644 (file)
 #include "zend_vm.h"
 #include "zend_cfg.h"
 #include "zend_func_info.h"
+#include "zend_call_graph.h"
 #include "zend_dump.h"
 
+#ifndef HAVE_DFA_PASS
+# define HAVE_DFA_PASS 0
+#endif
+
 static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
 {
        zval_dtor(zvalue);
@@ -606,15 +611,18 @@ static void zend_optimize(zend_op_array      *op_array,
                }
        }
 
+#if HAVE_DFA_PASS
        /* pass 6:
         * - DFA optimization
         */
-       if (ZEND_OPTIMIZER_PASS_6 & ctx->optimization_level) {
+       if ((ZEND_OPTIMIZER_PASS_6 & ctx->optimization_level) &&
+           !(ZEND_OPTIMIZER_PASS_7 & ctx->optimization_level)) {
                optimize_dfa(op_array, ctx);
                if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_6) {
                        zend_dump_op_array(op_array, 0, "after pass 6", NULL);
                }
        }
+#endif
 
        /* pass 9:
         * - Optimize temp variables usage
@@ -651,12 +659,10 @@ static void zend_optimize(zend_op_array      *op_array,
        }
 }
 
-static void zend_optimize_op_array(zend_op_array      *op_array,
-                                   zend_optimizer_ctx *ctx)
+static void zend_revert_pass_two(zend_op_array *op_array)
 {
        zend_op *opline, *end;
 
-       /* Revert pass_two() */
        opline = op_array->opcodes;
        end = opline + op_array->last;
        while (opline < end) {
@@ -668,11 +674,12 @@ static void zend_optimize_op_array(zend_op_array      *op_array,
                }
                opline++;
        }
+}
 
-       /* Do actual optimizations */
-       zend_optimize(op_array, ctx);
+static void zend_redo_pass_two(zend_op_array *op_array)
+{
+       zend_op *opline, *end;
 
-       /* Redo pass_two() */
        opline = op_array->opcodes;
        end = opline + op_array->last;
        while (opline < end) {
@@ -687,6 +694,19 @@ static void zend_optimize_op_array(zend_op_array      *op_array,
        }
 }
 
+static void zend_optimize_op_array(zend_op_array      *op_array,
+                                   zend_optimizer_ctx *ctx)
+{
+       /* Revert pass_two() */
+       zend_revert_pass_two(op_array);
+
+       /* Do actual optimizations */
+       zend_optimize(op_array, ctx);
+
+       /* Redo pass_two() */
+       zend_redo_pass_two(op_array);
+}
+
 static void zend_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer_ctx *ctx)
 {
        zend_function *func;
@@ -714,6 +734,7 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend
        zend_class_entry *ce;
        zend_op_array *op_array;
        zend_optimizer_ctx ctx;
+       zend_call_graph call_graph;
 
        ctx.arena = zend_arena_create(64 * 1024);
        ctx.script = script;
@@ -751,6 +772,39 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend
                }
        }
 
+#if HAVE_DFA_PASS
+       if ((ZEND_OPTIMIZER_PASS_6 & optimization_level) &&
+           (ZEND_OPTIMIZER_PASS_7 & optimization_level) &&
+           zend_build_call_graph(&ctx.arena, script, ZEND_RT_CONSTANTS, &call_graph) == SUCCESS) {
+               /* Optimize using call-graph */
+               uint32_t i;
+               zend_func_info *func_info;
+
+               for (i = 0; i < call_graph.op_arrays_count; i++) {
+                       zend_revert_pass_two(call_graph.op_arrays[i]);
+                       func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
+                       if (func_info) {
+                               func_info->ssa.rt_constants = 0;
+                       }
+               }
+
+               for (i = 0; i < call_graph.op_arrays_count; i++) {
+                       optimize_dfa(call_graph.op_arrays[i], &ctx);
+               }
+
+               if (debug_level & ZEND_DUMP_AFTER_PASS_7) {
+                       for (i = 0; i < call_graph.op_arrays_count; i++) {
+                               zend_dump_op_array(call_graph.op_arrays[i], 0, "after pass 7", NULL);
+                       }
+               }
+
+               for (i = 0; i < call_graph.op_arrays_count; i++) {
+                       zend_redo_pass_two(call_graph.op_arrays[i]);
+                       ZEND_SET_FUNC_INFO(call_graph.op_arrays[i], NULL);
+               }
+       }
+#endif
+
        if (ZEND_OPTIMIZER_PASS_12 & optimization_level) {
                zend_adjust_fcall_stack_size(&script->main_op_array, &ctx);
 
index 5ec7d8fd8dbdc3dbbc73811410175fcfeb7bfdb6..5743ab6e3eaac70514da28689fe23e50c4d3aeaa 100644 (file)
@@ -31,7 +31,7 @@
 #define ZEND_OPTIMIZER_PASS_4          (1<<3)   /* INIT_FCALL_BY_NAME -> DO_FCALL */
 #define ZEND_OPTIMIZER_PASS_5          (1<<4)   /* CFG based optimization       */
 #define ZEND_OPTIMIZER_PASS_6          (1<<5)   /* DFA based optimization       */
-#define ZEND_OPTIMIZER_PASS_7          (1<<6)
+#define ZEND_OPTIMIZER_PASS_7          (1<<6)   /* CALL GRAPH optimization      */
 #define ZEND_OPTIMIZER_PASS_8          (1<<7)
 #define ZEND_OPTIMIZER_PASS_9          (1<<8)   /* TMP VAR usage                */
 #define ZEND_OPTIMIZER_PASS_10         (1<<9)   /* NOP removal                 */
index 51500a95ffda3129e1544141f2f839cc30f5dd8a..ca7ad67fd08a5519b0e9df9723badc5909fdf548 100644 (file)
@@ -2768,6 +2768,8 @@ file_cache_fallback:
                zend_accel_blacklist_load(&accel_blacklist, ZCG(accel_directives.user_blacklist_filename));
        }
 
+       zend_optimizer_startup();
+
        return SUCCESS;
 }
 
@@ -2785,6 +2787,8 @@ void accel_shutdown(void)
        zend_ini_entry *ini_entry;
        zend_bool file_cache_only = 0;
 
+       zend_optimizer_shutdown();
+
        zend_accel_blacklist_shutdown(&accel_blacklist);
 
        if (!ZCG(enabled) || !accel_startup_ok) {