@@ -4485,6 +4485,7 @@ static struct jit_observer_fcall_is_unobserved_data jit_observer_fcall_is_unobse
4485
4485
if (func) {
4486
4486
ZEND_ASSERT((func->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_GENERATOR)) == 0);
4487
4487
} else {
4488
+ // JIT: if (function->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_GENERATOR)) {
4488
4489
ZEND_ASSERT(rx != IR_UNUSED);
4489
4490
ir_ref if_trampoline_or_generator = ir_IF(ir_AND_U32(
4490
4491
ir_LOAD_U32(ir_ADD_OFFSET(func_ref, offsetof(zend_function, common.fn_flags))),
@@ -4494,13 +4495,15 @@ static struct jit_observer_fcall_is_unobserved_data jit_observer_fcall_is_unobse
4494
4495
ir_IF_FALSE(if_trampoline_or_generator);
4495
4496
}
4496
4497
if (func && (func->common.fn_flags & ZEND_ACC_CLOSURE) == 0 && ZEND_MAP_PTR_IS_OFFSET(func->common.run_time_cache)) {
4498
+ // JIT: ZEND_MAP_PTR_GET_IMM(func->common.runtime_cache)
4497
4499
run_time_cache = ir_LOAD_A(ir_ADD_OFFSET(ir_LOAD_A(jit_CG(map_ptr_base)), (uintptr_t)ZEND_MAP_PTR(func->common.run_time_cache)));
4498
4500
} else {
4499
4501
ZEND_ASSERT(rx != IR_UNUSED);
4500
4502
// Closures may be duplicated and have a different runtime cache. Use the regular run_time_cache access pattern for these
4501
4503
if (func && ZEND_USER_CODE(func->type)) { // not a closure and definitely not an internal function
4502
4504
run_time_cache = ir_LOAD_A(jit_CALL(rx, run_time_cache));
4503
4505
} else {
4506
+ // JIT: ZEND_MAP_PTR_GET(func->common.runtime_cache)
4504
4507
run_time_cache = ir_LOAD_A(ir_ADD_OFFSET(ir_LOAD_A(jit_CALL(rx, func)), offsetof(zend_op_array, run_time_cache__ptr)));
4505
4508
ir_ref if_odd = ir_IF(ir_AND_A(run_time_cache, ir_CONST_ADDR(1)));
4506
4509
ir_IF_TRUE(if_odd);
@@ -4510,6 +4513,7 @@ static struct jit_observer_fcall_is_unobserved_data jit_observer_fcall_is_unobse
4510
4513
ir_ref if_odd_end = ir_END();
4511
4514
ir_IF_FALSE(if_odd);
4512
4515
4516
+ // JIT: if (func->common.runtime_cache != NULL) {
4513
4517
ir_ref if_rt_cache = ir_IF(ir_EQ(run_time_cache, IR_NULL));
4514
4518
ir_IF_TRUE(if_rt_cache);
4515
4519
ir_END_list(data.ir_end_inputs);
@@ -4519,12 +4523,13 @@ static struct jit_observer_fcall_is_unobserved_data jit_observer_fcall_is_unobse
4519
4523
run_time_cache = ir_PHI_2(IR_ADDR, run_time_cache, run_time_cache2);
4520
4524
}
4521
4525
}
4526
+ // JIT: observer_handler = runtime_cache + ZEND_OBSERVER_HANDLE(function)
4522
4527
if (func) {
4523
4528
*observer_handler = ir_ADD_OFFSET(run_time_cache, ZEND_OBSERVER_HANDLE(func) * sizeof(void *));
4524
4529
} else {
4525
- // JIT: if (ZEND_USER_CODE( func->type)) {
4530
+ // JIT: ( func->type == ZEND_INTERNAL_FUNCTION ? zend_observer_fcall_internal_function_extension : zend_observer_fcall_op_array_extension) * sizeof(void *)
4526
4531
ir_ref tmp = ir_LOAD_U8(ir_ADD_OFFSET(func_ref, offsetof(zend_function, type)));
4527
- ir_ref if_internal_func = ir_IF(ir_AND_U8(tmp, ir_CONST_U8(1 )));
4532
+ ir_ref if_internal_func = ir_IF(ir_AND_U8(tmp, ir_CONST_U8(ZEND_INTERNAL_FUNCTION )));
4528
4533
ir_IF_TRUE(if_internal_func);
4529
4534
4530
4535
ir_ref observer_handler_internal = ir_ADD_OFFSET(run_time_cache, zend_observer_fcall_internal_function_extension * sizeof(void *));
@@ -4538,11 +4543,13 @@ static struct jit_observer_fcall_is_unobserved_data jit_observer_fcall_is_unobse
4538
4543
*observer_handler = ir_PHI_2(IR_ADDR, observer_handler_internal, observer_handler_user);
4539
4544
}
4540
4545
4546
+ // JIT: if (*observer_handler == ZEND_OBSERVER_NONE_OBSERVED) {
4541
4547
data.if_unobserved = ir_IF(ir_EQ(ir_LOAD_A(*observer_handler), ir_CONST_ADDR(ZEND_OBSERVER_NONE_OBSERVED)));
4542
4548
ir_IF_FALSE(data.if_unobserved);
4543
4549
return data;
4544
4550
}
4545
4551
4552
+ /* For frameless the true branch of if_unobserved is used and this function not called. */
4546
4553
static void jit_observer_fcall_is_unobserved_end(zend_jit_ctx *jit, struct jit_observer_fcall_is_unobserved_data *data) {
4547
4554
ir_END_list(data->ir_end_inputs);
4548
4555
ir_IF_TRUE(data->if_unobserved);
@@ -4555,6 +4562,7 @@ static void jit_observer_fcall_begin(zend_jit_ctx *jit, ir_ref rx, ir_ref observ
4555
4562
}
4556
4563
4557
4564
static void jit_observer_fcall_end(zend_jit_ctx *jit, ir_ref rx, ir_ref res_ref) {
4565
+ // JIT: if (execute_data == EG(current_observed_frame)) {
4558
4566
ir_ref has_end_observer = ir_IF(ir_EQ(rx, ir_LOAD_A(jit_EG(current_observed_frame))));
4559
4567
ir_IF_TRUE(has_end_observer);
4560
4568
ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_observer_fcall_end_prechecked),
@@ -17058,7 +17066,7 @@ static ir_ref jit_frameless_observer(zend_jit_ctx *jit, const zend_op *opline) {
17058
17066
// Not need for runtime cache or generator checks here, we just need if_unobserved
17059
17067
ir_ref if_unobserved = jit_observer_fcall_is_unobserved_start(jit, fbc, &observer_handler, IR_UNUSED, IR_UNUSED).if_unobserved;
17060
17068
17061
- // push call frame
17069
+ // Call zend_frameless_observed_call for the main logic.
17062
17070
if (GCC_GLOBAL_REGS) {
17063
17071
// FP register will point to the right place, but zend_frameless_observed_call needs IP to be also pointing to the precise opline.
17064
17072
ir_ref old_ip = ir_HARD_COPY_A(ir_RLOAD_A(ZREG_IP));
@@ -17150,7 +17158,6 @@ static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint3
17150
17158
zend_jit_addr res_addr = RES_ADDR();
17151
17159
zend_jit_addr op1_addr = OP1_ADDR();
17152
17160
zend_jit_addr op2_addr = OP2_ADDR();
17153
-
17154
17161
ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
17155
17162
ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr);
17156
17163
ir_ref op2_ref = jit_ZVAL_ADDR(jit, op2_addr);
@@ -17210,7 +17217,6 @@ static void jit_frameless_icall3(zend_jit_ctx *jit, const zend_op *opline, uint3
17210
17217
zend_jit_addr op1_addr = OP1_ADDR();
17211
17218
zend_jit_addr op2_addr = OP2_ADDR();
17212
17219
zend_jit_addr op3_addr = OP1_DATA_ADDR();
17213
-
17214
17220
ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
17215
17221
ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr);
17216
17222
ir_ref op2_ref = jit_ZVAL_ADDR(jit, op2_addr);
0 commit comments