Skip to content

Commit 2bf5ba9

Browse files
committed
Fix IR JIT for CALL VM with global register variables
1 parent 61c114b commit 2bf5ba9

File tree

2 files changed

+68
-89
lines changed

2 files changed

+68
-89
lines changed

ext/opcache/jit/zend_jit_ir.c

Lines changed: 67 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,35 @@
1919
#include "jit/ir/ir.h"
2020

2121
#if defined(IR_TARGET_X86)
22-
# define IR_REG_SP 4 /* IR_REG_RSP */
23-
# define ZREG_FP 6 /* IR_REG_RSI */
24-
# define ZREG_IP 7 /* IR_REG_RDI */
25-
# define ZREG_FIRST_FPR 8
22+
# define IR_REG_SP 4 /* IR_REG_RSP */
23+
# define ZREG_FP 6 /* IR_REG_RSI */
24+
# define ZREG_IP 7 /* IR_REG_RDI */
25+
# define ZREG_FIRST_FPR 8
26+
# define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<6) | (1<<7)) /* all preserved registers */
2627
#elif defined(IR_TARGET_X64)
27-
# define IR_REG_SP 4 /* IR_REG_RSP */
28-
# define ZREG_FP 14 /* IR_REG_R14 */
29-
# define ZREG_IP 15 /* IR_REG_R15 */
30-
# define ZREG_FIRST_FPR 16
28+
# define IR_REG_SP 4 /* IR_REG_RSP */
29+
# define ZREG_FP 14 /* IR_REG_R14 */
30+
# define ZREG_IP 15 /* IR_REG_R15 */
31+
# define ZREG_FIRST_FPR 16
32+
# define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<12) | (1<<13) | (1<<14) | (1<<15)) /* all preserved registers */
3133
#elif defined(IR_TARGET_AARCH64)
32-
# define IR_REG_SP 31 /* IR_REG_RSP */
33-
# define ZREG_FP 27 /* IR_REG_X27 */
34-
# define ZREG_IP 28 /* IR_REG_X28 */
35-
# define ZREG_FIRST_FPR 32
34+
# define IR_REG_SP 31 /* IR_REG_RSP */
35+
# define ZREG_FP 27 /* IR_REG_X27 */
36+
# define ZREG_IP 28 /* IR_REG_X28 */
37+
# define ZREG_FIRST_FPR 32
38+
# define IR_REGSET_PRESERVED ((1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23) | (1<<24) | \
39+
(1<<25) | (1<<26) | (1<<27) | (1<<29) | (1<<30)) /* all preserved registers */
3640
#else
3741
# error "Unknown IR target"
3842
#endif
3943

40-
#define ZREG_RX ZREG_IP
44+
#define ZREG_RX ZREG_IP
45+
46+
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
47+
# define IR_REGSET_PHP_FIXED ((1<<ZREG_FP) | (1<<ZREG_IP) | (1<<5)) /* prevent %rbp (%r5) usage */
48+
#else
49+
# define IR_REGSET_PHP_FIXED ((1<<ZREG_FP) | (1<<ZREG_IP))
50+
#endif
4151

4252
#ifdef ZEND_ENABLE_ZVAL_LONG64
4353
# define IR_PHP_LONG IR_I64
@@ -47,14 +57,6 @@
4757
# define ir_const_php_long ir_const_i32
4858
#endif
4959

