Skip to content

Commit 84aa8b8

Browse files
committed
Simplify frameless jit handler and fix wordpress issue
1 parent 56d521e commit 84aa8b8

File tree

1 file changed

+33
-43
lines changed

1 file changed

+33
-43
lines changed

ext/opcache/jit/zend_jit_ir.c

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4534,11 +4534,11 @@ static void jit_observer_fcall_begin(zend_jit_ctx *jit, ir_ref rx, ir_ref observ
45344534
ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_observer_fcall_begin_prechecked), rx, observer_handler);
45354535
}
45364536

4537-
static void jit_observer_fcall_end(zend_jit_ctx *jit, ir_ref rx, zend_jit_addr res_addr) {
4537+
static void jit_observer_fcall_end(zend_jit_ctx *jit, ir_ref rx, ir_ref res_ref) {
45384538
ir_ref has_end_observer = ir_IF(ir_EQ(rx, ir_LOAD_A(jit_EG(current_observed_frame))));
45394539
ir_IF_TRUE(has_end_observer);
45404540
ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_observer_fcall_end_prechecked),
4541-
rx, jit_ZVAL_ADDR(jit, res_addr));
4541+
rx, res_ref);
45424542
ir_MERGE_WITH_EMPTY_FALSE(has_end_observer);
45434543
}
45444544

@@ -10117,8 +10117,9 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1011710117
zend_jit_reset_last_valid_opline(jit);
1011810118

1011910119
// JIT: (zend_execute_internal ? zend_execute_internal : fbc->internal_function.handler)(call, ret);
10120+
ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
1012010121
if (zend_execute_internal) {
10121-
ir_CALL_2(IR_VOID, ir_CONST_FUNC(zend_execute_internal), rx, jit_ZVAL_ADDR(jit, res_addr));
10122+
ir_CALL_2(IR_VOID, ir_CONST_FUNC(zend_execute_internal), rx, res_ref);
1012210123
} else {
1012310124
if (func) {
1012410125
func_ptr = ir_CONST_FC_FUNC(func->internal_function.handler);
@@ -10128,11 +10129,11 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1012810129
func_ptr = ir_CAST_FC_FUNC(func_ptr);
1012910130
#endif
1013010131
}
10131-
ir_CALL_2(IR_VOID, func_ptr, rx, jit_ZVAL_ADDR(jit, res_addr));
10132+
ir_CALL_2(IR_VOID, func_ptr, rx, res_ref);
1013210133
}
1013310134

1013410135
if (may_have_observer) {
10135-
jit_observer_fcall_end(jit, rx, res_addr);
10136+
jit_observer_fcall_end(jit, rx, res_ref);
1013610137
}
1013710138

1013810139
// JIT: EG(current_execute_data) = execute_data;
@@ -10844,9 +10845,7 @@ static int zend_jit_return(zend_jit_ctx *jit, const zend_op *opline, const zend_
1084410845
}
1084510846
op1_addr = dst;
1084610847
}
10847-
ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_observer_fcall_end),
10848-
jit_FP(jit),
10849-
jit_ZVAL_ADDR(jit, op1_addr));
10848+
jit_observer_fcall_end(jit, jit_FP(jit), jit_ZVAL_ADDR(jit, op1_addr));
1085010849
}
1085110850

1085210851
// JIT: if (!EX(return_value))
@@ -16762,38 +16761,37 @@ static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa,
1676216761
return 1;
1676316762
}
1676416763

16765-
struct jit_frameless_observer_data {
16766-
ir_ref if_unobserved;
16767-
ir_ref reused_jit_ip;
16768-
};
16769-
16770-
static struct jit_frameless_observer_data jit_frameless_observer_begin(zend_jit_ctx *jit, int checked_stack, const zend_op *opline, ir_ref op1_ref, uint32_t op1_info, ir_ref op2_ref, uint32_t op2_info, ir_ref op1_data_ref, uint32_t op1_data_info) {
16771-
struct jit_frameless_observer_data data;
16764+
static ir_ref jit_frameless_observer(zend_jit_ctx *jit, int checked_stack, const zend_op *opline, ir_ref op1_ref, uint32_t op1_info, ir_ref op2_ref, uint32_t op2_info, ir_ref op1_data_ref, uint32_t op1_data_info, ir_ref res_ref) {
1677216765
// JIT: zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc))
1677316766
ir_ref observer_handler;
1677416767
zend_function *fbc = ZEND_FLF_FUNC(opline);
1677516768
// Not need for runtime cache or generator checks here, we just need if_unobserved
16776-
data.if_unobserved = jit_observer_fcall_is_unobserved_start(jit, fbc, &observer_handler, IR_UNUSED, IR_UNUSED).if_unobserved;
16769+
ir_ref if_unobserved = jit_observer_fcall_is_unobserved_start(jit, fbc, &observer_handler, IR_UNUSED, IR_UNUSED).if_unobserved;
1677716770

16778-
// push args to a valid call frame, without copying
16771+
// push args to a valid call frame, without copying (flf call takes care of freeing args)
1677916772
bool track_last_valid_opline = jit->track_last_valid_opline;
16773+
bool use_last_valid_opline = jit->use_last_valid_opline;
1678016774
const zend_op *last_valid_opline = jit->last_valid_opline;
1678116775
bool reuse_ip = jit->reuse_ip;
1678216776
if (reuse_ip) {
16783-
data.reused_jit_ip = jit_IP(jit);
16777+
ir_ref call = jit_CALL(jit_FP(jit), call);
16778+
ir_STORE(jit_CALL(jit_IP(jit), prev_execute_data), ir_LOAD_A(call));
16779+
ir_STORE(call, jit_IP(jit));
1678416780
}
1678516781
zend_jit_push_call_frame(jit, opline, NULL, fbc, 0, 0, checked_stack, ir_CONST_ADDR(fbc), IR_NULL);
16786-
// yes, we'll temporarily reuse the IP, but we don't want to handle this via the reuse_ip mechanism for simiplicity - we just reset IP to original in end
16782+
// yes, we'll temporarily reuse the IP, but we must not handle this via the reuse_ip mechanism - we just reset IP to original in end
16783+
// the primary issue here is that this code is just executed conditionally while the reuse mechanisms are meant to be global
1678716784
jit->track_last_valid_opline = track_last_valid_opline;
16785+
jit->use_last_valid_opline = use_last_valid_opline;
1678816786
jit->last_valid_opline = last_valid_opline;
1678916787
jit->reuse_ip = reuse_ip;
1679016788

1679116789
// push all args
1679216790
uint32_t call_num_args = ZEND_FLF_NUM_ARGS(opline->opcode);
1679316791
switch (call_num_args) {
16794-
case 3: jit_ZVAL_COPY(jit, ZEND_ADDR_MEM_ZVAL(ZREG_RX, EX_NUM_TO_VAR(3)), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op1_data_ref), op1_data_info, 0); ZEND_FALLTHROUGH;
16795-
case 2: jit_ZVAL_COPY(jit, ZEND_ADDR_MEM_ZVAL(ZREG_RX, EX_NUM_TO_VAR(2)), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op2_ref), op2_info, 0); ZEND_FALLTHROUGH;
16796-
case 1: jit_ZVAL_COPY(jit, ZEND_ADDR_MEM_ZVAL(ZREG_RX, EX_NUM_TO_VAR(1)), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op1_ref), op1_info, 0);
16792+
case 3: jit_ZVAL_COPY(jit, ZEND_ADDR_MEM_ZVAL(ZREG_RX, EX_NUM_TO_VAR(2)), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op1_data_ref), op1_data_info, 0); ZEND_FALLTHROUGH;
16793+
case 2: jit_ZVAL_COPY(jit, ZEND_ADDR_MEM_ZVAL(ZREG_RX, EX_NUM_TO_VAR(1)), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op2_ref), op2_info, 0); ZEND_FALLTHROUGH;
16794+
case 1: jit_ZVAL_COPY(jit, ZEND_ADDR_MEM_ZVAL(ZREG_RX, EX_NUM_TO_VAR(0)), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op1_ref), op1_info, 0);
1679716795
}
1679816796

1679916797
// Make call frame externally visible
@@ -16803,12 +16801,10 @@ static struct jit_frameless_observer_data jit_frameless_observer_begin(zend_jit_
1680316801

1680416802
jit_observer_fcall_begin(jit, rx, observer_handler);
1680516803

16806-
return data;
16807-
}
16804+
// JIT: fbc->internal_function.handler(new_frame, return_value)
16805+
ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(fbc->internal_function.handler), rx, res_ref);
1680816806

16809-
static ir_ref jit_frameless_observer_end(zend_jit_ctx *jit, struct jit_frameless_observer_data *data, const zend_op *opline, zend_jit_addr res_addr) {
16810-
ir_ref rx = jit_IP(jit);
16811-
jit_observer_fcall_end(jit, rx, res_addr);
16807+
jit_observer_fcall_end(jit, rx, res_ref);
1681216808

1681316809
ir_STORE(jit_EG(current_execute_data), ir_LOAD_A(jit_CALL(rx, prev_execute_data)));
1681416810

@@ -16837,14 +16833,16 @@ static ir_ref jit_frameless_observer_end(zend_jit_ctx *jit, struct jit_frameless
1683716833
ir_MERGE_WITH(allocated_path);
1683816834
}
1683916835

16840-
if (jit->reuse_ip) {
16841-
jit_STORE_IP(jit, data->reused_jit_ip);
16836+
if (reuse_ip) {
16837+
jit_STORE_IP(jit, ir_LOAD_A(jit_CALL(jit_FP(jit), call)));
16838+
ir_STORE(jit_CALL(jit_FP(jit), call), ir_LOAD_A(jit_CALL(jit_IP(jit), prev_execute_data)));
1684216839
} else {
16843-
jit_SET_EX_OPLINE(jit, opline);
16840+
// Note: conditional (if_unobserved) opline, zend_jit_set_last_valid_opline() may only be called if the opline is actually unconditionally updated
16841+
jit_STORE_IP(jit, ir_CONST_ADDR(jit->last_valid_opline ? jit->last_valid_opline : opline));
1684416842
}
1684516843

1684616844
ir_ref skip = ir_END();
16847-
ir_IF_TRUE(data->if_unobserved);
16845+
ir_IF_TRUE(if_unobserved);
1684816846
return skip;
1684916847
}
1685016848

@@ -16859,9 +16857,7 @@ static void jit_frameless_icall0(zend_jit_ctx *jit, int checked_stack, const zen
1685916857

1686016858
ir_ref skip_observer = IR_UNUSED;
1686116859
if (ZEND_OBSERVER_ENABLED) {
16862-
struct jit_frameless_observer_data observer_data = jit_frameless_observer_begin(jit, checked_stack, opline, IR_UNUSED, 0, IR_UNUSED, 0, IR_UNUSED, 0);
16863-
ir_CALL_1(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref);
16864-
skip_observer = jit_frameless_observer_end(jit, &observer_data, opline, res_addr);
16860+
skip_observer = jit_frameless_observer(jit, checked_stack, opline, IR_UNUSED, 0, IR_UNUSED, 0, IR_UNUSED, 0, res_ref);
1686516861
}
1686616862
ir_CALL_1(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref);
1686716863
if (skip_observer != IR_UNUSED) {
@@ -16895,9 +16891,7 @@ static void jit_frameless_icall1(zend_jit_ctx *jit, int checked_stack, const zen
1689516891

1689616892
ir_ref skip_observer = IR_UNUSED;
1689716893
if (ZEND_OBSERVER_ENABLED) {
16898-
struct jit_frameless_observer_data observer_data = jit_frameless_observer_begin(jit, checked_stack, opline, op1_ref, op1_info, IR_UNUSED, 0, IR_UNUSED, 0);
16899-
ir_CALL_2(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref);
16900-
skip_observer = jit_frameless_observer_end(jit, &observer_data, opline, res_addr);
16894+
skip_observer = jit_frameless_observer(jit, checked_stack, opline, op1_ref, op1_info, IR_UNUSED, 0, IR_UNUSED, 0, res_ref);
1690116895
}
1690216896
ir_CALL_2(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref);
1690316897
if (skip_observer != IR_UNUSED) {
@@ -16944,9 +16938,7 @@ static void jit_frameless_icall2(zend_jit_ctx *jit, int checked_stack, const zen
1694416938

1694516939
ir_ref skip_observer = IR_UNUSED;
1694616940
if (ZEND_OBSERVER_ENABLED) {
16947-
struct jit_frameless_observer_data observer_data = jit_frameless_observer_begin(jit, checked_stack, opline, op1_ref, op1_info, op2_ref, op2_info, IR_UNUSED, 0);
16948-
ir_CALL_3(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref, op2_ref);
16949-
skip_observer = jit_frameless_observer_end(jit, &observer_data, opline, res_addr);
16941+
skip_observer = jit_frameless_observer(jit, checked_stack, opline, op1_ref, op1_info, op2_ref, op2_info, IR_UNUSED, 0, res_ref);
1695016942
}
1695116943
ir_CALL_3(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref, op2_ref);
1695216944
if (skip_observer != IR_UNUSED) {
@@ -17011,9 +17003,7 @@ static void jit_frameless_icall3(zend_jit_ctx *jit, int checked_stack, const zen
1701117003

1701217004
ir_ref skip_observer = IR_UNUSED;
1701317005
if (ZEND_OBSERVER_ENABLED) {
17014-
struct jit_frameless_observer_data observer_data = jit_frameless_observer_begin(jit, checked_stack, opline, op1_ref, op1_info, op2_ref, op2_info, op3_ref, op1_data_info);
17015-
ir_CALL_4(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref, op2_ref, op3_ref);
17016-
skip_observer = jit_frameless_observer_end(jit, &observer_data, opline, res_addr);
17006+
skip_observer = jit_frameless_observer(jit, checked_stack, opline, op1_ref, op1_info, op2_ref, op2_info, op3_ref, op1_data_info, res_ref);
1701717007
}
1701817008
ir_CALL_4(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref, op2_ref, op3_ref);
1701917009
if (skip_observer != IR_UNUSED) {

0 commit comments

Comments
 (0)