File manager - Edit - /home/c14075/dragmet-ural.ru/www/Optimizer.tar
Back
zend_func_info.h 0000644 00000005751 15140223534 0007712 0 ustar 00 /* +----------------------------------------------------------------------+ | Zend Engine, Func Info | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Dmitry Stogov <dmitry@php.net> | +----------------------------------------------------------------------+ */ #ifndef ZEND_FUNC_INFO_H #define ZEND_FUNC_INFO_H #include "zend_ssa.h" /* func/cfg flags */ #define ZEND_FUNC_INDIRECT_VAR_ACCESS (1<<0) /* accesses variables by name */ #define ZEND_FUNC_HAS_CALLS (1<<1) #define ZEND_FUNC_VARARG (1<<2) /* uses func_get_args() */ #define ZEND_FUNC_NO_LOOPS (1<<3) #define ZEND_FUNC_IRREDUCIBLE (1<<4) #define ZEND_FUNC_FREE_LOOP_VAR (1<<5) #define ZEND_FUNC_RECURSIVE (1<<7) #define ZEND_FUNC_RECURSIVE_DIRECTLY (1<<8) #define ZEND_FUNC_RECURSIVE_INDIRECTLY (1<<9) #define ZEND_FUNC_HAS_EXTENDED_FCALL (1<<10) #define ZEND_FUNC_HAS_EXTENDED_STMT (1<<11) #define ZEND_SSA_TSSA (1<<12) /* used by tracing JIT */ #define ZEND_FUNC_JIT_ON_FIRST_EXEC (1<<13) /* used by JIT */ #define ZEND_FUNC_JIT_ON_PROF_REQUEST (1<<14) /* used by JIT */ #define ZEND_FUNC_JIT_ON_HOT_COUNTERS (1<<15) /* used by JIT */ #define ZEND_FUNC_JIT_ON_HOT_TRACE (1<<16) /* used by JIT */ typedef struct _zend_func_info zend_func_info; typedef struct _zend_call_info zend_call_info; #define ZEND_FUNC_INFO(op_array) \ ((zend_func_info*)((op_array)->reserved[zend_func_info_rid])) #define ZEND_SET_FUNC_INFO(op_array, info) do { \ zend_func_info** pinfo = (zend_func_info**)&(op_array)->reserved[zend_func_info_rid]; \ *pinfo = info; \ } while (0) BEGIN_EXTERN_C() extern ZEND_API int zend_func_info_rid; uint32_t zend_get_internal_func_info( const zend_function *callee_func, const zend_call_info *call_info, const zend_ssa *ssa); ZEND_API uint32_t zend_get_func_info( const zend_call_info *call_info, const zend_ssa *ssa, zend_class_entry **ce, bool *ce_is_instanceof); zend_result zend_func_info_startup(void); zend_result zend_func_info_shutdown(void); END_EXTERN_C() #endif /* ZEND_FUNC_INFO_H */ zend_optimizer.h 0000644 00000011535 15140223534 0007763 0 ustar 00 /* +----------------------------------------------------------------------+ | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andi Gutmans <andi@php.net> | | Zeev Suraski <zeev@php.net> | | Stanislav Malyshev <stas@zend.com> | | Dmitry Stogov <dmitry@php.net> | +----------------------------------------------------------------------+ */ #ifndef ZEND_OPTIMIZER_H #define ZEND_OPTIMIZER_H #include "zend.h" #include "zend_compile.h" #define ZEND_OPTIMIZER_PASS_1 (1<<0) /* Simple local optimizations */ #define ZEND_OPTIMIZER_PASS_2 (1<<1) /* */ #define ZEND_OPTIMIZER_PASS_3 (1<<2) /* Jump optimization */ #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) /* CALL GRAPH optimization */ #define ZEND_OPTIMIZER_PASS_8 (1<<7) /* SCCP (constant propagation) */ #define ZEND_OPTIMIZER_PASS_9 (1<<8) /* TMP VAR usage */ #define ZEND_OPTIMIZER_PASS_10 (1<<9) /* NOP removal */ #define ZEND_OPTIMIZER_PASS_11 (1<<10) /* Merge equal constants */ #define ZEND_OPTIMIZER_PASS_12 (1<<11) /* Adjust used stack */ #define ZEND_OPTIMIZER_PASS_13 (1<<12) /* Remove unused variables */ #define ZEND_OPTIMIZER_PASS_14 (1<<13) /* DCE (dead code elimination) */ #define ZEND_OPTIMIZER_PASS_15 (1<<14) /* (unsafe) Collect constants */ #define ZEND_OPTIMIZER_PASS_16 (1<<15) /* Inline functions */ #define ZEND_OPTIMIZER_IGNORE_OVERLOADING (1<<16) /* (unsafe) Ignore possibility of operator overloading */ #define ZEND_OPTIMIZER_NARROW_TO_DOUBLE (1<<17) /* try to narrow long constant assignments to double */ #define ZEND_OPTIMIZER_ALL_PASSES 0x7FFFFFFF #define DEFAULT_OPTIMIZATION_LEVEL "0x7FFEBFFF" #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) #define ZEND_DUMP_BLOCK_PASS_VARS (1<<20) #define ZEND_DUMP_BEFORE_DFA_PASS (1<<21) #define ZEND_DUMP_AFTER_DFA_PASS (1<<22) #define ZEND_DUMP_DFA_CFG (1<<23) #define ZEND_DUMP_DFA_DOMINATORS (1<<24) #define ZEND_DUMP_DFA_LIVENESS (1<<25) #define ZEND_DUMP_DFA_PHI (1<<26) #define ZEND_DUMP_DFA_SSA (1<<27) #define ZEND_DUMP_DFA_SSA_VARS (1<<28) #define ZEND_DUMP_SCCP (1<<29) typedef struct _zend_script { zend_string *filename; zend_op_array main_op_array; HashTable function_table; HashTable class_table; } zend_script; typedef void (*zend_optimizer_pass_t)(zend_script *, void *context); BEGIN_EXTERN_C() ZEND_API void zend_optimize_script(zend_script *script, zend_long optimization_level, zend_long debug_level); ZEND_API int zend_optimizer_register_pass(zend_optimizer_pass_t pass); ZEND_API void zend_optimizer_unregister_pass(int idx); zend_result zend_optimizer_startup(void); zend_result zend_optimizer_shutdown(void); END_EXTERN_C() #endif zend_inference.h 0000644 00000024355 15140223534 0007703 0 ustar 00 /* +----------------------------------------------------------------------+ | Zend Engine, e-SSA based Type & Range Inference | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Dmitry Stogov <dmitry@php.net> | +----------------------------------------------------------------------+ */ #ifndef ZEND_INFERENCE_H #define ZEND_INFERENCE_H #include "zend_optimizer.h" #include "zend_ssa.h" #include "zend_bitset.h" /* Bitmask for type inference (zend_ssa_var_info.type) */ #include "zend_type_info.h" #define MAY_BE_PACKED_GUARD (1<<27) /* needs packed array guard */ #define MAY_BE_CLASS_GUARD (1<<27) /* needs class guard */ #define MAY_BE_GUARD (1<<28) /* needs type guard */ //#define MAY_BE_IN_REG (1<<29) /* deprecated and not used */ #define MAY_HAVE_DTOR \ (MAY_BE_OBJECT|MAY_BE_RESOURCE \ |MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE) #define DEFINE_SSA_OP_HAS_RANGE(opN) \ static zend_always_inline bool _ssa_##opN##_has_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op) \ { \ if (opline->opN##_type == IS_CONST) { \ zval *zv = CRT_CONSTANT(opline->opN); \ return (Z_TYPE_P(zv) == IS_LONG); \ } else { \ return (opline->opN##_type != IS_UNUSED && \ ssa->var_info && \ ssa_op->opN##_use >= 0 && \ ssa->var_info[ssa_op->opN##_use].has_range); \ } \ return 0; \ } \ #define DEFINE_SSA_OP_MIN_RANGE(opN) \ static zend_always_inline zend_long _ssa_##opN##_min_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op) \ { \ if (opline->opN##_type == IS_CONST) { \ zval *zv = CRT_CONSTANT(opline->opN); \ if (Z_TYPE_P(zv) == IS_LONG) { \ return Z_LVAL_P(zv); \ } \ } else if (opline->opN##_type != IS_UNUSED && \ ssa->var_info && \ ssa_op->opN##_use >= 0 && \ ssa->var_info[ssa_op->opN##_use].has_range) { \ return ssa->var_info[ssa_op->opN##_use].range.min; \ } \ return ZEND_LONG_MIN; \ } \ #define DEFINE_SSA_OP_MAX_RANGE(opN) \ static zend_always_inline zend_long _ssa_##opN##_max_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op) \ { \ if (opline->opN##_type == IS_CONST) { \ zval *zv = CRT_CONSTANT(opline->opN); \ if (Z_TYPE_P(zv) == IS_LONG) { \ return Z_LVAL_P(zv); \ } \ } else if (opline->opN##_type != IS_UNUSED && \ ssa->var_info && \ ssa_op->opN##_use >= 0 && \ ssa->var_info[ssa_op->opN##_use].has_range) { \ return ssa->var_info[ssa_op->opN##_use].range.max; \ } \ return ZEND_LONG_MAX; \ } \ #define DEFINE_SSA_OP_RANGE_UNDERFLOW(opN) \ static zend_always_inline char _ssa_##opN##_range_underflow(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op) \ { \ if (opline->opN##_type == IS_CONST) { \ zval *zv = CRT_CONSTANT(opline->opN); \ if (Z_TYPE_P(zv) == IS_LONG) { \ return 0; \ } \ } else if (opline->opN##_type != IS_UNUSED && \ ssa->var_info && \ ssa_op->opN##_use >= 0 && \ ssa->var_info[ssa_op->opN##_use].has_range) { \ return ssa->var_info[ssa_op->opN##_use].range.underflow; \ } \ return 1; \ } \ #define DEFINE_SSA_OP_RANGE_OVERFLOW(opN) \ static zend_always_inline char _ssa_##opN##_range_overflow(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op) \ { \ if (opline->opN##_type == IS_CONST) { \ zval *zv = CRT_CONSTANT(opline->opN); \ if (Z_TYPE_P(zv) == IS_LONG) { \ return 0; \ } \ } else if (opline->opN##_type != IS_UNUSED && \ ssa->var_info && \ ssa_op->opN##_use >= 0 && \ ssa->var_info[ssa_op->opN##_use].has_range) { \ return ssa->var_info[ssa_op->opN##_use].range.overflow; \ } \ return 1; \ } \ DEFINE_SSA_OP_HAS_RANGE(op1) DEFINE_SSA_OP_MIN_RANGE(op1) DEFINE_SSA_OP_MAX_RANGE(op1) DEFINE_SSA_OP_RANGE_UNDERFLOW(op1) DEFINE_SSA_OP_RANGE_OVERFLOW(op1) DEFINE_SSA_OP_HAS_RANGE(op2) DEFINE_SSA_OP_MIN_RANGE(op2) DEFINE_SSA_OP_MAX_RANGE(op2) DEFINE_SSA_OP_RANGE_UNDERFLOW(op2) DEFINE_SSA_OP_RANGE_OVERFLOW(op2) #define OP1_HAS_RANGE() (_ssa_op1_has_range (op_array, ssa, opline, ssa_op)) #define OP1_MIN_RANGE() (_ssa_op1_min_range (op_array, ssa, opline, ssa_op)) #define OP1_MAX_RANGE() (_ssa_op1_max_range (op_array, ssa, opline, ssa_op)) #define OP1_RANGE_UNDERFLOW() (_ssa_op1_range_underflow (op_array, ssa, opline, ssa_op)) #define OP1_RANGE_OVERFLOW() (_ssa_op1_range_overflow (op_array, ssa, opline, ssa_op)) #define OP2_HAS_RANGE() (_ssa_op2_has_range (op_array, ssa, opline, ssa_op)) #define OP2_MIN_RANGE() (_ssa_op2_min_range (op_array, ssa, opline, ssa_op)) #define OP2_MAX_RANGE() (_ssa_op2_max_range (op_array, ssa, opline, ssa_op)) #define OP2_RANGE_UNDERFLOW() (_ssa_op2_range_underflow (op_array, ssa, opline, ssa_op)) #define OP2_RANGE_OVERFLOW() (_ssa_op2_range_overflow (op_array, ssa, opline, ssa_op)) BEGIN_EXTERN_C() ZEND_API uint32_t ZEND_FASTCALL zend_array_type_info(const zval *zv); END_EXTERN_C() static zend_always_inline uint32_t _const_op_type(const zval *zv) { if (Z_TYPE_P(zv) == IS_CONSTANT_AST) { return MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY; } else if (Z_TYPE_P(zv) == IS_ARRAY) { return zend_array_type_info(zv); } else { uint32_t tmp = (1 << Z_TYPE_P(zv)); if (Z_REFCOUNTED_P(zv)) { tmp |= MAY_BE_RC1 | MAY_BE_RCN; } else if (Z_TYPE_P(zv) == IS_STRING) { tmp |= MAY_BE_RCN; } return tmp; } } static zend_always_inline uint32_t get_ssa_var_info(const zend_ssa *ssa, int ssa_var_num) { if (ssa->var_info && ssa_var_num >= 0) { return ssa->var_info[ssa_var_num].type; } else { return MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_INDIRECT | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; } } #define DEFINE_SSA_OP_INFO(opN) \ static zend_always_inline uint32_t _ssa_##opN##_info(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op) \ { \ if (opline->opN##_type == IS_CONST) { \ return _const_op_type(CRT_CONSTANT(opline->opN)); \ } else { \ return get_ssa_var_info(ssa, ssa->var_info ? ssa_op->opN##_use : -1); \ } \ } \ #define DEFINE_SSA_OP_DEF_INFO(opN) \ static zend_always_inline uint32_t _ssa_##opN##_def_info(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op *ssa_op) \ { \ return get_ssa_var_info(ssa, ssa->var_info ? ssa_op->opN##_def : -1); \ } \ DEFINE_SSA_OP_INFO(op1) DEFINE_SSA_OP_INFO(op2) DEFINE_SSA_OP_INFO(result) DEFINE_SSA_OP_DEF_INFO(op1) DEFINE_SSA_OP_DEF_INFO(op2) DEFINE_SSA_OP_DEF_INFO(result) #define OP1_INFO() (_ssa_op1_info(op_array, ssa, opline, ssa_op)) #define OP2_INFO() (_ssa_op2_info(op_array, ssa, opline, ssa_op)) #define OP1_DATA_INFO() (_ssa_op1_info(op_array, ssa, (opline+1), (ssa_op+1))) #define OP2_DATA_INFO() (_ssa_op2_info(op_array, ssa, (opline+1), (ssa_op+1))) #define RES_USE_INFO() (_ssa_result_info(op_array, ssa, opline, ssa_op)) #define OP1_DEF_INFO() (_ssa_op1_def_info(op_array, ssa, opline, ssa_op)) #define OP2_DEF_INFO() (_ssa_op2_def_info(op_array, ssa, opline, ssa_op)) #define OP1_DATA_DEF_INFO() (_ssa_op1_def_info(op_array, ssa, (opline+1), (ssa_op+1))) #define OP2_DATA_DEF_INFO() (_ssa_op2_def_info(op_array, ssa, (opline+1), (ssa_op+1))) #define RES_INFO() (_ssa_result_def_info(op_array, ssa, opline, ssa_op)) static zend_always_inline bool zend_add_will_overflow(zend_long a, zend_long b) { return (b > 0 && a > ZEND_LONG_MAX - b) || (b < 0 && a < ZEND_LONG_MIN - b); } static zend_always_inline bool zend_sub_will_overflow(zend_long a, zend_long b) { return (b > 0 && a < ZEND_LONG_MIN + b) || (b < 0 && a > ZEND_LONG_MAX + b); } BEGIN_EXTERN_C() ZEND_API void zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ssa); ZEND_API void zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa); ZEND_API int zend_ssa_inference(zend_arena **raena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level); ZEND_API uint32_t zend_array_element_type(uint32_t t1, zend_uchar op_type, int write, int insert); ZEND_API bool zend_inference_propagate_range(const zend_op_array *op_array, zend_ssa *ssa, zend_op *opline, zend_ssa_op* ssa_op, int var, zend_ssa_range *tmp); ZEND_API uint32_t zend_fetch_arg_info_type( const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce); ZEND_API void zend_init_func_return_info( const zend_op_array *op_array, const zend_script *script, zend_ssa_var_info *ret); uint32_t zend_get_return_info_from_signature_only( const zend_function *func, const zend_script *script, zend_class_entry **ce, bool *ce_is_instanceof, bool use_tentative_return_info); ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_op_array *op_array, zend_ssa *ssa, uint32_t t1, uint32_t t2); ZEND_API bool zend_may_throw(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_op_array *op_array, zend_ssa *ssa); ZEND_API zend_result zend_update_type_info( const zend_op_array *op_array, zend_ssa *ssa, const zend_script *script, zend_op *opline, zend_ssa_op *ssa_op, const zend_op **ssa_opcodes, zend_long optimization_level); END_EXTERN_C() #endif /* ZEND_INFERENCE_H */ zend_call_graph.h 0000644 00000006143 15140223534 0010034 0 ustar 00 /* +----------------------------------------------------------------------+ | Zend Engine, Call Graph | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Dmitry Stogov <dmitry@php.net> | +----------------------------------------------------------------------+ */ #ifndef ZEND_CALL_GRAPH_H #define ZEND_CALL_GRAPH_H #include "zend_ssa.h" #include "zend_func_info.h" #include "zend_optimizer.h" typedef struct _zend_send_arg_info { zend_op *opline; } zend_send_arg_info; struct _zend_call_info { zend_op_array *caller_op_array; zend_op *caller_init_opline; zend_op *caller_call_opline; zend_function *callee_func; zend_call_info *next_caller; zend_call_info *next_callee; bool recursive; bool send_unpack; /* Parameters passed by SEND_UNPACK or SEND_ARRAY */ bool named_args; /* Function has named arguments */ bool is_prototype; /* An overridden child method may be called */ int num_args; zend_send_arg_info arg_info[1]; }; struct _zend_func_info { int num; uint32_t flags; zend_ssa ssa; /* Static Single Assignment Form */ zend_call_info *caller_info; /* where this function is called from */ zend_call_info *callee_info; /* which functions are called from this one */ zend_call_info **call_map; /* Call info associated with init/call/send opnum */ zend_ssa_var_info return_info; }; typedef struct _zend_call_graph { int op_arrays_count; zend_op_array **op_arrays; zend_func_info *func_infos; } zend_call_graph; BEGIN_EXTERN_C() ZEND_API void zend_build_call_graph(zend_arena **arena, zend_script *script, zend_call_graph *call_graph); ZEND_API void zend_analyze_call_graph(zend_arena **arena, zend_script *script, zend_call_graph *call_graph); ZEND_API zend_call_info **zend_build_call_map(zend_arena **arena, zend_func_info *info, const zend_op_array *op_array); ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_op_array *op_array, zend_func_info *func_info); END_EXTERN_C() #endif /* ZEND_CALL_GRAPH_H */ zend_dump.h 0000644 00000005404 15140223534 0006704 0 ustar 00 /* +----------------------------------------------------------------------+ | Zend Engine, Bytecode Visualisation | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Dmitry Stogov <dmitry@php.net> | +----------------------------------------------------------------------+ */ #ifndef ZEND_DUMP_H #define ZEND_DUMP_H #include "zend_ssa.h" #include "zend_dfg.h" #define ZEND_DUMP_HIDE_UNREACHABLE (1<<0) #define ZEND_DUMP_RC_INFERENCE (1<<1) #define ZEND_DUMP_CFG (1<<2) #define ZEND_DUMP_SSA (1<<3) #define ZEND_DUMP_LIVE_RANGES (1<<4) #define ZEND_DUMP_LINE_NUMBERS (1<<5) BEGIN_EXTERN_C() ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, const char *msg, const void *data); ZEND_API void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *b, const zend_op *opline, uint32_t dump_flags, const zend_ssa *ssa, const zend_ssa_op *ssa_op); ZEND_API void zend_dump_op_line(const zend_op_array *op_array, const zend_basic_block *b, const zend_op *opline, uint32_t dump_flags, const void *data); void zend_dump_dominators(const zend_op_array *op_array, const zend_cfg *cfg); void zend_dump_dfg(const zend_op_array *op_array, const zend_cfg *cfg, const zend_dfg *dfg); void zend_dump_phi_placement(const zend_op_array *op_array, const zend_ssa *ssa); void zend_dump_variables(const zend_op_array *op_array); void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa, uint32_t dump_flags); ZEND_API void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa, int ssa_var_num, zend_uchar var_type, int var_num, uint32_t dump_flags); ZEND_API void zend_dump_var(const zend_op_array *op_array, zend_uchar var_type, int var_num); void zend_dump_op_array_name(const zend_op_array *op_array); void zend_dump_const(const zval *zv); void zend_dump_ht(HashTable *ht); END_EXTERN_C() #endif /* ZEND_DUMP_H */ zend_ssa.h 0000644 00000027510 15140223534 0006527 0 ustar 00 /* +----------------------------------------------------------------------+ | Zend Engine, SSA - Static Single Assignment Form | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Dmitry Stogov <dmitry@php.net> | +----------------------------------------------------------------------+ */ #ifndef ZEND_SSA_H #define ZEND_SSA_H #include "zend_optimizer.h" #include "zend_cfg.h" typedef struct _zend_ssa_range { zend_long min; zend_long max; bool underflow; bool overflow; } zend_ssa_range; typedef enum _zend_ssa_negative_lat { NEG_NONE = 0, NEG_INIT = 1, NEG_INVARIANT = 2, NEG_USE_LT = 3, NEG_USE_GT = 4, NEG_UNKNOWN = 5 } zend_ssa_negative_lat; /* Special kind of SSA Phi function used in eSSA */ typedef struct _zend_ssa_range_constraint { zend_ssa_range range; /* simple range constraint */ int min_var; int max_var; int min_ssa_var; /* ((min_var>0) ? MIN(ssa_var) : 0) + range.min */ int max_ssa_var; /* ((max_var>0) ? MAX(ssa_var) : 0) + range.max */ zend_ssa_negative_lat negative; } zend_ssa_range_constraint; typedef struct _zend_ssa_type_constraint { uint32_t type_mask; /* Type mask to intersect with */ zend_class_entry *ce; /* Class entry for instanceof constraints */ } zend_ssa_type_constraint; typedef union _zend_ssa_pi_constraint { zend_ssa_range_constraint range; zend_ssa_type_constraint type; } zend_ssa_pi_constraint; /* SSA Phi - ssa_var = Phi(source0, source1, ...sourceN) */ typedef struct _zend_ssa_phi zend_ssa_phi; struct _zend_ssa_phi { zend_ssa_phi *next; /* next Phi in the same BB */ int pi; /* if >= 0 this is actually a e-SSA Pi */ zend_ssa_pi_constraint constraint; /* e-SSA Pi constraint */ int var; /* Original CV, VAR or TMP variable index */ int ssa_var; /* SSA variable index */ int block; /* current BB index */ int visited : 1; /* flag to avoid recursive processing */ int has_range_constraint : 1; zend_ssa_phi **use_chains; zend_ssa_phi *sym_use_chain; int *sources; /* Array of SSA IDs that produce this var. As many as this block has predecessors. */ }; typedef struct _zend_ssa_block { zend_ssa_phi *phis; } zend_ssa_block; typedef struct _zend_ssa_op { int op1_use; int op2_use; int result_use; int op1_def; int op2_def; int result_def; int op1_use_chain; int op2_use_chain; int res_use_chain; } zend_ssa_op; typedef enum _zend_ssa_alias_kind { NO_ALIAS, SYMTABLE_ALIAS, HTTP_RESPONSE_HEADER_ALIAS } zend_ssa_alias_kind; typedef enum _zend_ssa_escape_state { ESCAPE_STATE_UNKNOWN, ESCAPE_STATE_NO_ESCAPE, ESCAPE_STATE_FUNCTION_ESCAPE, ESCAPE_STATE_GLOBAL_ESCAPE } zend_ssa_escape_state; typedef struct _zend_ssa_var { int var; /* original var number; op.var for CVs and following numbers for VARs and TMP_VARs */ int scc; /* strongly connected component */ int definition; /* opcode that defines this value */ zend_ssa_phi *definition_phi; /* phi that defines this value */ int use_chain; /* uses of this value, linked through opN_use_chain */ zend_ssa_phi *phi_use_chain; /* uses of this value in Phi, linked through use_chain */ zend_ssa_phi *sym_use_chain; /* uses of this value in Pi constraints */ unsigned int no_val : 1; /* value doesn't matter (used as op1 in ZEND_ASSIGN) */ unsigned int scc_entry : 1; unsigned int alias : 2; /* value may be changed indirectly */ unsigned int escape_state : 2; } zend_ssa_var; typedef struct _zend_ssa_var_info { uint32_t type; /* inferred type (see zend_inference.h) */ zend_ssa_range range; zend_class_entry *ce; unsigned int has_range : 1; unsigned int is_instanceof : 1; /* 0 - class == "ce", 1 - may be child of "ce" */ unsigned int recursive : 1; unsigned int use_as_double : 1; unsigned int delayed_fetch_this : 1; unsigned int avoid_refcounting : 1; unsigned int guarded_reference : 1; unsigned int indirect_reference : 1; /* IS_INDIRECT returned by FETCH_DIM_W/FETCH_OBJ_W */ } zend_ssa_var_info; typedef struct _zend_ssa { zend_cfg cfg; /* control flow graph */ int vars_count; /* number of SSA variables */ int sccs; /* number of SCCs */ zend_ssa_block *blocks; /* array of SSA blocks */ zend_ssa_op *ops; /* array of SSA instructions */ zend_ssa_var *vars; /* use/def chain of SSA variables */ zend_ssa_var_info *var_info; } zend_ssa; BEGIN_EXTERN_C() ZEND_API zend_result zend_build_ssa(zend_arena **arena, const zend_script *script, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa); ZEND_API void zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_array, zend_ssa *ssa); ZEND_API int zend_ssa_rename_op(const zend_op_array *op_array, const zend_op *opline, uint32_t k, uint32_t build_flags, int ssa_vars_count, zend_ssa_op *ssa_ops, int *var); void zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var); void zend_ssa_replace_use_chain(zend_ssa *ssa, int op, int new_op, int var); void zend_ssa_remove_predecessor(zend_ssa *ssa, int from, int to); void zend_ssa_remove_defs_of_instr(zend_ssa *ssa, zend_ssa_op *ssa_op); void zend_ssa_remove_instr(zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op); void zend_ssa_remove_phi(zend_ssa *ssa, zend_ssa_phi *phi); void zend_ssa_remove_uses_of_var(zend_ssa *ssa, int var_num); void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int b); void zend_ssa_rename_var_uses(zend_ssa *ssa, int old_var, int new_var, bool update_types); void zend_ssa_remove_block_from_cfg(zend_ssa *ssa, int b); static zend_always_inline void _zend_ssa_remove_def(zend_ssa_var *var) { ZEND_ASSERT(var->definition >= 0); ZEND_ASSERT(var->use_chain < 0); ZEND_ASSERT(!var->phi_use_chain); var->definition = -1; } static zend_always_inline void zend_ssa_remove_result_def(zend_ssa *ssa, zend_ssa_op *ssa_op) { zend_ssa_var *var = &ssa->vars[ssa_op->result_def]; _zend_ssa_remove_def(var); ssa_op->result_def = -1; } static zend_always_inline void zend_ssa_remove_op1_def(zend_ssa *ssa, zend_ssa_op *ssa_op) { zend_ssa_var *var = &ssa->vars[ssa_op->op1_def]; _zend_ssa_remove_def(var); ssa_op->op1_def = -1; } static zend_always_inline void zend_ssa_remove_op2_def(zend_ssa *ssa, zend_ssa_op *ssa_op) { zend_ssa_var *var = &ssa->vars[ssa_op->op2_def]; _zend_ssa_remove_def(var); ssa_op->op2_def = -1; } END_EXTERN_C() static zend_always_inline int zend_ssa_next_use(const zend_ssa_op *ssa_op, int var, int use) { ssa_op += use; if (ssa_op->op1_use == var) { return ssa_op->op1_use_chain; } else if (ssa_op->op2_use == var) { return ssa_op->op2_use_chain; } else { return ssa_op->res_use_chain; } } static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(const zend_ssa *ssa, int var, const zend_ssa_phi *p) { if (p->pi >= 0) { return p->use_chains[0]; } else { int j; for (j = 0; j < ssa->cfg.blocks[p->block].predecessors_count; j++) { if (p->sources[j] == var) { return p->use_chains[j]; } } } return NULL; } static zend_always_inline bool zend_ssa_is_no_val_use(const zend_op *opline, const zend_ssa_op *ssa_op, int var) { if (opline->opcode == ZEND_ASSIGN || opline->opcode == ZEND_UNSET_CV || opline->opcode == ZEND_BIND_GLOBAL || opline->opcode == ZEND_BIND_STATIC) { return ssa_op->op1_use == var && ssa_op->op2_use != var; } if (opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) { return ssa_op->op2_use == var && ssa_op->op1_use != var; } if (ssa_op->result_use == var && opline->opcode != ZEND_ADD_ARRAY_ELEMENT && opline->opcode != ZEND_ADD_ARRAY_UNPACK) { return ssa_op->op1_use != var && ssa_op->op2_use != var; } return 0; } static zend_always_inline void zend_ssa_rename_defs_of_instr(zend_ssa *ssa, zend_ssa_op *ssa_op) { /* Rename def to use if possible. Mark variable as not defined otherwise. */ if (ssa_op->op1_def >= 0) { if (ssa_op->op1_use >= 0) { zend_ssa_rename_var_uses(ssa, ssa_op->op1_def, ssa_op->op1_use, 1); } ssa->vars[ssa_op->op1_def].definition = -1; ssa_op->op1_def = -1; } if (ssa_op->op2_def >= 0) { if (ssa_op->op2_use >= 0) { zend_ssa_rename_var_uses(ssa, ssa_op->op2_def, ssa_op->op2_use, 1); } ssa->vars[ssa_op->op2_def].definition = -1; ssa_op->op2_def = -1; } if (ssa_op->result_def >= 0) { if (ssa_op->result_use >= 0) { zend_ssa_rename_var_uses(ssa, ssa_op->result_def, ssa_op->result_use, 1); } ssa->vars[ssa_op->result_def].definition = -1; ssa_op->result_def = -1; } } #define NUM_PHI_SOURCES(phi) \ ((phi)->pi >= 0 ? 1 : (ssa->cfg.blocks[(phi)->block].predecessors_count)) /* FOREACH_USE and FOREACH_PHI_USE explicitly support "continue" * and changing the use chain of the current element */ #define FOREACH_USE(var, use) do { \ int _var_num = (var) - ssa->vars, next; \ for (use = (var)->use_chain; use >= 0; use = next) { \ next = zend_ssa_next_use(ssa->ops, _var_num, use); #define FOREACH_USE_END() \ } \ } while (0) #define FOREACH_PHI_USE(var, phi) do { \ int _var_num = (var) - ssa->vars; \ zend_ssa_phi *next_phi; \ for (phi = (var)->phi_use_chain; phi; phi = next_phi) { \ next_phi = zend_ssa_next_use_phi(ssa, _var_num, phi); #define FOREACH_PHI_USE_END() \ } \ } while (0) #define FOREACH_PHI_SOURCE(phi, source) do { \ zend_ssa_phi *_phi = (phi); \ int _i, _end = NUM_PHI_SOURCES(phi); \ for (_i = 0; _i < _end; _i++) { \ ZEND_ASSERT(_phi->sources[_i] >= 0); \ source = _phi->sources[_i]; #define FOREACH_PHI_SOURCE_END() \ } \ } while (0) #define FOREACH_PHI(phi) do { \ int _i; \ for (_i = 0; _i < ssa->cfg.blocks_count; _i++) { \ phi = ssa->blocks[_i].phis; \ for (; phi; phi = phi->next) { #define FOREACH_PHI_END() \ } \ } \ } while (0) #define FOREACH_BLOCK(block) do { \ int _i; \ for (_i = 0; _i < ssa->cfg.blocks_count; _i++) { \ (block) = &ssa->cfg.blocks[_i]; \ if (!((block)->flags & ZEND_BB_REACHABLE)) { \ continue; \ } #define FOREACH_BLOCK_END() \ } \ } while (0) /* Does not support "break" */ #define FOREACH_INSTR_NUM(i) do { \ zend_basic_block *_block; \ FOREACH_BLOCK(_block) { \ uint32_t _end = _block->start + _block->len; \ for ((i) = _block->start; (i) < _end; (i)++) { #define FOREACH_INSTR_NUM_END() \ } \ } FOREACH_BLOCK_END(); \ } while (0) #endif /* ZEND_SSA_H */ zend_dfg.h 0000644 00000003777 15140223534 0006512 0 ustar 00 /* +----------------------------------------------------------------------+ | Zend Engine, DFG - Data Flow Graph | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Dmitry Stogov <dmitry@php.net> | +----------------------------------------------------------------------+ */ #ifndef ZEND_DFG_H #define ZEND_DFG_H #include "zend_bitset.h" #include "zend_cfg.h" typedef struct _zend_dfg { int vars; uint32_t size; zend_bitset tmp; zend_bitset def; zend_bitset use; zend_bitset in; zend_bitset out; } zend_dfg; #define DFG_BITSET(set, set_size, block_num) \ ((set) + ((block_num) * (set_size))) #define DFG_SET(set, set_size, block_num, var_num) \ zend_bitset_incl(DFG_BITSET(set, set_size, block_num), (var_num)) #define DFG_ISSET(set, set_size, block_num, var_num) \ zend_bitset_in(DFG_BITSET(set, set_size, block_num), (var_num)) BEGIN_EXTERN_C() void zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg, uint32_t build_flags); ZEND_API void zend_dfg_add_use_def_op(const zend_op_array *op_array, const zend_op *opline, uint32_t build_flags, zend_bitset use, zend_bitset def); END_EXTERN_C() #endif /* ZEND_DFG_H */ zend_cfg.h 0000644 00000013016 15140223534 0006474 0 ustar 00 /* +----------------------------------------------------------------------+ | Zend Engine, CFG - Control Flow Graph | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Dmitry Stogov <dmitry@php.net> | +----------------------------------------------------------------------+ */ #ifndef ZEND_CFG_H #define ZEND_CFG_H /* zend_basic_block.flags */ #define ZEND_BB_START (1<<0) /* first block */ #define ZEND_BB_FOLLOW (1<<1) /* follows the next block */ #define ZEND_BB_TARGET (1<<2) /* jump target */ #define ZEND_BB_EXIT (1<<3) /* without successors */ #define ZEND_BB_ENTRY (1<<4) /* stackless entry */ #define ZEND_BB_TRY (1<<5) /* start of try block */ #define ZEND_BB_CATCH (1<<6) /* start of catch block */ #define ZEND_BB_FINALLY (1<<7) /* start of finally block */ #define ZEND_BB_FINALLY_END (1<<8) /* end of finally block */ #define ZEND_BB_UNREACHABLE_FREE (1<<11) /* unreachable loop free */ #define ZEND_BB_RECV_ENTRY (1<<12) /* RECV entry */ #define ZEND_BB_LOOP_HEADER (1<<16) #define ZEND_BB_IRREDUCIBLE_LOOP (1<<17) #define ZEND_BB_REACHABLE (1U<<31) #define ZEND_BB_PROTECTED (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY|ZEND_BB_TRY|ZEND_BB_CATCH|ZEND_BB_FINALLY|ZEND_BB_FINALLY_END|ZEND_BB_UNREACHABLE_FREE) typedef struct _zend_basic_block { int *successors; /* successor block indices */ uint32_t flags; uint32_t start; /* first opcode number */ uint32_t len; /* number of opcodes */ int successors_count; /* number of successors */ int predecessors_count; /* number of predecessors */ int predecessor_offset; /* offset of 1-st predecessor */ int idom; /* immediate dominator block */ int loop_header; /* closest loop header, or -1 */ int level; /* steps away from the entry in the dom. tree */ int children; /* list of dominated blocks */ int next_child; /* next dominated block */ int successors_storage[2]; /* up to 2 successor blocks */ } zend_basic_block; /* +------------+---+---+---+---+---+ | |OP1|OP2|EXT| 0 | 1 | +------------+---+---+---+---+---+ |JMP |ADR| | |OP1| - | |JMPZ | |ADR| |OP2|FOL| |JMPNZ | |ADR| |OP2|FOL| |JMPZ_EX | |ADR| |OP2|FOL| |JMPNZ_EX | |ADR| |OP2|FOL| |JMP_SET | |ADR| |OP2|FOL| |COALESCE | |ADR| |OP2|FOL| |ASSERT_CHK | |ADR| |OP2|FOL| |NEW | |ADR| |OP2|FOL| |DCL_ANON* |ADR| | |OP1|FOL| |FE_RESET_* | |ADR| |OP2|FOL| |FE_FETCH_* | | |ADR|EXT|FOL| |CATCH | | |ADR|EXT|FOL| |FAST_CALL |ADR| | |OP1|FOL| |FAST_RET | | | | - | - | |RETURN* | | | | - | - | |EXIT | | | | - | - | |THROW | | | | - | - | |* | | | |FOL| - | +------------+---+---+---+---+---+ */ typedef struct _zend_cfg { int blocks_count; /* number of basic blocks */ int edges_count; /* number of edges */ zend_basic_block *blocks; /* array of basic blocks */ int *predecessors; uint32_t *map; uint32_t flags; } zend_cfg; /* Build Flags */ #define ZEND_CFG_STACKLESS (1<<30) #define ZEND_SSA_DEBUG_LIVENESS (1<<29) #define ZEND_SSA_DEBUG_PHI_PLACEMENT (1<<28) #define ZEND_SSA_RC_INFERENCE (1<<27) #define ZEND_CFG_NO_ENTRY_PREDECESSORS (1<<25) #define ZEND_CFG_RECV_ENTRY (1<<24) #define ZEND_CALL_TREE (1<<23) #define ZEND_SSA_USE_CV_RESULTS (1<<22) #define CRT_CONSTANT_EX(op_array, opline, node) \ (((op_array)->fn_flags & ZEND_ACC_DONE_PASS_TWO) ? \ RT_CONSTANT(opline, (node)) \ : \ CT_CONSTANT_EX(op_array, (node).constant) \ ) #define CRT_CONSTANT(node) \ CRT_CONSTANT_EX(op_array, opline, node) #define RETURN_VALUE_USED(opline) \ ((opline)->result_type != IS_UNUSED) BEGIN_EXTERN_C() ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_cfg *cfg); void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg); ZEND_API void zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg); ZEND_API void zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cfg); ZEND_API void zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg); END_EXTERN_C() #endif /* ZEND_CFG_H */
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.27 |
proxy
|
phpinfo
|
Settings