2222#include "jit/ir/ir_builder.h"
2323#include "jit/tls/zend_jit_tls.h"
2424
25- #if defined(IR_TARGET_X86)
26- # define IR_REG_SP 4 /* IR_REG_RSP */
27- # define IR_REG_FP 5 /* IR_REG_RBP */
28- # define ZREG_FP 6 /* IR_REG_RSI */
29- # define ZREG_IP 7 /* IR_REG_RDI */
30- # define ZREG_FIRST_FPR 8
31- # define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<6) | (1<<7)) /* all preserved registers */
32- # if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL
33- # error
34- # endif
35- #elif defined(IR_TARGET_X64)
36- # define IR_REG_SP 4 /* IR_REG_RSP */
37- # define IR_REG_FP 5 /* IR_REG_RBP */
38- # if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL
39- /* Use the first two arg registers of the preserve_none calling convention for FP/IP
40- * https://github.com/llvm/llvm-project/blob/68bfe91b5a34f80dbcc4f0a7fa5d7aa1cdf959c2/llvm/lib/Target/X86/X86CallingConv.td#L1029 */
41- # define ZREG_FP 12 /* IR_REG_R12 */
42- # define ZREG_IP 13 /* IR_REG_R13 */
43- # else
44- # define ZREG_FP 14 /* IR_REG_R14 */
45- # define ZREG_IP 15 /* IR_REG_R15 */
46- # endif
47- # define ZREG_FIRST_FPR 16
48- # if defined(_WIN64)
49- # define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<6) | (1<<7) | (1<<12) | (1<<13) | (1<<14) | (1<<15))
50- /*
51- # define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<6) | (1<<7) | (1<<12) | (1<<13) | (1<<14) | (1<<15) | \
52- (1<<(16+6)) | (1<<(16+7)) | (1<<(16+8)) | (1<<(16+9)) | (1<<(16+10)) | \
53- (1<<(16+11)) | (1<<(16+12)) | (1<<(16+13)) | (1<<(16+14)) | (1<<(16+15)))
54- */
55- # define IR_SHADOW_ARGS 32
56- # else
57- # define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<12) | (1<<13) | (1<<14) | (1<<15)) /* all preserved registers */
58- # endif
59- #elif defined(IR_TARGET_AARCH64)
60- # define IR_REG_SP 31 /* IR_REG_RSP */
61- # define IR_REG_LR 30 /* IR_REG_X30 */
62- # define IR_REG_FP 29 /* IR_REG_X29 */
63- # if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL
64- /* Use the first two arg registers of the preserve_none calling convention for FP/IP
65- * https://github.com/llvm/llvm-project/blob/68bfe91b5a34f80dbcc4f0a7fa5d7aa1cdf959c2/llvm/lib/Target/AArch64/AArch64CallingConvention.td#L541 */
66- # define ZREG_FP 20 /* IR_REG_X20 */
67- # define ZREG_IP 21 /* IR_REG_X21 */
68- # else
69- # define ZREG_FP 27 /* IR_REG_X27 */
70- # define ZREG_IP 28 /* IR_REG_X28 */
71- # endif
72- # define ZREG_FIRST_FPR 32
73- # define IR_REGSET_PRESERVED ((1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23) | \
74- (1<<24) | (1<<25) | (1<<26) | (1<<27) | (1<<28)) /* all preserved registers */
75- #else
76- # error "Unknown IR target"
77- #endif
78-
79- #define ZREG_RX ZREG_IP
25+ #include "Zend/zend_vm.h"
26+ #include "Zend/zend_exceptions.h"
27+ #include "Zend/zend_cpuinfo.h"
28+ #include "Zend/zend_observer.h"
29+ #include "Zend/zend_closures.h"
30+ #include "Zend/Optimizer/zend_inference.h"
31+ #include "Zend/Optimizer/zend_worklist.h"
32+ #include "zend_shared_alloc.h"
33+ #include "jit/zend_jit_internal.h"
34+ #include "jit/zend_jit_shared.h"
35+
36+ #include "jit/zend_jit_helpers.c"
8037
8138#define OPTIMIZE_FOR_SIZE 0
8239
174131# define ir_LOAD_L ir_LOAD_I32
175132#endif
176133
177- /* A helper structure to collect IT rers for the following use in (MERGE/PHI)_N */
178- typedef struct _ir_refs {
179- uint32_t count;
180- uint32_t limit;
181- ir_ref refs[] ZEND_ELEMENT_COUNT(count);
182- } ir_refs;
183-
184134#define ir_refs_size(_n) (offsetof(ir_refs, refs) + sizeof(ir_ref) * (_n))
185135#define ir_refs_init(_name, _n) _name = alloca(ir_refs_size(_n)); \
186136 do {_name->count = 0; _name->limit = (_n);} while (0)
@@ -199,7 +149,6 @@ static size_t zend_jit_trace_prologue_size = (size_t)-1;
199149static uint32_t allowed_opt_flags = 0;
200150static uint32_t default_mflags = 0;
201151#endif
202- static bool delayed_call_chain = false; // TODO: remove this var (use jit->delayed_call_level) ???
203152
204153#ifdef ZTS
205154static size_t tsrm_ls_cache_tcb_offset = 0;
@@ -237,112 +186,12 @@ static size_t tsrm_tls_offset = -1;
237186#define jit_RX(_field) \
238187 jit_CALL(jit_IP(jit), _field)
239188
240- #define JIT_STUBS(_) \
241- _(exception_handler, IR_SKIP_PROLOGUE) \
242- _(exception_handler_undef, IR_SKIP_PROLOGUE) \
243- _(exception_handler_free_op2, IR_SKIP_PROLOGUE) \
244- _(exception_handler_free_op1_op2, IR_SKIP_PROLOGUE) \
245- _(interrupt_handler, IR_SKIP_PROLOGUE) \
246- _(leave_function_handler, IR_SKIP_PROLOGUE) \
247- _(negative_shift, IR_SKIP_PROLOGUE) \
248- _(mod_by_zero, IR_SKIP_PROLOGUE) \
249- _(invalid_this, IR_SKIP_PROLOGUE) \
250- _(undefined_function, IR_SKIP_PROLOGUE) \
251- _(throw_cannot_pass_by_ref, IR_SKIP_PROLOGUE) \
252- _(icall_throw, IR_SKIP_PROLOGUE) \
253- _(leave_throw, IR_SKIP_PROLOGUE) \
254- _(hybrid_runtime_jit, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
255- _(hybrid_profile_jit, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
256- _(hybrid_func_hot_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
257- _(hybrid_loop_hot_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
258- _(hybrid_func_trace_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
259- _(hybrid_ret_trace_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
260- _(hybrid_loop_trace_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
261- _(trace_halt, IR_SKIP_PROLOGUE) \
262- _(trace_escape, IR_SKIP_PROLOGUE) \
263- _(trace_exit, IR_SKIP_PROLOGUE) \
264- _(undefined_offset, IR_FUNCTION | IR_FASTCALL_FUNC) \
265- _(undefined_key, IR_FUNCTION | IR_FASTCALL_FUNC) \
266- _(cannot_add_element, IR_FUNCTION | IR_FASTCALL_FUNC) \
267- _(assign_const, IR_FUNCTION | IR_FASTCALL_FUNC) \
268- _(assign_tmp, IR_FUNCTION | IR_FASTCALL_FUNC) \
269- _(assign_var, IR_FUNCTION | IR_FASTCALL_FUNC) \
270- _(assign_cv_noref, IR_FUNCTION | IR_FASTCALL_FUNC) \
271- _(assign_cv, IR_FUNCTION | IR_FASTCALL_FUNC) \
272- _(new_array, IR_FUNCTION | IR_FASTCALL_FUNC) \
273-
274- #define JIT_STUB_ID(name, flags) \
275- jit_stub_ ## name,
276-
277189#define JIT_STUB_FORWARD(name, flags) \
278190 static int zend_jit_ ## name ## _stub(zend_jit_ctx *jit);
279191
280192#define JIT_STUB(name, flags) \
281193 {JIT_STUB_PREFIX #name, zend_jit_ ## name ## _stub, flags},
282194
283- typedef enum _jit_stub_id {
284- JIT_STUBS(JIT_STUB_ID)
285- jit_last_stub
286- } jit_stub_id;
287-
288- typedef struct _zend_jit_reg_var {
289- ir_ref ref;
290- uint32_t flags;
291- } zend_jit_reg_var;
292-
293- typedef struct _zend_jit_ctx {
294- ir_ctx ctx;
295- const zend_op *last_valid_opline;
296- bool use_last_valid_opline;
297- bool track_last_valid_opline;
298- bool reuse_ip;
299- uint32_t delayed_call_level;
300- int b; /* current basic block number or -1 */
301- #ifdef ZTS
302- ir_ref tls;
303- #endif
304- ir_ref fp;
305- ir_ref poly_func_ref; /* restored from parent trace snapshot */
306- ir_ref poly_this_ref; /* restored from parent trace snapshot */
307- ir_ref trace_loop_ref;
308- ir_ref return_inputs;
309- const zend_op_array *op_array;
310- const zend_op_array *current_op_array;
311- zend_ssa *ssa;
312- zend_string *name;
313- ir_ref *bb_start_ref; /* PHP BB -> IR ref mapping */
314- ir_ref *bb_predecessors; /* PHP BB -> index in bb_edges -> IR refs of predessors */
315- ir_ref *bb_edges;
316- zend_jit_trace_info *trace;
317- zend_jit_reg_var *ra;
318- int delay_var;
319- ir_refs *delay_refs;
320- ir_ref eg_exception_addr;
321- HashTable addr_hash;
322- ir_ref stub_addr[jit_last_stub];
323- } zend_jit_ctx;
324-
325- typedef int8_t zend_reg;
326-
327- typedef struct _zend_jit_registers_buf {
328- #if defined(IR_TARGET_X64)
329- uint64_t gpr[16]; /* general purpose integer register */
330- double fpr[16]; /* floating point registers */
331- #elif defined(IR_TARGET_X86)
332- uint32_t gpr[8]; /* general purpose integer register */
333- double fpr[8]; /* floating point registers */
334- #elif defined (IR_TARGET_AARCH64)
335- uint64_t gpr[32]; /* general purpose integer register */
336- double fpr[32]; /* floating point registers */
337- #else
338- # error "Unknown IR target"
339- #endif
340- } zend_jit_registers_buf;
341-
342- /* Keep 32 exit points in a single code block */
343- #define ZEND_JIT_EXIT_POINTS_SPACING 4 // push byte + short jmp = bytes
344- #define ZEND_JIT_EXIT_POINTS_PER_GROUP 32 // number of continuous exit points
345-
346195static uint32_t zend_jit_exit_point_by_addr(const void *addr);
347196int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf *regs);
348197
@@ -369,17 +218,22 @@ typedef struct _zend_jit_stub {
369218
370219JIT_STUBS(JIT_STUB_FORWARD)
371220
221+ #define JIT_STUB_PREFIX "JIT$$"
222+
372223static const zend_jit_stub zend_jit_stubs[] = {
373224 JIT_STUBS(JIT_STUB)
374225};
375226
376- #if defined(_WIN32) || defined(IR_TARGET_AARCH64)
377- /* We keep addresses in SHM to share them between sepaeate processes (on Windows) or to support veneers (on AArch64) */
378- static void** zend_jit_stub_handlers = NULL;
227+ #ifdef ZEND_JIT_USE_RC_INFERENCE
228+ # define RC_MAY_BE_1(info) (((info) & (MAY_BE_RC1|MAY_BE_REF)) != 0)
229+ # define RC_MAY_BE_N(info) (((info) & (MAY_BE_RCN|MAY_BE_REF)) != 0)
379230#else
380- static void* zend_jit_stub_handlers[sizeof(zend_jit_stubs) / sizeof(zend_jit_stubs[0])];
231+ # define RC_MAY_BE_1(info) 1
232+ # define RC_MAY_BE_N(info) 1
381233#endif
382234
235+ #define BP_JIT_IS 6 /* Used for ISSET_ISEMPTY_DIM_OBJ. see BP_VAR_*defines in Zend/zend_compile.h */
236+
383237#if defined(IR_TARGET_AARCH64)
384238
385239# ifdef __FreeBSD__
0 commit comments