]> granicus.if.org Git - php/commitdiff
Improved optimizer dubugging facility
authorDmitry Stogov <dmitry@zend.com>
Wed, 9 Dec 2015 11:52:00 +0000 (14:52 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 9 Dec 2015 11:52:00 +0000 (14:52 +0300)
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/zend_dump.c
ext/opcache/Optimizer/zend_dump.h
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/Optimizer/zend_optimizer.h
ext/opcache/Optimizer/zend_optimizer_internal.h
ext/opcache/ZendAccelerator.c
ext/opcache/ZendAccelerator.h
ext/opcache/zend_accelerator_module.c

index 2e797d4e7e1c41428ac9bb78ad4494fa57cd7f1b..6aab22eff58f88536dfcb26deb23012fbf86004c 100644 (file)
@@ -759,9 +759,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
        zend_op *new_opcodes;
        zend_op *opline;
        uint32_t len = 0;
-#if DEBUG_BLOCKPASS
        int n;
-#endif
 
        for (b = blocks; b < end; b++) {
                if (b->flags & ZEND_BB_REACHABLE) {
@@ -979,7 +977,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
                *opline_num = -1;
        }
 
-#if DEBUG_BLOCKPASS
        /* rebild map (judt for printing) */
        memset(cfg->map, -1, sizeof(int) * op_array->last);
        for (n = 0; n < cfg->blocks_count; n++) {
@@ -987,7 +984,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
                        cfg->map[cfg->blocks[n].start] = n;
                }
        }
-#endif
 }
 
 static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_array, zend_cfg *cfg, zend_uchar *same_t)
@@ -1731,11 +1727,6 @@ void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
        zend_op **Tsource;
        zend_uchar *same_t;
 
-#if DEBUG_BLOCKPASS
-       fprintf(stderr, "File %s func %s\n", op_array->filename->val, op_array->function_name ? op_array->function_name->val : "main");
-       fflush(stderr);
-#endif
-
     /* Build CFG */
        checkpoint = zend_arena_checkpoint(ctx->arena);
        if (zend_build_cfg(&ctx->arena, op_array, 0, 0, &cfg, NULL) != SUCCESS) {
@@ -1743,10 +1734,9 @@ void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                return;
        }
 
-#if DEBUG_BLOCKPASS
-       fprintf(stderr, "\nBEFORE-BLOCK-PASS: %s:\n", op_array->function_name ? op_array->function_name->val : "(null)");
-       zend_dump_op_array(op_array, &cfg, 1);
-#endif
+       if (ctx->debug_level & ZEND_DUMP_BEFORE_BLOCK_PASS) {
+               zend_dump_op_array(op_array, &cfg, ZEND_DUMP_UNREACHABLE, "before block pass");
+       }
 
        if (op_array->last_var || op_array->T) {
                bitset_len = zend_bitset_len(op_array->last_var + op_array->T);
@@ -1791,10 +1781,9 @@ void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
        zend_t_usage(&cfg, op_array, usage, ctx);
        assemble_code_blocks(&cfg, op_array);
 
-#if DEBUG_BLOCKPASS
-       fprintf(stderr, "\nAFTER-BLOCK-PASS: %s:\n", op_array->function_name ? op_array->function_name->val : "(null)");
-       zend_dump_op_array(op_array, &cfg, 0);
-#endif
+       if (ctx->debug_level & ZEND_DUMP_AFTER_BLOCK_PASS) {
+               zend_dump_op_array(op_array, &cfg, 0, "after block pass");
+       }
 
        /* Destroy CFG */
        zend_arena_release(&ctx->arena, checkpoint);
index 59669350707cda6ca278e5077fc48b159e754b3c..e411a4bc3a319802c9dd273066f762f3437663c1 100644 (file)
@@ -120,17 +120,36 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *
        fprintf(stderr, "\n");
 }
 