50-
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
51-
# define IR_REGSET_PHP_FIXED \
52-
((1<<ZREG_FP) | (1<<ZREG_IP) | (1<<5)) /* prevent %rbp (%r5) usage */
53-
#else
54-
# define IR_REGSET_PHP_FIXED \
55-
((1<<ZREG_FP) | (1<<ZREG_IP))
56-
#endif
57-
5860
static size_t zend_jit_trace_prologue_size = (size_t)-1;
5961
static uint32_t allowed_opt_flags = 0;
6062
static bool delayed_call_chain = 0; // TODO: remove this var (use jit->delayed_call_level) ???
@@ -1390,7 +1392,7 @@ static int zend_jit_set_ip(zend_jit_ctx *jit, const zend_op *target)
13901392
if (jit->last_valid_opline) {
13911393
zend_jit_use_last_valid_opline(jit);
13921394
if (jit->last_valid_opline != target) {
1393-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
1395+
if (GCC_GLOBAL_REGS) {
13941396
ref = zend_jit_ip(jit);
13951397
} else {
13961398
addr = zend_jit_ex_opline_addr(jit);
@@ -1403,14 +1405,14 @@ static int zend_jit_set_ip(zend_jit_ctx *jit, const zend_op *target)
14031405
ref = ir_fold2(&jit->ctx, IR_OPT(IR_SUB, IR_ADDR), ref,
14041406
zend_jit_const_addr(jit, (uintptr_t)jit->last_valid_opline - (uintptr_t)target));
14051407
}
1406-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
1408+
if (GCC_GLOBAL_REGS) {
14071409
zend_jit_store_ip(jit, ref);
14081410
} else {
14091411
zend_jit_store(jit, addr, ref);
14101412
}
14111413
}
14121414
} else {
1413-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
1415+
if (GCC_GLOBAL_REGS) {
14141416
zend_jit_store_ip(jit,
14151417
zend_jit_const_addr(jit, (uintptr_t)target));
14161418
} else {
@@ -2572,7 +2574,7 @@ static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit)
25722574
{
25732575
ir_ref ref, if_timeout, timeout_path, if_exception, exception_path;
25742576

2575-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
2577+
if (GCC_GLOBAL_REGS) {
25762578
// EX(opline) = opline
25772579
zend_jit_store(jit,
25782580
zend_jit_ex_opline_addr(jit),
@@ -2612,10 +2614,7 @@ static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit)
26122614
zend_jit_store_ip(jit, ref);
26132615
}
26142616

2615-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
2616-
zend_jit_tailcall_0(jit,
2617-
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));
2618-
} else if (GCC_GLOBAL_REGS) {
2617+
if (GCC_GLOBAL_REGS) {
26192618
zend_jit_tailcall_0(jit,
26202619
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));
26212620
} else {
@@ -2628,14 +2627,14 @@ static int zend_jit_leave_function_handler_stub(zend_jit_ctx *jit)
26282627
{
26292628
ir_ref call_info = zend_jit_load_at_offset(jit, IR_U32,
26302629
zend_jit_fp(jit), offsetof(zend_execute_data, This.u1.type_info));
2630+
ir_ref if_top = zend_jit_if(jit,
2631+
ir_fold2(&jit->ctx, IR_OPT(IR_AND, IR_U32),
2632+
call_info,
2633+
ir_const_u32(&jit->ctx, ZEND_CALL_TOP)));
26312634

2632-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
2633-
ir_ref if_top = zend_jit_if(jit,
2634-
ir_fold2(&jit->ctx, IR_OPT(IR_AND, IR_U32),
2635-
call_info,
2636-
ir_const_u32(&jit->ctx, ZEND_CALL_TOP)));
2635+
zend_jit_if_false(jit, if_top);
26372636

2638-
zend_jit_if_false(jit, if_top);
2637+
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
26392638
zend_jit_call_1(jit, IR_VOID,
26402639
zend_jit_const_func_addr(jit, (uintptr_t)zend_jit_leave_nested_func_helper, IR_CONST_FASTCALL_FUNC),
26412640
call_info);
@@ -2644,26 +2643,30 @@ static int zend_jit_leave_function_handler_stub(zend_jit_ctx *jit)
26442643
zend_jit_ex_opline_addr(jit)));
26452644
zend_jit_tailcall_0(jit,
26462645
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));
2647-
2648-
zend_jit_if_true(jit, if_top);
2649-
zend_jit_call_1(jit, IR_VOID,
2650-
zend_jit_const_func_addr(jit, (uintptr_t)zend_jit_leave_top_func_helper, IR_CONST_FASTCALL_FUNC),
2646+
} else if (GCC_GLOBAL_REGS) {
2647+
zend_jit_tailcall_1(jit,
2648+
zend_jit_const_func_addr(jit, (uintptr_t)zend_jit_leave_nested_func_helper, IR_CONST_FASTCALL_FUNC),
26512649
call_info);
2652-
zend_jit_tailcall_0(jit,
2653-
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));
26542650
} else {
2655-
ir_ref if_top = zend_jit_if(jit,
2656-
ir_fold2(&jit->ctx, IR_OPT(IR_AND, IR_U32),
2657-
call_info,
2658-
ir_const_u32(&jit->ctx, ZEND_CALL_TOP)));
2659-
2660-
zend_jit_if_false(jit, if_top);
26612651
zend_jit_tailcall_2(jit,
26622652
zend_jit_const_func_addr(jit, (uintptr_t)zend_jit_leave_nested_func_helper, IR_CONST_FASTCALL_FUNC),
26632653
call_info,
26642654
zend_jit_fp(jit));
2655+
}
2656+
2657+
zend_jit_if_true(jit, if_top);
26652658

