@@ -2302,7 +2302,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
23022302 Insn::GuardLess { left, right, .. } => write!(f, "GuardLess {left}, {right}"),
23032303 Insn::GuardGreaterEq { left, right, .. } => write!(f, "GuardGreaterEq {left}, {right}"),
23042304 &Insn::GetBlockParam { level, ep_offset, state, .. } => {
2305- let iseq = self.fun.map(|fun| fun.frame_state (state).iseq );
2305+ let iseq = self.fun.map(|fun| fun.frame_state_iseq (state));
23062306 let name = get_local_var_name_for_printer(iseq, level, ep_offset)
23072307 .map_or(String::new(), |x| format!("{x}, "));
23082308 write!(f, "GetBlockParam {name}l{level}, EP@{ep_offset}")
@@ -2393,7 +2393,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
23932393 write!(f, "IsBlockParamModified {flags}")
23942394 },
23952395 &Insn::SetLocal { val, level, ep_offset, state } => {
2396- let iseq = self.fun.map(|fun| fun.frame_state (state).iseq );
2396+ let iseq = self.fun.map(|fun| fun.frame_state_iseq (state));
23972397 let name = get_local_var_name_for_printer(iseq, level, ep_offset).map_or(String::new(), |x| format!("{x}, "));
23982398 write!(f, "SetLocal {name}l{level}, EP@{ep_offset}, {val}")
23992399 },
@@ -3092,14 +3092,32 @@ impl Function {
30923092 }).max().unwrap_or(0)
30933093 }
30943094
3095- /// Return a FrameState at the given instruction index.
3095+ /// Return a resolved, freshly allocated FrameState at the given instruction index.
30963096 pub fn frame_state(&self, insn_id: InsnId) -> FrameState {
30973097 match self.find(insn_id) {
30983098 Insn::Snapshot { state } => *state,
30993099 insn => panic!("Unexpected non-Snapshot {insn} when looking up FrameState"),
31003100 }
31013101 }
31023102
3103+ /// Return an unresolved FrameState reference at the given instruction index.
3104+ pub fn frame_state_ref(&self, insn_id: InsnId) -> &FrameState {
3105+ match self.find_ref(insn_id) {
3106+ Insn::Snapshot { state } => state,
3107+ insn => panic!("Unexpected non-Snapshot {insn} when looking up FrameState"),
3108+ }
3109+ }
3110+
3111+ /// Return a FrameState's iseq at the given instruction index.
3112+ pub fn frame_state_iseq(&self, insn_id: InsnId) -> *const rb_iseq_t {
3113+ self.frame_state_ref(insn_id).iseq
3114+ }
3115+
3116+ /// Return a FrameState's interpreter instruction index.
3117+ pub fn frame_state_insn_idx(&self, insn_id: InsnId) -> YarvInsnIdx {
3118+ self.frame_state_ref(insn_id).insn_idx
3119+ }
3120+
31033121 /// Return the inlining depth recorded on the `Snapshot` at the given
31043122 /// instruction index. This peeks the field directly so callers that only
31053123 /// need the depth avoid cloning the whole `FrameState`, including its stack
@@ -4063,8 +4081,11 @@ impl Function {
40634081 }
40644082
40654083 fn count_caller_splat_profile(&mut self, block: BlockId, state: InsnId) {
4066- let state = self.frame_state(state);
4067- let summary = get_or_create_iseq_payload(state.iseq).profile.get_splat_length_summary(state.insn_idx);
4084+ let (iseq, insn_idx) = {
4085+ let frame_state = self.frame_state_ref(state);
4086+ (frame_state.iseq, frame_state.insn_idx)
4087+ };
4088+ let summary = get_or_create_iseq_payload(iseq).profile.get_splat_length_summary(insn_idx);
40684089 let counter = match summary {
40694090 None => Counter::caller_splat_profile_no_profiles,
40704091 Some(summary) if summary.is_monomorphic() => Counter::caller_splat_profile_monomorphic,
@@ -4925,10 +4946,13 @@ impl Function {
49254946 continue;
49264947 }
49274948
4928- let frame_state = self.frame_state(state);
4949+ let (frame_state_iseq, frame_state_insn_idx) = {
4950+ let frame_state = self.frame_state_ref(state);
4951+ (frame_state.iseq, frame_state.insn_idx)
4952+ };
49294953
49304954 // Don't handle super in a block since that needs a loop to find the running CME.
4931- if frame_state.iseq != unsafe { rb_get_iseq_body_local_iseq(frame_state.iseq ) } {
4955+ if frame_state_iseq != unsafe { rb_get_iseq_body_local_iseq(frame_state_iseq ) } {
49324956 self.push_insn_id(block, insn_id);
49334957 self.set_dynamic_send_reason(insn_id, SuperFromBlock);
49344958 continue;
@@ -4952,12 +4976,12 @@ impl Function {
49524976 continue;
49534977 }
49544978
4955- // Use frame_state.iseq so that an inlined super call looks up its
4979+ // Use frame_state_iseq so that an inlined super call looks up its
49564980 // profiled CME against the callee's payload rather than the outer
49574981 // compilation's. The runtime guard walks from the live CFP, which is
49584982 // the callee's CFP for inlined code, so the profile lookup must agree.
4959- let local_payload = get_or_create_iseq_payload(frame_state.iseq );
4960- let Some(current_cme) = local_payload.profile.get_super_method_entry(frame_state.insn_idx ) else {
4983+ let local_payload = get_or_create_iseq_payload(frame_state_iseq );
4984+ let Some(current_cme) = local_payload.profile.get_super_method_entry(frame_state_insn_idx ) else {
49614985 self.push_insn_id(block, insn_id);
49624986
49634987 // The absence of the super CME could be due to a missing profile, but
@@ -5015,7 +5039,7 @@ impl Function {
50155039 self.push_insn_id(block, insn_id); continue;
50165040 };
50175041
5018- emit_super_call_guards(self, block, super_cme, current_cme, mid, state, frame_state.iseq );
5042+ emit_super_call_guards(self, block, super_cme, current_cme, mid, state, frame_state_iseq );
50195043
50205044 // Use SendDirect with the super method's CME and ISEQ.
50215045 let replacement = self.try_inline_send_direct(block, Insn::SendDirect(Box::new(SendDirectData {
@@ -5059,7 +5083,7 @@ impl Function {
50595083 continue;
50605084 }
50615085
5062- emit_super_call_guards(self, block, super_cme, current_cme, mid, state, frame_state.iseq );
5086+ emit_super_call_guards(self, block, super_cme, current_cme, mid, state, frame_state_iseq );
50635087
50645088 // Try inlining the cfunc into HIR
50655089 let tmp_block = self.new_block(u32::MAX);
@@ -5109,7 +5133,7 @@ impl Function {
51095133
51105134 // Variadic C function: func(int argc, VALUE *argv, VALUE recv)
51115135 -1 => {
5112- emit_super_call_guards(self, block, super_cme, current_cme, mid, state, frame_state.iseq );
5136+ emit_super_call_guards(self, block, super_cme, current_cme, mid, state, frame_state_iseq );
51135137
51145138 // Try inlining the cfunc into HIR
51155139 let tmp_block = self.new_block(u32::MAX);
0 commit comments