-void zend_dump_op_array(const zend_op_array *op_array, const zend_cfg *cfg, int all)
+void zend_dump_op_array(const zend_op_array *op_array, const zend_cfg *cfg, uint32_t dump_flags, const char *msg)
 {
        int i;
 
+       if (op_array->function_name) {
+               if (op_array->scope && op_array->scope->name) {
+                       fprintf(stderr, "\n%s::%s", op_array->scope->name->val, op_array->function_name->val);
+               } else {
+                       fprintf(stderr, "\n%s", op_array->function_name->val);
+               }
+       } else {
+               fprintf(stderr, "\n%s", "$_main");
+       }
+       fprintf(stderr, ": ; (lines=%d, args=%d, vars=%d, tmps=%d)\n",
+               op_array->last,
+               op_array->num_args,
+               op_array->last_var,
+               op_array->T);
+       if (msg) {
+               fprintf(stderr, "    ; (%s)\n", msg);
+       }
+       fprintf(stderr, "    ; %s:%u-%u\n", op_array->filename->val, op_array->line_start, op_array->line_end);
+
        if (cfg) {
                int n;
                zend_basic_block *b;
 
                for (n = 0; n < cfg->blocks_count; n++) {
                        b = cfg->blocks + n;
-                       if (all || (b->flags & ZEND_BB_REACHABLE)) {
+                       if ((dump_flags & ZEND_DUMP_UNREACHABLE) || (b->flags & ZEND_BB_REACHABLE)) {
                                const zend_op *opline;
                                const zend_op *end;
                                int printed = 0;
@@ -169,7 +188,7 @@ void zend_dump_op_array(const zend_op_array *op_array, const zend_cfg *cfg, int
                                if (b->flags & ZEND_BB_KILL_VAR) {
                                        fprintf(stderr, " kill_var");
                                }
-                               if (all & !(b->flags & ZEND_BB_REACHABLE)) {
+                               if ((dump_flags & ZEND_DUMP_UNREACHABLE) & !(b->flags & ZEND_BB_REACHABLE)) {
                                        fprintf(stderr, " unreachable");
                                }
 
index 6e2577c04f345320652c43886f9dbe7fca798b34..551c8343000b291bd7dd38654b281e99038360d9 100644 (file)
 #ifndef ZEND_DUMP_H
 #define ZEND_DUMP_H
 
+#define ZEND_DUMP_UNREACHABLE          (1<<0)
+
 BEGIN_EXTERN_C()
 
-void zend_dump_op_array(const zend_op_array *op_array, const zend_cfg *cfg, int all);
+void zend_dump_op_array(const zend_op_array *op_array, const zend_cfg *cfg, uint32_t dump_flags, const char *msg);
 
 END_EXTERN_C()
 
index 43c80e3ed2e61aca85fcc400a16a958568e3cb2c..3d238acd850faafe548886c39f85132811f331e9 100644 (file)
@@ -26,6 +26,8 @@
 #include "zend_constants.h"
 #include "zend_execute.h"
 #include "zend_vm.h"
+#include "zend_cfg.h"
+#include "zend_dump.h"
 
 static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
 {
@@ -529,6 +531,10 @@ static void zend_optimize(zend_op_array      *op_array,
                return;
        }
 
+       if (ctx->debug_level & ZEND_DUMP_BEFORE_OPTIMIZER) {
+               zend_dump_op_array(op_array, NULL, 1, "before optimizer");
+       }
+
        /* pass 1
         * - substitute persistent constants (true, false, null, etc)
         * - perform compile-time evaluation of constant binary and unary operations
@@ -537,6 +543,9 @@ static void zend_optimize(zend_op_array      *op_array,
         */
        if (ZEND_OPTIMIZER_PASS_1 & ctx->optimization_level) {
                zend_optimizer_pass1(op_array, ctx);
+               if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_1) {
+                       zend_dump_op_array(op_array, NULL, 1, "after pass 1");
+               }
        }
 
        /* pass 2:
@@ -547,6 +556,9 @@ static void zend_optimize(zend_op_array      *op_array,
         */
        if (ZEND_OPTIMIZER_PASS_2 & ctx->optimization_level) {
                zend_optimizer_pass2(op_array);
+               if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_2) {
+                       zend_dump_op_array(op_array, NULL, 1, "after pass 2");
+               }
        }
 
        /* pass 3:
@@ -556,6 +568,9 @@ static void zend_optimize(zend_op_array      *op_array,
         */
        if (ZEND_OPTIMIZER_PASS_3 & ctx->optimization_level) {
                zend_optimizer_pass3(op_array);
+               if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_3) {
+                       zend_dump_op_array(op_array, NULL, 1, "after pass 1");
+               }
        }
 
        /* pass 4:
@@ -563,6 +578,9 @@ static void zend_optimize(zend_op_array      *op_array,
         */
        if (ZEND_OPTIMIZER_PASS_4 & ctx->optimization_level) {
                optimize_func_calls(op_array, ctx);
+               if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_4) {
+                       zend_dump_op_array(op_array, NULL, 1, "after pass 1");
+               }
        }
 
        /* pass 5:
@@ -570,6 +588,9 @@ static void zend_optimize(zend_op_array      *op_array,
         */
        if (ZEND_OPTIMIZER_PASS_5 & ctx->optimization_level) {
                optimize_cfg(op_array, ctx);
+               if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_5) {
+                       zend_dump_op_array(op_array, NULL, 1, "after pass 5");
+               }
        }
 
        /* pass 9:
@@ -577,6 +598,9 @@ static void zend_optimize(zend_op_array      *op_array,
         */
        if (ZEND_OPTIMIZER_PASS_9 & ctx->optimization_level) {
                optimize_temporary_variables(op_array, ctx);
+               if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_9) {
+                       zend_dump_op_array(op_array, NULL, 1, "after pass 9");
+               }
        }
 
        /* pass 10:
@@ -584,6 +608,9 @@ static void zend_optimize(zend_op_array      *op_array,
         */
        if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & ctx->optimization_level) == ZEND_OPTIMIZER_PASS_10) {
                zend_optimizer_nop_removal(op_array);
+               if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_10) {
+                       zend_dump_op_array(op_array, NULL, 1, "after pass 10");
+               }
        }
 
        /* pass 11:
@@ -591,6 +618,13 @@ static void zend_optimize(zend_op_array      *op_array,
         */
        if (ZEND_OPTIMIZER_PASS_11 & ctx->optimization_level) {
                zend_optimizer_compact_literals(op_array, ctx);
+               if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_11) {
+                       zend_dump_op_array(op_array, NULL, 1, "after pass 11");
+               }
+       }
+
+       if (ctx->debug_level & ZEND_DUMP_AFTER_OPTIMIZER) {
+               zend_dump_op_array(op_array, NULL, 1, "after optimizer");
        }
 }
 
@@ -650,7 +684,7 @@ static void zend_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer
        }
 }
 
-int zend_optimize_script(zend_script *script, zend_long optimization_level)
+int zend_optimize_script(zend_script *script, zend_long optimization_level, zend_long debug_level)
 {
        uint idx, j;
        Bucket *p, *q;
@@ -662,6 +696,7 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level)
        ctx.script = script;
        ctx.constants = NULL;
        ctx.optimization_level = optimization_level;
+       ctx.debug_level = debug_level;
 
        zend_optimize_op_array(&script->main_op_array, &ctx);
 
index 9c2a805e7690579a5ee9c109561eb4d97b26ab46..c8e33c368eb00d4c6f2754b1ff996dc5f032a907 100644 (file)
 
 #define DEFAULT_OPTIMIZATION_LEVEL  "0xFFFFFFFF"
 
+
+#define ZEND_DUMP_AFTER_PASS_1         ZEND_OPTIMIZER_PASS_1
+#define ZEND_DUMP_AFTER_PASS_2         ZEND_OPTIMIZER_PASS_2
+#define ZEND_DUMP_AFTER_PASS_3         ZEND_OPTIMIZER_PASS_3
+#define ZEND_DUMP_AFTER_PASS_4         ZEND_OPTIMIZER_PASS_4
+#define ZEND_DUMP_AFTER_PASS_5         ZEND_OPTIMIZER_PASS_5
+#define ZEND_DUMP_AFTER_PASS_6         ZEND_OPTIMIZER_PASS_6
+#define ZEND_DUMP_AFTER_PASS_7         ZEND_OPTIMIZER_PASS_7
+#define ZEND_DUMP_AFTER_PASS_8         ZEND_OPTIMIZER_PASS_8
+#define ZEND_DUMP_AFTER_PASS_9         ZEND_OPTIMIZER_PASS_9
+#define ZEND_DUMP_AFTER_PASS_10                ZEND_OPTIMIZER_PASS_10
+#define ZEND_DUMP_AFTER_PASS_11                ZEND_OPTIMIZER_PASS_11
+#define ZEND_DUMP_AFTER_PASS_12                ZEND_OPTIMIZER_PASS_12
+#define ZEND_DUMP_AFTER_PASS_13                ZEND_OPTIMIZER_PASS_13
+#define ZEND_DUMP_AFTER_PASS_14                ZEND_OPTIMIZER_PASS_14
+
+#define ZEND_DUMP_BEFORE_OPTIMIZER  (1<<16)
+#define ZEND_DUMP_AFTER_OPTIMIZER   (1<<17)
+#define ZEND_DUMP_BEFORE_BLOCK_PASS (1<<18)
+#define ZEND_DUMP_AFTER_BLOCK_PASS  (1<<19)
+
 typedef struct _zend_script {
        zend_string   *filename;
        zend_op_array  main_op_array;
@@ -51,6 +72,6 @@ typedef struct _zend_script {
        HashTable      class_table;
 } zend_script;
 
-int zend_optimize_script(zend_script *script, zend_long optimization_level);
+int zend_optimize_script(zend_script *script, zend_long optimization_level, zend_long debug_level);
 
 #endif
index 529727d7c9ed511f63143255a91a8d833a7df347..b41fe9f9e661865bfddeb4a60ca347b78f709c85 100644 (file)
@@ -49,6 +49,7 @@ typedef struct _zend_optimizer_ctx {
        zend_script            *script;
        HashTable              *constants;
        zend_long               optimization_level;
+       zend_long               debug_level;
 } zend_optimizer_ctx;
 
 #define LITERAL_LONG(op, val) do { \
index 2bf05fef9fd65eeae58c95b60babbbe44c5ad4e6..5df11f2e24d4a2a692fb642bef130abebdc35841 100644 (file)
@@ -1157,7 +1157,7 @@ static zend_persistent_script *cache_script_in_file_cache(zend_persistent_script
                return new_persistent_script;
        }
 
-       if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level)) {
+       if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
                return new_persistent_script;
        }
 
