mirror of
https://github.com/php/php-src.git
synced 2026-04-05 07:02:33 +02:00
Added call-graph analyses
This commit is contained in:
@@ -30,10 +30,6 @@
|
||||
#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);
|
||||
|
||||
@@ -28,8 +28,13 @@
|
||||
#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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user