2666-
zend_jit_if_true(jit, if_top);
2659+
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
2660+
zend_jit_call_1(jit, IR_VOID,
2661+
zend_jit_const_func_addr(jit, (uintptr_t)zend_jit_leave_top_func_helper, IR_CONST_FASTCALL_FUNC),
2662+
call_info);
2663+
zend_jit_tailcall_0(jit,
2664+
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));
2665+
} else if (GCC_GLOBAL_REGS) {
2666+
zend_jit_tailcall_1(jit,
2667+
zend_jit_const_func_addr(jit, (uintptr_t)zend_jit_leave_top_func_helper, IR_CONST_FASTCALL_FUNC),
2668+
call_info);
2669+
} else {
26672670
zend_jit_tailcall_2(jit,
26682671
zend_jit_const_func_addr(jit, (uintptr_t)zend_jit_leave_top_func_helper, IR_CONST_FASTCALL_FUNC),
26692672
call_info,
@@ -3135,10 +3138,8 @@ static int zend_jit_trace_halt_stub(zend_jit_ctx *jit)
31353138
zend_jit_tailcall_0(jit,
31363139
zend_jit_const_func_addr(jit, (uintptr_t)zend_jit_halt_op->handler, IR_CONST_FASTCALL_FUNC));
31373140
} else if (GCC_GLOBAL_REGS) {
3138-
ZEND_ASSERT(0 && "NIY");
3139-
//??? | add r4, SPAD // stack alignment
3140-
//??? | xor IP, IP // PC must be zero
3141-
//??? | ret
3141+
zend_jit_store_ip(jit, IR_NULL);
3142+
zend_jit_ret(jit, IR_UNUSED);
31423143
} else {
31433144
zend_jit_ret(jit, ir_const_i32(&jit->ctx, -1)); // ZEND_VM_RETURN
31443145
}
@@ -3147,13 +3148,9 @@ static int zend_jit_trace_halt_stub(zend_jit_ctx *jit)
31473148

31483149
static int zend_jit_trace_escape_stub(zend_jit_ctx *jit)
31493150
{
3150-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
3151+
if (GCC_GLOBAL_REGS) {
31513152
zend_jit_tailcall_0(jit,
31523153
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));
3153-
} else if (GCC_GLOBAL_REGS) {
3154-
ZEND_ASSERT(0 && "NIY");
3155-
//??? | add r4, SPAD // stack alignment
3156-
//??? | JMP_IP
31573154
} else {
31583155
zend_jit_ret(jit, ir_const_i32(&jit->ctx, 1)); // ZEND_VM_ENTER
31593156
}
@@ -3186,15 +3183,8 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit)
31863183
ref = zend_jit_load(jit, IR_ADDR,
31873184
zend_jit_ex_opline_addr(jit));
31883185
zend_jit_store_ip(jit, ref);
3189-
}
3190-
3191-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
31923186
zend_jit_tailcall_0(jit,
31933187
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));
3194-
} else if (GCC_GLOBAL_REGS) {
3195-
ZEND_ASSERT(0 && "NIY");
3196-
// | add r4, SPAD // stack alignment
3197-
// | JMP_IP
31983188
} else {
31993189
zend_jit_ret(jit, ir_const_i32(&jit->ctx, 1)); // ZEND_VM_ENTER
32003190
}
@@ -3220,7 +3210,7 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit)
32203210
}
32213211

