Skip to content

Commit 0ce2aa8

Browse files
committed
Fix profile count
1 parent a0e5729 commit 0ce2aa8

3 files changed

Lines changed: 23 additions & 5 deletions

File tree

zjit/src/backend/lir.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use std::mem::take;
44
use std::rc::Rc;
55
use crate::bitset::BitSet;
66
use crate::codegen::{local_size_and_idx_to_ep_offset, perf_symbol_range_start, perf_symbol_range_end};
7-
use crate::cruby::{IseqPtr, RUBY_OFFSET_CFP_ISEQ, RUBY_OFFSET_CFP_JIT_RETURN, RUBY_OFFSET_CFP_PC, RUBY_OFFSET_CFP_SP, SIZEOF_VALUE_I32, vm_stack_canary};
7+
use crate::cruby::{vm_stack_canary, IseqPtr, YarvInsnIdx, RUBY_OFFSET_CFP_ISEQ, RUBY_OFFSET_CFP_JIT_RETURN, RUBY_OFFSET_CFP_PC, RUBY_OFFSET_CFP_SP, SIZEOF_VALUE_I32};
88
use crate::hir::{Invariant, SideExitReason};
99
use crate::hir;
1010
use crate::options::{TraceExits, PerfMap, get_option};
1111
use crate::cruby::VALUE;
12-
use crate::payload::IseqVersionRef;
12+
use crate::payload::{IseqVersionRef, get_or_create_iseq_payload};
1313
use crate::stats::{exit_counter_ptr, exit_counter_ptr_for_opcode, side_exit_counter, CompileError};
1414
use crate::virtualmem::CodePtr;
1515
use crate::asm::{CodeBlock, Label};
@@ -2402,7 +2402,8 @@ impl Assembler
24022402

24032403
fn compile_exit_recompile(asm: &mut Assembler, exit: &SideExit) {
24042404
if let Some(recompile) = &exit.recompile {
2405-
2405+
let payload = get_or_create_iseq_payload(exit.iseq);
2406+
payload.reset_profiles_remaining(recompile.insn_idx as YarvInsnIdx);
24062407
use crate::codegen::exit_recompile;
24072408
asm_comment!(asm, "profile and maybe recompile");
24082409
asm_ccall!(asm, exit_recompile,

zjit/src/payload.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::ptr::NonNull;
33
use crate::codegen::IseqCallRef;
44
use crate::stats::CompileError;
55
use crate::{cruby::*, profile::IseqProfile, virtualmem::CodePtr};
6+
use crate::options::get_option;
67

78
pub use crate::jit_frame::JITFrame;
89

@@ -26,6 +27,11 @@ impl IseqPayload {
2627
was_invalidated_for_singleton_class_creation: false,
2728
}
2829
}
30+
31+
pub fn reset_profiles_remaining(&mut self, insn_idx: YarvInsnIdx) {
32+
let num_profiles = get_option!(num_profiles);
33+
self.profile.entry_mut(insn_idx).set_profiles_remaining(num_profiles);
34+
}
2935
}
3036

3137
/// JIT code version. When the same ISEQ is compiled with a different assumption, a new version is created.

zjit/src/profile.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ impl ProfiledType {
417417

418418
/// Per-instruction profile entry, stored sparsely in a sorted Vec.
419419
#[derive(Debug)]
420-
struct ProfileEntry {
420+
pub struct ProfileEntry {
421421
/// YARV instruction index
422422
insn_idx: u32,
423423
/// Type information of YARV instruction operands
@@ -426,6 +426,12 @@ struct ProfileEntry {
426426
profiles_remaining: NumProfiles,
427427
}
428428

429+
impl ProfileEntry {
430+
pub fn set_profiles_remaining(&mut self, num_profiles: NumProfiles) {
431+
self.profiles_remaining = num_profiles;
432+
}
433+
}
434+
429435
#[derive(Debug)]
430436
pub struct IseqProfile {
431437
/// Sparse storage of per-instruction profile data, sorted by instruction index.
@@ -445,7 +451,7 @@ impl IseqProfile {
445451
}
446452

447453
/// Get or create a mutable profile entry for the given instruction index.
448-
fn entry_mut(&mut self, insn_idx: YarvInsnIdx) -> &mut ProfileEntry {
454+
pub fn entry_mut(&mut self, insn_idx: YarvInsnIdx) -> &mut ProfileEntry {
449455
let idx = insn_idx as u32;
450456
match self.entries.binary_search_by_key(&idx, |e| e.insn_idx) {
451457
Ok(i) => &mut self.entries[i],
@@ -479,6 +485,11 @@ impl IseqProfile {
479485
pub fn profile_send_at(&mut self, iseq: IseqPtr, insn_idx: YarvInsnIdx, sp: *const VALUE, argc: usize) -> bool {
480486
let n = argc + 1; // args + receiver
481487
let entry = self.entry_mut(insn_idx);
488+
// Reset profiling if the previous round already finished (stale YARV profiles).
489+
// This ensures we collect num_profiles samples of the new shapes before recompiling.
490+
if entry.profiles_remaining == 0 {
491+
entry.profiles_remaining = get_option!(num_profiles);
492+
}
482493
if entry.opnd_types.is_empty() {
483494
entry.opnd_types.resize(n, TypeDistribution::new());
484495
}

0 commit comments

Comments
 (0)