@@ -3069,8 +3069,6 @@ static void zend_jit_setup_disasm(void)
3069
3069
REGISTER_HELPER(zend_jit_pre_dec_obj_helper);
3070
3070
REGISTER_HELPER(zend_jit_post_dec_obj_helper);
3071
3071
REGISTER_HELPER(zend_jit_rope_end);
3072
- REGISTER_HELPER(zend_jit_observed_frameless_helper_push);
3073
- REGISTER_HELPER(zend_jit_observed_frameless_helper_call);
3074
3072
3075
3073
#ifndef ZTS
3076
3074
REGISTER_DATA(EG(current_execute_data));
@@ -17052,36 +17050,25 @@ static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa,
17052
17050
return 1;
17053
17051
}
17054
17052
17055
- static ir_ref jit_frameless_observer(zend_jit_ctx *jit, 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) {
17053
+ void zend_frameless_observed_call(void); // we just care about the symbol to use it here, IP and FP may need to be passed depending on global regs
17054
+ static ir_ref jit_frameless_observer(zend_jit_ctx *jit, const zend_op *opline) {
17056
17055
// JIT: zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc))
17057
17056
ir_ref observer_handler;
17058
17057
zend_function *fbc = ZEND_FLF_FUNC(opline);
17059
17058
// Not need for runtime cache or generator checks here, we just need if_unobserved
17060
17059
ir_ref if_unobserved = jit_observer_fcall_is_unobserved_start(jit, fbc, &observer_handler, IR_UNUSED, IR_UNUSED).if_unobserved;
17061
17060
17062
- uint32_t call_num_args = ZEND_FLF_NUM_ARGS(opline->opcode);
17063
-
17064
17061
// push call frame
17065
- ir_ref call_ref = ir_CALL_4(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_observed_frameless_helper_push),
17066
- jit_FP(jit),
17067
- ir_CONST_U32(zend_vm_calc_used_stack(call_num_args, fbc)),
17068
- ir_CONST_ADDR(fbc),
17069
- ir_CONST_U32(call_num_args));
17070
-
17071
- // push all args
17072
- switch (call_num_args) {
17073
- case 3: jit_ZVAL_COPY(jit, ZEND_ADDR_REF_ZVAL(ir_ADD_OFFSET(call_ref, EX_NUM_TO_VAR(2))), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op1_data_ref), op1_data_info, 1); ZEND_FALLTHROUGH;
17074
- case 2: jit_ZVAL_COPY(jit, ZEND_ADDR_REF_ZVAL(ir_ADD_OFFSET(call_ref, EX_NUM_TO_VAR(1))), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op2_ref), op2_info, 1); ZEND_FALLTHROUGH;
17075
- case 1: jit_ZVAL_COPY(jit, ZEND_ADDR_REF_ZVAL(ir_ADD_OFFSET(call_ref, EX_NUM_TO_VAR(0))), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op1_ref), op1_info, 1);
17062
+ if (GCC_GLOBAL_REGS) {
17063
+ // FP register will point to the right place, but zend_frameless_observed_call needs IP to be also pointing to the precise opline.
17064
+ ir_ref old_ip = ir_HARD_COPY_A(ir_RLOAD_A(ZREG_IP));
17065
+ ir_RSTORE(ZREG_IP, ir_CONST_ADDR(opline));
17066
+ ir_CALL(IR_VOID, ir_CONST_ADDR((size_t)zend_frameless_observed_call));
17067
+ ir_RSTORE(ZREG_IP, old_ip); // restore it so that further offset calculations are not wrong
17068
+ } else {
17069
+ ir_CALL_2(IR_VOID, ir_CONST_ADDR((size_t)zend_frameless_observed_call), jit_FP(jit), ir_CONST_ADDR(opline));
17076
17070
}
17077
17071
17078
- // call and free args
17079
- ir_CALL_4(IR_VOID, ir_CONST_FC_FUNC(zend_jit_observed_frameless_helper_call),
17080
- call_ref,
17081
- ir_CONST_FC_FUNC(fbc->internal_function.handler),
17082
- observer_handler,
17083
- res_ref);
17084
-
17085
17072
ir_ref skip = ir_END();
17086
17073
ir_IF_TRUE(if_unobserved);
17087
17074
return skip;
@@ -17091,16 +17078,18 @@ static void jit_frameless_icall0(zend_jit_ctx *jit, const zend_op *opline)
17091
17078
{
17092
17079
jit_SET_EX_OPLINE(jit, opline);
17093
17080
17081
+ ir_ref skip_observer = IR_UNUSED;
17082
+ if (ZEND_OBSERVER_ENABLED) {
17083
+ skip_observer = jit_frameless_observer(jit, opline);
17084
+ }
17085
+
17094
17086
void *function = ZEND_FLF_HANDLER(opline);
17095
17087
zend_jit_addr res_addr = RES_ADDR();
17096
17088
ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
17097
17089
jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL);
17098
17090
17099
- ir_ref skip_observer = IR_UNUSED;
17100
- if (ZEND_OBSERVER_ENABLED) {
17101
- skip_observer = jit_frameless_observer(jit, opline, IR_UNUSED, 0, IR_UNUSED, 0, IR_UNUSED, 0, res_ref);
17102
- }
17103
17091
ir_CALL_1(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref);
17092
+
17104
17093
if (skip_observer != IR_UNUSED) {
17105
17094
ir_MERGE_WITH(skip_observer);
17106
17095
}
@@ -17112,6 +17101,11 @@ static void jit_frameless_icall1(zend_jit_ctx *jit, const zend_op *opline, uint3
17112
17101
{
17113
17102
jit_SET_EX_OPLINE(jit, opline);
17114
17103
17104
+ ir_ref skip_observer = IR_UNUSED;
17105
+ if (ZEND_OBSERVER_ENABLED) {
17106
+ skip_observer = jit_frameless_observer(jit, opline);
17107
+ }
17108
+
17115
17109
/* Avoid dropping RC check in case op escapes. */
17116
17110
if (op1_info & MAY_BE_RC1) {
17117
17111
op1_info |= MAY_BE_RCN;
@@ -17130,24 +17124,26 @@ static void jit_frameless_icall1(zend_jit_ctx *jit, const zend_op *opline, uint3
17130
17124
op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref);
17131
17125
}
17132
17126
17133
- ir_ref skip_observer = IR_UNUSED;
17134
- if (ZEND_OBSERVER_ENABLED) {
17135
- skip_observer = jit_frameless_observer(jit, opline, op1_ref, op1_info, IR_UNUSED, 0, IR_UNUSED, 0, res_ref);
17136
- }
17137
17127
ir_CALL_2(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref);
17128
+
17129
+ jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL);
17130
+
17138
17131
if (skip_observer != IR_UNUSED) {
17139
17132
ir_MERGE_WITH(skip_observer);
17140
17133
}
17141
17134
17142
- jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL);
17143
-
17144
17135
zend_jit_check_exception(jit);
17145
17136
}
17146
17137
17147
17138
static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_info, uint32_t op2_info)
17148
17139
{
17149
17140
jit_SET_EX_OPLINE(jit, opline);
17150
17141
17142
+ ir_ref skip_observer = IR_UNUSED;
17143
+ if (ZEND_OBSERVER_ENABLED) {
17144
+ skip_observer = jit_frameless_observer(jit, opline);
17145
+ }
17146
+
17151
17147
/* Avoid dropping RC check in case op escapes. */
17152
17148
if (op1_info & MAY_BE_RC1) {
17153
17149
op1_info |= MAY_BE_RCN;
@@ -17178,14 +17174,7 @@ static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint3
17178
17174
op2_ref = jit_ZVAL_DEREF_ref(jit, op2_ref);
17179
17175
}
17180
17176
17181
- ir_ref skip_observer = IR_UNUSED;
17182
- if (ZEND_OBSERVER_ENABLED) {
17183
- skip_observer = jit_frameless_observer(jit, opline, op1_ref, op1_info, op2_ref, op2_info, IR_UNUSED, 0, res_ref);
17184
- }
17185
17177
ir_CALL_3(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref, op2_ref);
17186
- if (skip_observer != IR_UNUSED) {
17187
- ir_MERGE_WITH(skip_observer);
17188
- }
17189
17178
17190
17179
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL);
17191
17180
/* Set OP1 to UNDEF in case FREE_OP2() throws. */
@@ -17195,13 +17184,22 @@ static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint3
17195
17184
}
17196
17185
jit_FREE_OP(jit, opline->op2_type, opline->op2, op2_info, NULL);
17197
17186
17187
+ if (skip_observer != IR_UNUSED) {
17188
+ ir_MERGE_WITH(skip_observer);
17189
+ }
17190
+
17198
17191
zend_jit_check_exception(jit);
17199
17192
}
17200
17193
17201
17194
static void jit_frameless_icall3(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_info, uint32_t op2_info, uint32_t op1_data_info)
17202
17195
{
17203
17196
jit_SET_EX_OPLINE(jit, opline);
17204
17197
17198
+ ir_ref skip_observer = IR_UNUSED;
17199
+ if (ZEND_OBSERVER_ENABLED) {
17200
+ skip_observer = jit_frameless_observer(jit, opline);
17201
+ }
17202
+
17205
17203
/* Avoid dropping RC check in case op escapes. */
17206
17204
if (op1_info & MAY_BE_RC1) {
17207
17205
op1_info |= MAY_BE_RCN;
@@ -17244,14 +17242,7 @@ static void jit_frameless_icall3(zend_jit_ctx *jit, const zend_op *opline, uint3
17244
17242
op3_ref = jit_ZVAL_DEREF_ref(jit, op3_ref);
17245
17243
}
17246
17244
17247
- ir_ref skip_observer = IR_UNUSED;
17248
- if (ZEND_OBSERVER_ENABLED) {
17249
- skip_observer = jit_frameless_observer(jit, opline, op1_ref, op1_info, op2_ref, op2_info, op3_ref, op1_data_info, res_ref);
17250
- }
17251
17245
ir_CALL_4(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref, op2_ref, op3_ref);
17252
- if (skip_observer != IR_UNUSED) {
17253
- ir_MERGE_WITH(skip_observer);
17254
- }
17255
17246
17256
17247
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL);
17257
17248
/* Set OP1 to UNDEF in case FREE_OP2() throws. */
@@ -17270,6 +17261,10 @@ static void jit_frameless_icall3(zend_jit_ctx *jit, const zend_op *opline, uint3
17270
17261
}
17271
17262
jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->op1, op1_data_info, NULL);
17272
17263
17264
+ if (skip_observer != IR_UNUSED) {
17265
+ ir_MERGE_WITH(skip_observer);
17266
+ }
17267
+
17273
17268
zend_jit_check_exception(jit);
17274
17269
}
17275
17270
0 commit comments