Skip to content

ZJIT: Re-profile the whole ISEQ after recompile side exits #1000

Description

@k0kubun

Follow-up to ruby#17457 (comment) and the earlier discussion at ruby#17326 (comment).

PR ruby#17457 fixes the smaller deduplication issue by sharing the per-instruction profiling logic used by zjit_ YARV instructions. After that PR, recompile exits can recover the current instruction from the materialized CFP and profile that instruction through profile.rs instead of carrying kind-specific profiling payloads across the C ABI.

The remaining follow-up is to change the recompile-exit lifecycle so the interpreter actually executes zjit_ YARV profiling instructions again, rather than having the ZJIT side-exit hook directly call into the profiling implementation for only the current instruction.

Problem

Today, a recompile side exit profiles only the instruction that caused the exit. That is enough to fix the immediate side exit, but it means an ISEQ with multiple no-profile callsites may need multiple recompile versions: one exit/version to discover each missing profile.

For example, if an ISEQ has N no-profile callsites, the current behavior can require up to N recompile exits because each exit only profiles the callsite that happened to exit. If the side exit instead disabled the current compiled version and re-enabled interpreter profiling for the ISEQ, the next interpreter pass could collect profiles for the exiting instruction and for other zjit_-profiled instructions in the same ISEQ before compiling the next version.

Desired behavior

When a side exit with recompile metadata is hit:

  • Disable/invalidate the current compiled version, preserving the existing distinction between the frame/current ISEQ being profiled and the compiled ISEQ whose version must be invalidated for inlined exits.
  • Re-enable zjit_ YARV instructions so the interpreter profiles the ISEQ through the normal rb_zjit_profile_insn path.
  • Restart the relevant profiles_remaining counters so this is a real --zjit-num-profiles profiling window, not just a one-off sample for entries that had already finished profiling.
  • Let the normal profile-threshold/call-threshold path compile the next version after the interpreter has had a chance to collect whole-ISEQ profile data.
  • Keep the max-version/final-version behavior intact: if the ISEQ cannot be recompiled, the side exit should not keep re-enabling profiling or churning counters.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions