@@ -17040,22 +17040,23 @@ static ir_ref jit_frameless_observer(zend_jit_ctx *jit, int checked_stack, const
17040
17040
// Not need for runtime cache or generator checks here, we just need if_unobserved
17041
17041
ir_ref if_unobserved = jit_observer_fcall_is_unobserved_start(jit, fbc, &observer_handler, IR_UNUSED, IR_UNUSED).if_unobserved;
17042
17042
17043
+ // Preserve delayed_call_level. We cannot override delayed_call_level without also saving in unobserved path.
17044
+ uint32_t delayed_call_level = jit->delayed_call_level;
17045
+ bool is_delayed_call_chain = delayed_call_chain;
17046
+ if (jit->delayed_call_level) {
17047
+ zend_jit_save_call_chain(jit, jit->delayed_call_level);
17048
+ }
17049
+
17043
17050
// push args to a valid call frame
17044
17051
bool track_last_valid_opline = jit->track_last_valid_opline;
17045
17052
bool use_last_valid_opline = jit->use_last_valid_opline;
17046
17053
const zend_op *last_valid_opline = jit->last_valid_opline;
17047
17054
bool reuse_ip = jit->reuse_ip;
17048
- // zend_jit_save_call_chain, but preserve delayed_call_level. We cannot override delayed_call_level without also saving in unobserved path.
17049
- if (jit->delayed_call_level) {
17050
- ir_ref call = jit_CALL(jit_FP(jit), call);
17051
- ir_STORE(jit_CALL(jit_IP(jit), prev_execute_data), jit->delayed_call_level == 1 ? IR_NULL : ir_LOAD_A(call));
17052
- ir_STORE(call, jit_IP(jit));
17053
- }
17054
17055
zend_jit_push_call_frame(jit, opline, NULL, fbc, 0, 0, checked_stack, ir_CONST_ADDR(fbc), IR_NULL);
17055
17056
// 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
17056
17057
// the primary issue here is that this code is just executed conditionally while the reuse mechanisms are meant to be global
17057
17058
jit->track_last_valid_opline = track_last_valid_opline;
17058
- jit->use_last_valid_opline = use_last_valid_opline;
17059
+ jit->use_last_valid_opline = use_last_valid_opline; // opline restored later in function
17059
17060
jit->last_valid_opline = last_valid_opline;
17060
17061
jit->reuse_ip = reuse_ip;
17061
17062
@@ -17117,8 +17118,10 @@ static ir_ref jit_frameless_observer(zend_jit_ctx *jit, int checked_stack, const
17117
17118
17118
17119
if (reuse_ip) {
17119
17120
jit_STORE_IP(jit, ir_LOAD_A(jit_CALL(jit_FP(jit), call)));
17120
- if (jit-> delayed_call_level) { // restore if saved
17121
+ if (delayed_call_level) { // restore if saved
17121
17122
ir_STORE(jit_CALL(jit_FP(jit), call), ir_LOAD_A(jit_CALL(jit_IP(jit), prev_execute_data)));
17123
+ delayed_call_chain = is_delayed_call_chain;
17124
+ jit->delayed_call_level = delayed_call_level;
17122
17125
}
17123
17126
} else {
17124
17127
// Note: conditional (if_unobserved) opline, zend_jit_set_last_valid_opline() may only be called if the opline is actually unconditionally updated
0 commit comments