summaryrefslogtreecommitdiff
path: root/ext/opcache/jit/zend_jit.h
blob: 0d71efa47075e786e155400b8a9d548dc576a533 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
   +----------------------------------------------------------------------+
   | Zend JIT                                                             |
   +----------------------------------------------------------------------+
   | 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:           |
   | http://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 HAVE_JIT_H
#define HAVE_JIT_H

#define ZEND_JIT_LEVEL_NONE        0     /* no JIT */
#define ZEND_JIT_LEVEL_MINIMAL     1     /* minimal JIT (subroutine threading) */
#define ZEND_JIT_LEVEL_INLINE      2     /* selective inline threading */
#define ZEND_JIT_LEVEL_OPT_FUNC    3     /* optimized JIT based on Type-Inference */
#define ZEND_JIT_LEVEL_OPT_FUNCS   4     /* optimized JIT based on Type-Inference and call-tree */
#define ZEND_JIT_LEVEL_OPT_SCRIPT  5     /* optimized JIT based on Type-Inference and inner-procedure analysis */

#define ZEND_JIT_ON_SCRIPT_LOAD    0
#define ZEND_JIT_ON_FIRST_EXEC     1
#define ZEND_JIT_ON_PROF_REQUEST   2     /* compile the most frequently caled on first request functions */
#define ZEND_JIT_ON_HOT_COUNTERS   3     /* compile functions after N calls or loop iterations */
#define ZEND_JIT_ON_DOC_COMMENT    4     /* compile functions with "@jit" tag in doc-comments */
#define ZEND_JIT_ON_HOT_TRACE      5     /* trace functions after N calls or loop iterations */

#define ZEND_JIT_REG_ALLOC_LOCAL  (1<<0) /* local linear scan register allocation */
#define ZEND_JIT_REG_ALLOC_GLOBAL (1<<1) /* global linear scan register allocation */
#define ZEND_JIT_CPU_AVX          (1<<2) /* use AVX instructions, if available */

#define ZEND_JIT_DEFAULT_BUFFER_SIZE  "0"

#define ZEND_JIT_COUNTER_INIT         32531

#define ZEND_JIT_DEBUG_ASM       (1<<0)
#define ZEND_JIT_DEBUG_SSA       (1<<1)
#define ZEND_JIT_DEBUG_REG_ALLOC (1<<2)
#define ZEND_JIT_DEBUG_ASM_STUBS (1<<3)

#define ZEND_JIT_DEBUG_PERF      (1<<4)
#define ZEND_JIT_DEBUG_PERF_DUMP (1<<5)
#define ZEND_JIT_DEBUG_OPROFILE  (1<<6)
#define ZEND_JIT_DEBUG_VTUNE     (1<<7)

#define ZEND_JIT_DEBUG_GDB       (1<<8)
#define ZEND_JIT_DEBUG_SIZE      (1<<9)

#define ZEND_JIT_DEBUG_TRACE_START     (1<<12)
#define ZEND_JIT_DEBUG_TRACE_STOP      (1<<13)
#define ZEND_JIT_DEBUG_TRACE_COMPILED  (1<<14)
#define ZEND_JIT_DEBUG_TRACE_EXIT      (1<<15)
#define ZEND_JIT_DEBUG_TRACE_ABORT     (1<<16)
#define ZEND_JIT_DEBUG_TRACE_BLACKLIST (1<<17)
#define ZEND_JIT_DEBUG_TRACE_BYTECODE  (1<<18)
#define ZEND_JIT_DEBUG_TRACE_TSSA      (1<<19)
#define ZEND_JIT_DEBUG_TRACE_EXIT_INFO (1<<20)

#define ZEND_JIT_DEBUG_PERSISTENT      0x1f0 /* profile and debbuger flags can't be changed at run-time */

#define ZEND_JIT_TRACE_MAX_LENGTH        1024 /* max length of single trace */
#define ZEND_JIT_TRACE_MAX_EXITS          512 /* max number of side exits per trace */

#define ZEND_JIT_TRACE_MAX_FUNCS           30 /* max number of different functions in a single trace */
#define ZEND_JIT_TRACE_MAX_CALL_DEPTH      10 /* max depth of inlined calls */
#define ZEND_JIT_TRACE_MAX_RET_DEPTH        4 /* max depth of inlined returns */
#define ZEND_JIT_TRACE_MAX_LOOPS_UNROLL    10 /* max number of unrolled loops */