@@ -1215,7 +1215,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
                return new_persistent_script;
        }
 
-       if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level)) {
+       if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
                return new_persistent_script;
        }
 
index 9256212090b3b3c4ffdfd3daea4aaa1dab4987ac..ae550291c5fd5b792bdded1b486ee282150814ac 100644 (file)
@@ -191,6 +191,7 @@ typedef struct _zend_accel_directives {
        zend_long           log_verbosity_level;
 
        zend_long           optimization_level;
+       zend_long           opt_debug_level;
        zend_long           max_file_size;
        zend_long           interned_strings_buffer;
        char          *restrict_api;
index 8514e2b39147ce6b3ef59634e7f7887d9ff00001..bb89020b215825c72084bb90dbf3e1a0e8836d62 100644 (file)
@@ -294,6 +294,7 @@ ZEND_INI_BEGIN()
        STD_PHP_INI_ENTRY("opcache.fast_shutdown"         , "0"  , PHP_INI_SYSTEM, OnUpdateBool,                  accel_directives.fast_shutdown,             zend_accel_globals, accel_globals)
 
        STD_PHP_INI_ENTRY("opcache.optimization_level"    , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level,   zend_accel_globals, accel_globals)
+       STD_PHP_INI_ENTRY("opcache.opt_debug_level"       , "0"      , PHP_INI_SYSTEM, OnUpdateLong,             accel_directives.opt_debug_level,            zend_accel_globals, accel_globals)
        STD_PHP_INI_BOOLEAN("opcache.enable_file_override"      , "0"   , PHP_INI_SYSTEM, OnUpdateBool,              accel_directives.file_override_enabled,     zend_accel_globals, accel_globals)
        STD_PHP_INI_BOOLEAN("opcache.enable_cli"             , "0"   , PHP_INI_SYSTEM, OnUpdateBool,              accel_directives.enable_cli,                zend_accel_globals, accel_globals)
        STD_PHP_INI_ENTRY("opcache.error_log"                , ""    , PHP_INI_SYSTEM, OnUpdateString,           accel_directives.error_log,                 zend_accel_globals, accel_globals)