Skip to content

Commit 206cfcc

Browse files
committed
Use zend_jit_save_call_chain
1 parent c89217b commit 206cfcc

File tree

1 file changed

+11
-8
lines changed

1 file changed

+11
-8
lines changed

ext/opcache/jit/zend_jit_ir.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17040,22 +17040,23 @@ static ir_ref jit_frameless_observer(zend_jit_ctx *jit, int checked_stack, const
1704017040
// Not need for runtime cache or generator checks here, we just need if_unobserved
1704117041
ir_ref if_unobserved = jit_observer_fcall_is_unobserved_start(jit, fbc, &observer_handler, IR_UNUSED, IR_UNUSED).if_unobserved;
1704217042

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+
1704317050
// push args to a valid call frame
1704417051
bool track_last_valid_opline = jit->track_last_valid_opline;
1704517052
bool use_last_valid_opline = jit->use_last_valid_opline;
1704617053
const zend_op *last_valid_opline = jit->last_valid_opline;
1704717054
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-
}
1705417055
zend_jit_push_call_frame(jit, opline, NULL, fbc, 0, 0, checked_stack, ir_CONST_ADDR(fbc), IR_NULL);
1705517056
// 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
1705617057
// the primary issue here is that this code is just executed conditionally while the reuse mechanisms are meant to be global
1705717058
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
1705917060
jit->last_valid_opline = last_valid_opline;
1706017061
jit->reuse_ip = reuse_ip;
1706117062

@@ -17117,8 +17118,10 @@ static ir_ref jit_frameless_observer(zend_jit_ctx *jit, int checked_stack, const
1711717118

1711817119
if (reuse_ip) {
1711917120
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
1712117122
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;
1712217125
}
1712317126
} else {
1712417127
// 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

Comments
 (0)