#define ZEND_JIT_TRACE_BAD_ROOT_SLOTS      64 /* number of slots in bad root trace cache */

typedef struct _zend_jit_trace_rec zend_jit_trace_rec;
typedef struct _zend_jit_trace_stack_frame zend_jit_trace_stack_frame;
typedef struct _sym_node zend_sym_node;

typedef struct _zend_jit_globals {
	bool enabled;
	bool on;
	uint8_t   trigger;
	uint8_t   opt_level;
	uint32_t  opt_flags;

	const char *options;
	zend_long   buffer_size;
	zend_long   debug;
	zend_long   bisect_limit;
	double      prof_threshold;
	zend_long   max_root_traces;       /* max number of root traces */
	zend_long   max_side_traces;       /* max number of side traces (per root trace) */
	zend_long   max_exit_counters;     /* max total number of side exits for all traces */
	zend_long   hot_loop;
	zend_long   hot_func;
	zend_long   hot_return;
	zend_long   hot_side_exit;         /* number of exits before taking side trace */
	zend_long   blacklist_root_trace;  /* number of attempts to JIT a root trace before blacklist it */
	zend_long   blacklist_side_trace;  /* number of attempts to JIT a side trace before blacklist it */
	zend_long   max_loop_unrolls;      /* max number of unrolled loops */
	zend_long   max_recursive_calls;   /* max number of recursive inlined call unrolls */
	zend_long   max_recursive_returns; /* max number of recursive inlined return unrolls */
	zend_long   max_polymorphic_calls; /* max number of inlined polymorphic calls */

	zend_sym_node *symbols;            /* symbols for disassembler */

	bool tracing;

	zend_jit_trace_rec *current_trace;
	zend_jit_trace_stack_frame *current_frame;

	const zend_op *bad_root_cache_opline[ZEND_JIT_TRACE_BAD_ROOT_SLOTS];
	uint8_t bad_root_cache_count[ZEND_JIT_TRACE_BAD_ROOT_SLOTS];
	uint8_t bad_root_cache_stop[ZEND_JIT_TRACE_BAD_ROOT_SLOTS];
	uint32_t bad_root_slot;

	uint8_t  *exit_counters;
} zend_jit_globals;

#ifdef ZTS
# define JIT_G(v) ZEND_TSRMG(jit_globals_id, zend_jit_globals *, v)
extern int jit_globals_id;
#else
# define JIT_G(v) (jit_globals.v)
extern zend_jit_globals jit_globals;
#endif

ZEND_EXT_API int  zend_jit_op_array(zend_op_array *op_array, zend_script *script);
ZEND_EXT_API int  zend_jit_script(zend_script *script);
ZEND_EXT_API void zend_jit_unprotect(void);
ZEND_EXT_API void zend_jit_protect(void);
ZEND_EXT_API void zend_jit_init(void);
ZEND_EXT_API int  zend_jit_config(zend_string *jit_options, int stage);
ZEND_EXT_API int  zend_jit_debug_config(zend_long old_val, zend_long new_val, int stage);
ZEND_EXT_API int  zend_jit_check_support(void);
ZEND_EXT_API int  zend_jit_startup(void *jit_buffer, size_t size, bool reattached);
ZEND_EXT_API void zend_jit_shutdown(void);
ZEND_EXT_API void zend_jit_activate(void);
ZEND_EXT_API void zend_jit_deactivate(void);
ZEND_EXT_API void zend_jit_status(zval *ret);
ZEND_EXT_API void zend_jit_restart(void);

typedef struct _zend_lifetime_interval zend_lifetime_interval;
typedef struct _zend_life_range zend_life_range;

struct _zend_life_range {
	uint32_t         start;
	uint32_t         end;
	zend_life_range *next;
};

#define ZREG_FLAGS_SHIFT    8

#define ZREG_STORE          (1<<0)
#define ZREG_LOAD           (1<<1)
#define ZREG_LAST_USE       (1<<2)
#define ZREG_SPLIT          (1<<3)

struct _zend_lifetime_interval {
	int                     ssa_var;
	union {
		struct {
		ZEND_ENDIAN_LOHI_3(
			int8_t          reg,
			uint8_t         flags,
			uint16_t        reserved
		)};
		uint32_t            reg_flags;
	};
	zend_life_range         range;
	zend_lifetime_interval *hint;
	zend_lifetime_interval *used_as_hint;
	zend_lifetime_interval *list_next;
};

#endif /* HAVE_JIT_H */