@@ -3069,6 +3069,8 @@ 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);
3072
3074
3073
3075
#ifndef ZTS
3074
3076
REGISTER_DATA(EG(current_execute_data));
@@ -17050,25 +17052,36 @@ static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa,
17050
17052
return 1;
17051
17053
}
17052
17054
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) {
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) {
17055
17056
// JIT: zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc))
17056
17057
ir_ref observer_handler;
17057
17058
zend_function *fbc = ZEND_FLF_FUNC(opline);
17058
17059
// Not need for runtime cache or generator checks here, we just need if_unobserved
17059
17060
ir_ref if_unobserved = jit_observer_fcall_is_unobserved_start(jit, fbc, &observer_handler, IR_UNUSED, IR_UNUSED).if_unobserved;
17060
17061
17062
+ uint32_t call_num_args = ZEND_FLF_NUM_ARGS(opline->opcode);
17063
+
17061
17064
// push call frame
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));
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);
17070
17076
}
17071
17077
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
+
17072
17085
ir_ref skip = ir_END();
17073
17086
ir_IF_TRUE(if_unobserved);
17074
17087
return skip;
@@ -17078,18 +17091,16 @@ static void jit_frameless_icall0(zend_jit_ctx *jit, const zend_op *opline)
17078
17091
{
17079
17092
jit_SET_EX_OPLINE(jit, opline);
17080
17093
17081
- ir_ref skip_observer = IR_UNUSED;
17082
- if (ZEND_OBSERVER_ENABLED) {
17083
- skip_observer = jit_frameless_observer(jit, opline);
17084
- }
17085
-
17086
17094
void *function = ZEND_FLF_HANDLER(opline);
17087
17095
zend_jit_addr res_addr = RES_ADDR();
17088
17096
ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
17089
17097
jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL);
17090
17098
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
+ }
17091
17103
ir_CALL_1(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref);
17092
-
17093
17104
if (skip_observer != IR_UNUSED) {
17094
17105
ir_MERGE_WITH(skip_observer);
17095
17106
}
@@ -17101,11 +17112,6 @@ static void jit_frameless_icall1(zend_jit_ctx *jit, const zend_op *opline, uint3
17101
17112
{
17102
17113
jit_SET_EX_OPLINE(jit, opline);
17103
17114
17104
- ir_ref skip_observer = IR_UNUSED;
17105
- if (ZEND_OBSERVER_ENABLED) {
17106
- skip_observer = jit_frameless_observer(jit, opline);
17107
- }
17108
-
17109
17115
/* Avoid dropping RC check in case op escapes. */
17110
17116
if (op1_info & MAY_BE_RC1) {
17111
17117
op1_info |= MAY_BE_RCN;
@@ -17124,26 +17130,24 @@ static void jit_frameless_icall1(zend_jit_ctx *jit, const zend_op *opline, uint3
17124
17130
op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref);
17125
17131
}
17126
17132
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
+ }
17127
17137
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
-
17131
17138
if (skip_observer != IR_UNUSED) {
17132
17139
ir_MERGE_WITH(skip_observer);
17133
17140
}
17134
17141
17142
+ jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL);
17143
+
17135
17144
zend_jit_check_exception(jit);
17136
17145
}
17137
17146
17138
17147
static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_info, uint32_t op2_info)
17139
17148
{
17140
17149
jit_SET_EX_OPLINE(jit, opline);
17141
17150
17142
- ir_ref skip_observer = IR_UNUSED;
17143
- if (ZEND_OBSERVER_ENABLED) {
17144
- skip_observer = jit_frameless_observer(jit, opline);
17145
- }
17146
-
17147
17151
/* Avoid dropping RC check in case op escapes. */
17148
17152
if (op1_info & MAY_BE_RC1) {
17149
17153
op1_info |= MAY_BE_RCN;
@@ -17174,7 +17178,14 @@ static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint3
17174
17178
op2_ref = jit_ZVAL_DEREF_ref(jit, op2_ref);
17175
17179
}
17176
17180
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
+ }
17177
17185
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
+ }
17178
17189
17179
17190
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL);
17180
17191
/* Set OP1 to UNDEF in case FREE_OP2() throws. */
@@ -17184,22 +17195,13 @@ static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint3
17184
17195
}
17185
17196
jit_FREE_OP(jit, opline->op2_type, opline->op2, op2_info, NULL);
17186
17197
17187
- if (skip_observer != IR_UNUSED) {
17188
- ir_MERGE_WITH(skip_observer);
17189
- }
17190
-
17191
17198
zend_jit_check_exception(jit);
17192
17199
}
17193
17200
17194
17201
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)
17195
17202
{
17196
17203
jit_SET_EX_OPLINE(jit, opline);
17197
17204
17198
- ir_ref skip_observer = IR_UNUSED;
17199
- if (ZEND_OBSERVER_ENABLED) {
17200
- skip_observer = jit_frameless_observer(jit, opline);
17201
- }
17202
-
17203
17205
/* Avoid dropping RC check in case op escapes. */
17204
17206
if (op1_info & MAY_BE_RC1) {
17205
17207
op1_info |= MAY_BE_RCN;
@@ -17242,7 +17244,14 @@ static void jit_frameless_icall3(zend_jit_ctx *jit, const zend_op *opline, uint3
17242
17244
op3_ref = jit_ZVAL_DEREF_ref(jit, op3_ref);
17243
17245
}
17244
17246
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
+ }
17245
17251
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
+ }
17246
17255
17247
17256
jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL);
17248
17257
/* Set OP1 to UNDEF in case FREE_OP2() throws. */
@@ -17261,10 +17270,6 @@ static void jit_frameless_icall3(zend_jit_ctx *jit, const zend_op *opline, uint3
17261
17270
}
17262
17271
jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->op1, op1_data_info, NULL);
17263
17272
17264
- if (skip_observer != IR_UNUSED) {
17265
- ir_MERGE_WITH(skip_observer);
17266
- }
17267
-
17268
17273
zend_jit_check_exception(jit);
17269
17274
}
17270
17275
0 commit comments