Skip to content

Commit d05f23b

Browse files
committed
ZJIT: handle megamorphic and skewed megamorphic profiling results
1 parent 6902bc7 commit d05f23b

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

zjit/src/hir.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -567,29 +567,35 @@ impl std::fmt::Display for SideExitReason {
567567
/// Represents whether we know the receiver's class statically at compile-time,
568568
/// have profiled type information, or know nothing about it.
569569
pub enum ReceiverTypeResolution {
570-
/// The receiver's class is statically known at JIT compile-time (no guard needed)
571-
StaticallyKnown { class: VALUE },
570+
/// No profile information available for the receiver
571+
NoProfile,
572572
/// The receiver has a monomorphic profile (single type observed, guard needed)
573573
Monomorphic { class: VALUE, profiled_type: ProfiledType },
574-
/// The receiver has a skewed polymorphic profile (dominant type with some other types, guard needed)
575-
SkewedPolymorphic { class: VALUE, profiled_type: ProfiledType },
576574
/// The receiver is polymorphic (multiple types, none dominant)
577575
Polymorphic,
578-
/// No profile information available for the receiver
579-
NoProfile,
576+
/// The receiver has a skewed polymorphic profile (dominant type with some other types, guard needed)
577+
SkewedPolymorphic { class: VALUE, profiled_type: ProfiledType },
578+
/// More than N types seen with no clear winner
579+
Megamorphic,
580+
/// Megamorphic, but with a significant skew towards one type
581+
SkewedMegamorphic { class: VALUE, profiled_type: ProfiledType },
582+
/// The receiver's class is statically known at JIT compile-time (no guard needed)
583+
StaticallyKnown { class: VALUE },
580584
}
581585

582586
/// Reason why a send-ish instruction cannot be optimized from a fallback instruction
583587
#[derive(Debug, Clone, Copy)]
584588
pub enum SendFallbackReason {
585589
SendWithoutBlockPolymorphic,
590+
SendWithoutBlockMegamorphic,
586591
SendWithoutBlockNoProfiles,
587592
SendWithoutBlockCfuncNotVariadic,
588593
SendWithoutBlockCfuncArrayVariadic,
589594
SendWithoutBlockNotOptimizedMethodType(MethodType),
590595
SendWithoutBlockNotOptimizedOptimizedMethodType(OptimizedMethodType),
591596
SendWithoutBlockDirectTooManyArgs,
592597
SendPolymorphic,
598+
SendMegamorphic,
593599
SendNoProfiles,
594600
SendNotOptimizedMethodType(MethodType),
595601
CCallWithFrameTooManyArgs,
@@ -2158,6 +2164,8 @@ impl Function {
21582164
/// - `StaticallyKnown` if the receiver's exact class is known at compile-time
21592165
/// - `Monomorphic`/`SkewedPolymorphic` if we have usable profile data
21602166
/// - `Polymorphic` if the receiver has multiple types
2167+
/// - `Megamorphic`/`SkewedMegamorphic` if the receiver has too many types to optimize
2168+
/// (SkewedMegamorphic may be optimized in the future, but for now we don't)
21612169
/// - `NoProfile` if we have no type information
21622170
fn resolve_receiver_type(&self, recv: InsnId, recv_type: Type, insn_idx: usize) -> ReceiverTypeResolution {
21632171
if let Some(class) = recv_type.runtime_exact_ruby_class() {
@@ -2185,8 +2193,16 @@ impl Function {
21852193
class: profiled_type.class(),
21862194
profiled_type,
21872195
};
2196+
} else if entry_type_summary.is_skewed_megamorphic() {
2197+
let profiled_type = entry_type_summary.bucket(0);
2198+
return ReceiverTypeResolution::SkewedMegamorphic {
2199+
class: profiled_type.class(),
2200+
profiled_type,
2201+
};
21882202
} else if entry_type_summary.is_polymorphic() {
21892203
return ReceiverTypeResolution::Polymorphic;
2204+
} else if entry_type_summary.is_megamorphic() {
2205+
return ReceiverTypeResolution::Megamorphic;
21902206
}
21912207
}
21922208
}
@@ -2342,6 +2358,14 @@ impl Function {
23422358
ReceiverTypeResolution::StaticallyKnown { class } => (class, None),
23432359
ReceiverTypeResolution::Monomorphic { class, profiled_type }
23442360
| ReceiverTypeResolution::SkewedPolymorphic { class, profiled_type } => (class, Some(profiled_type)),
2361+
ReceiverTypeResolution::SkewedMegamorphic { .. }
2362+
| ReceiverTypeResolution::Megamorphic => {
2363+
if get_option!(stats) {
2364+
self.set_dynamic_send_reason(insn_id, SendWithoutBlockMegamorphic);
2365+
}
2366+
self.push_insn_id(block, insn_id);
2367+
continue;
2368+
}
23452369
ReceiverTypeResolution::Polymorphic => {
23462370
if get_option!(stats) {
23472371
self.set_dynamic_send_reason(insn_id, SendWithoutBlockPolymorphic);
@@ -2535,6 +2559,14 @@ impl Function {
25352559
ReceiverTypeResolution::StaticallyKnown { class } => class,
25362560
ReceiverTypeResolution::Monomorphic { class, .. }
25372561
| ReceiverTypeResolution::SkewedPolymorphic { class, .. } => class,
2562+
ReceiverTypeResolution::SkewedMegamorphic { .. }
2563+
| ReceiverTypeResolution::Megamorphic => {
2564+
if get_option!(stats) {
2565+
self.set_dynamic_send_reason(insn_id, SendMegamorphic);
2566+
}
2567+
self.push_insn_id(block, insn_id);
2568+
continue;
2569+
}
25382570
ReceiverTypeResolution::Polymorphic => {
25392571
if get_option!(stats) {
25402572
self.set_dynamic_send_reason(insn_id, SendPolymorphic);
@@ -2815,7 +2847,7 @@ impl Function {
28152847
ReceiverTypeResolution::StaticallyKnown { class } => (class, None),
28162848
ReceiverTypeResolution::Monomorphic { class, profiled_type }
28172849
| ReceiverTypeResolution::SkewedPolymorphic { class, profiled_type } => (class, Some(profiled_type)),
2818-
ReceiverTypeResolution::Polymorphic | ReceiverTypeResolution::NoProfile => return Err(()),
2850+
ReceiverTypeResolution::SkewedMegamorphic { .. } | ReceiverTypeResolution::Polymorphic | ReceiverTypeResolution::Megamorphic | ReceiverTypeResolution::NoProfile => return Err(()),
28192851
};
28202852

28212853
// Do method lookup
@@ -2920,7 +2952,7 @@ impl Function {
29202952
ReceiverTypeResolution::StaticallyKnown { class } => (class, None),
29212953
ReceiverTypeResolution::Monomorphic { class, profiled_type }
29222954
| ReceiverTypeResolution::SkewedPolymorphic { class, profiled_type } => (class, Some(profiled_type)),
2923-
ReceiverTypeResolution::Polymorphic | ReceiverTypeResolution::NoProfile => return Err(()),
2955+
ReceiverTypeResolution::SkewedMegamorphic { .. } | ReceiverTypeResolution::Polymorphic | ReceiverTypeResolution::Megamorphic | ReceiverTypeResolution::NoProfile => return Err(()),
29242956
};
29252957

29262958
// Do method lookup

zjit/src/stats.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,15 @@ make_counters! {
168168
dynamic_send {
169169
// send_fallback_: Fallback reasons for send-ish instructions
170170
send_fallback_send_without_block_polymorphic,
171+
send_fallback_send_without_block_megamorphic,
171172
send_fallback_send_without_block_no_profiles,
172173
send_fallback_send_without_block_cfunc_not_variadic,
173174
send_fallback_send_without_block_cfunc_array_variadic,
174175
send_fallback_send_without_block_not_optimized_method_type,
175176
send_fallback_send_without_block_not_optimized_optimized_method_type,
176177
send_fallback_send_without_block_direct_too_many_args,
177178
send_fallback_send_polymorphic,
179+
send_fallback_send_megamorphic,
178180
send_fallback_send_no_profiles,
179181
send_fallback_send_not_optimized_method_type,
180182
send_fallback_ccall_with_frame_too_many_args,
@@ -428,6 +430,7 @@ pub fn send_fallback_counter(reason: crate::hir::SendFallbackReason) -> Counter
428430
use crate::stats::Counter::*;
429431
match reason {
430432
SendWithoutBlockPolymorphic => send_fallback_send_without_block_polymorphic,
433+
SendWithoutBlockMegamorphic => send_fallback_send_without_block_megamorphic,
431434
SendWithoutBlockNoProfiles => send_fallback_send_without_block_no_profiles,
432435
SendWithoutBlockCfuncNotVariadic => send_fallback_send_without_block_cfunc_not_variadic,
433436
SendWithoutBlockCfuncArrayVariadic => send_fallback_send_without_block_cfunc_array_variadic,
@@ -436,6 +439,7 @@ pub fn send_fallback_counter(reason: crate::hir::SendFallbackReason) -> Counter
436439
=> send_fallback_send_without_block_not_optimized_optimized_method_type,
437440
SendWithoutBlockDirectTooManyArgs => send_fallback_send_without_block_direct_too_many_args,
438441
SendPolymorphic => send_fallback_send_polymorphic,
442+
SendMegamorphic => send_fallback_send_megamorphic,
439443
SendNoProfiles => send_fallback_send_no_profiles,
440444
ComplexArgPass => send_fallback_one_or_more_complex_arg_pass,
441445
BmethodNonIseqProc => send_fallback_bmethod_non_iseq_proc,

0 commit comments

Comments
 (0)