JIT: Record fake init calls for subtraces (fixes array_map optimization) - #23450
Conversation
The array_map optimization may emit loops inside an INIT_FCALL-DO_FCALL sequence, which was not possible before. JIT doesn't expect that and forgets about pending calls when starting a subtrace for the loop. Fix by recording fake init calls in zend_jit_trace_subtrace().
iliaal
left a comment
There was a problem hiding this comment.
Looks good!
One thing beyond this patch: zend_jit_trace_record_fake_init_call_ex() returns idx on every path, including when TRACE_RECORD hits the limit and only sets its function-local stop. So the if (idx < 0) here, like the three at the existing callers, cannot fire, and the recursion writes one record per level as it unwinds before the new aggregate check runs. With opcache.jit_max_trace_length defaulting to 1024 and trace_buffer[] sized ZEND_JIT_TRACE_MAX_LENGTH = 1024, that overshoot spends the two-slot headroom instead of stopping with TOO_LONG. Propagating the overflow out of the helper seems better than a fourth dead check.
Separately: with several chained fake INIT_CALL records, zend_jit_trace_find_init_fcall_op() walks backward and returns NULL, so num_args falls back to -1. Looks harmless, but is #23449 meant to land before this one?
Good catch, I didn't notice this. I added this check since every call to
I confirm it's harmless: |
The array_map optimization may emit loops inside an INIT_FCALL-DO_FCALL sequence, which was not possible before. JIT doesn't expect that and forgets about pending calls when starting a subtrace for the loop.
Fix by recording fake init calls in zend_jit_trace_subtrace().
Blocks #23254