32223212
addr = zend_jit_orig_opline_handler(jit);
3223-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID || GCC_GLOBAL_REGS) {
3213+
if (GCC_GLOBAL_REGS) {
32243214
zend_jit_tailcall_0(jit, addr);
32253215
} else {
32263216
#if defined(IR_TARGET_X86)
@@ -3357,16 +3347,11 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags)
33573347
jit->ctx.flags |= IR_FUNCTION;
33583348
/* Stack must be 16 byte aligned */
33593349
jit->ctx.fixed_stack_frame_size = sizeof(void*) * 7; /* TODO: reduce stack size ??? */
3360-
#if defined(IR_TARGET_X86)
3361-
jit->ctx.fixed_save_regset = (1<<3) | (1<<5) | (1<<6) | (1<<7); /* all preserved registers ??? */
3362-
#elif defined(IR_TARGET_X64)
3363-
jit->ctx.fixed_save_regset = (1<<3) | (1<<5) | (1<<12) | (1<<13) | (1<<14) | (1<<15); /* all preserved registers ??? */
3364-
#elif defined(IR_TARGET_AARCH64)
3365-
jit->ctx.fixed_save_regset = (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23) | (1<<24)
3366-
| (1<<25) | (1<<26) | (1<<27) | (1<<27) | (1<<28) | (1<<29) | (1<<30); /* all preserved registers ??? */
3367-
#else
3368-
ZEND_ASSERT(0 && "NIY");
3369-
#endif
3350+
if (GCC_GLOBAL_REGS) {
3351+
jit->ctx.fixed_save_regset = IR_REGSET_PRESERVED & ~((1<<ZREG_FP) | (1<<ZREG_IP));
3352+
} else {
3353+
jit->ctx.fixed_save_regset = IR_REGSET_PRESERVED;
3354+
}
33703355
} else {
33713356
#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE
33723357
jit->ctx.fixed_stack_red_zone = ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE;
@@ -3375,9 +3360,6 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags)
33753360
jit->ctx.fixed_stack_red_zone = 0;
33763361
jit->ctx.fixed_stack_frame_size = 0;
33773362
#endif
3378-
if (!GCC_GLOBAL_REGS) {
3379-
jit->ctx.fixed_save_regset = 1 << ZREG_FP;
3380-
}
33813363
}
33823364
}
33833365
jit->ctx.fixed_regset = IR_REGSET_PHP_FIXED;
@@ -4371,15 +4353,15 @@ static int zend_jit_cmp_ip(zend_jit_ctx *jit, ir_op op, const zend_op *next_opli
43714353
ir_ref ref;
43724354

43734355
#if 1
4374-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
4356+
if (GCC_GLOBAL_REGS) {
43754357
ref = zend_jit_ip32(jit);
43764358
} else {
43774359
ref = zend_jit_ex_opline_addr(jit);
43784360
ref = zend_jit_load(jit, IR_U32, ref);
43794361
}
43804362
ref = ir_fold2(&jit->ctx, IR_OPT(op, IR_BOOL), ref, ir_const_u32(&jit->ctx, (uint32_t)(uintptr_t)next_opline));
43814363
#else
4382-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
4364+
if (GCC_GLOBAL_REGS) {
43834365
ref = zend_jit_ip(jit);
43844366
} else {
43854367
ref = zend_jit_ex_opline_addr(jit);
@@ -11846,10 +11828,7 @@ static int zend_jit_leave_func(zend_jit_ctx *jit,
1184611828
}
1184711829
}
1184811830

11849-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
11850-
zend_jit_tailcall_0(jit,
11851-
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));
11852-
} else if (GCC_GLOBAL_REGS) {
11831+
if (GCC_GLOBAL_REGS) {
1185311832
zend_jit_tailcall_0(jit,
1185411833
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));
1185511834
} else {
@@ -17564,9 +17543,9 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr
1756417543
zend_jit_stub_addr(jit, jit_stub_trace_halt));
1756517544
}
1756617545
} else if (GCC_GLOBAL_REGS) {
17567-
ZEND_ASSERT(0 && "NIY");
17568-
//??? | test IP, IP
17569-
//??? | je ->trace_halt
17546+
zend_jit_guard(jit,
17547+
zend_jit_ip(jit),
17548+
zend_jit_stub_addr(jit, jit_stub_trace_halt));
1757017549
} else {
1757117550
zend_jit_guard(jit,
1757217551
ir_fold2(&jit->ctx, IR_OPT(IR_GE, IR_BOOL),
@@ -17797,7 +17776,7 @@ static int zend_jit_trace_end_loop(zend_jit_ctx *jit, int loop_ref, const void *
1779717776

1779817777
static int zend_jit_trace_return(zend_jit_ctx *jit, bool original_handler, const zend_op *opline)
1779917778
{
17800-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID || GCC_GLOBAL_REGS) {
17779+
if (GCC_GLOBAL_REGS) {
1780117780
if (!original_handler) {
1780217781
zend_jit_tailcall_0(jit,
1780317782
zend_jit_load(jit, IR_ADDR, zend_jit_ip(jit)));

0 commit comments

Comments
 (0)