Skip to content

Commit 4c7faf9

Browse files
committed
ZJIT: handle megamorphic and skewed megamorphic profiling results
1 parent 30ebb8e commit 4c7faf9

2 files changed

Lines changed: 48 additions & 12 deletions

File tree

zjit/src/hir.rs

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -564,29 +564,35 @@ impl std::fmt::Display for SideExitReason {
564564
/// Represents whether we know the receiver's class statically at compile-time,
565565
/// have profiled type information, or know nothing about it.
566566
pub enum ReceiverTypeResolution {
567-
/// The receiver's class is statically known at JIT compile-time (no guard needed)
568-
StaticallyKnown { class: VALUE },
567+
/// No profile information available for the receiver
568+
NoProfile,
569569
/// The receiver has a monomorphic profile (single type observed, guard needed)
570570
Monomorphic { class: VALUE, profiled_type: ProfiledType },
571-
/// The receiver has a skewed polymorphic profile (dominant type with some other types, guard needed)
572-
SkewedPolymorphic { class: VALUE, profiled_type: ProfiledType },
573571
/// The receiver is polymorphic (multiple types, none dominant)
574572
Polymorphic,
575-
/// No profile information available for the receiver
576-
NoProfile,
573+
/// The receiver has a skewed polymorphic profile (dominant type with some other types, guard needed)
574+
SkewedPolymorphic { class: VALUE, profiled_type: ProfiledType },
575+
/// More than N types seen with no clear winner
576+
Megamorphic,
577+
/// Megamorphic, but with a significant skew towards one type
578+
SkewedMegamorphic { class: VALUE, profiled_type: ProfiledType },
579+
/// The receiver's class is statically known at JIT compile-time (no guard needed)
580+
StaticallyKnown { class: VALUE },
577581
}
578582

579583
/// Reason why a send-ish instruction cannot be optimized from a fallback instruction
580584
#[derive(Debug, Clone, Copy)]
581585
pub enum SendFallbackReason {
582586
SendWithoutBlockPolymorphic,
587+
SendWithoutBlockMegamorphic,
583588
SendWithoutBlockNoProfiles,
584589
SendWithoutBlockCfuncNotVariadic,
585590
SendWithoutBlockCfuncArrayVariadic,
586591
SendWithoutBlockNotOptimizedMethodType(MethodType),
587592
SendWithoutBlockNotOptimizedOptimizedMethodType(OptimizedMethodType),
588593
SendWithoutBlockDirectTooManyArgs,
589594
SendPolymorphic,
595+
SendMegamorphic,
590596
SendNoProfiles,
591597
SendNotOptimizedMethodType(MethodType),
592598
CCallWithFrameTooManyArgs,
@@ -2156,8 +2162,16 @@ impl Function {
21562162
class: profiled_type.class(),
21572163
profiled_type,
21582164
};
2165+
} else if entry_type_summary.is_skewed_megamorphic() {
2166+
let profiled_type = entry_type_summary.bucket(0);
2167+
return ReceiverTypeResolution::SkewedMegamorphic {
2168+
class: profiled_type.class(),
2169+
profiled_type,
2170+
};
21592171
} else if entry_type_summary.is_polymorphic() {
21602172
return ReceiverTypeResolution::Polymorphic;
2173+
} else if entry_type_summary.is_megamorphic() {
2174+
return ReceiverTypeResolution::Megamorphic;
21612175
}
21622176
}
21632177
}
@@ -2312,7 +2326,15 @@ impl Function {
23122326
let (klass, profiled_type) = match self.resolve_receiver_type(recv, self.type_of(recv), frame_state.insn_idx) {
23132327
ReceiverTypeResolution::StaticallyKnown { class } => (class, None),
23142328
ReceiverTypeResolution::Monomorphic { class, profiled_type }
2315-
| ReceiverTypeResolution::SkewedPolymorphic { class, profiled_type } => (class, Some(profiled_type)),
2329+
| ReceiverTypeResolution::SkewedPolymorphic { class, profiled_type }
2330+
| ReceiverTypeResolution::SkewedMegamorphic { class, profiled_type } => (class, Some(profiled_type)),
2331+
ReceiverTypeResolution::Megamorphic => {
2332+
if get_option!(stats) {
2333+
self.set_dynamic_send_reason(insn_id, SendWithoutBlockMegamorphic);
2334+
}
2335+
self.push_insn_id(block, insn_id);
2336+
continue;
2337+
}
23162338
ReceiverTypeResolution::Polymorphic => {
23172339
if get_option!(stats) {
23182340
self.set_dynamic_send_reason(insn_id, SendWithoutBlockPolymorphic);
@@ -2505,7 +2527,15 @@ impl Function {
25052527
let klass = match self.resolve_receiver_type(recv, self.type_of(recv), frame_state.insn_idx) {
25062528
ReceiverTypeResolution::StaticallyKnown { class } => class,
25072529
ReceiverTypeResolution::Monomorphic { class, .. }
2508-
| ReceiverTypeResolution::SkewedPolymorphic { class, .. } => class,
2530+
| ReceiverTypeResolution::SkewedPolymorphic { class, .. }
2531+
| ReceiverTypeResolution::SkewedMegamorphic { class, .. } => class,
2532+
ReceiverTypeResolution::Megamorphic => {
2533+
if get_option!(stats) {
2534+
self.set_dynamic_send_reason(insn_id, SendMegamorphic);
2535+
}
2536+
self.push_insn_id(block, insn_id);
2537+
continue;
2538+
}
25092539
ReceiverTypeResolution::Polymorphic => {
25102540
if get_option!(stats) {
25112541
self.set_dynamic_send_reason(insn_id, SendPolymorphic);
@@ -2785,8 +2815,9 @@ impl Function {
27852815
let (recv_class, profiled_type) = match fun.resolve_receiver_type(recv, self_type, iseq_insn_idx) {
27862816
ReceiverTypeResolution::StaticallyKnown { class } => (class, None),
27872817
ReceiverTypeResolution::Monomorphic { class, profiled_type }
2788-
| ReceiverTypeResolution::SkewedPolymorphic { class, profiled_type } => (class, Some(profiled_type)),
2789-
ReceiverTypeResolution::Polymorphic | ReceiverTypeResolution::NoProfile => return Err(()),
2818+
| ReceiverTypeResolution::SkewedPolymorphic { class, profiled_type }
2819+
| ReceiverTypeResolution::SkewedMegamorphic { class, profiled_type } => (class, Some(profiled_type)),
2820+
ReceiverTypeResolution::Polymorphic | ReceiverTypeResolution::Megamorphic | ReceiverTypeResolution::NoProfile => return Err(()),
27902821
};
27912822

27922823
// Do method lookup
@@ -2890,8 +2921,9 @@ impl Function {
28902921
let (recv_class, profiled_type) = match fun.resolve_receiver_type(recv, self_type, iseq_insn_idx) {
28912922
ReceiverTypeResolution::StaticallyKnown { class } => (class, None),
28922923
ReceiverTypeResolution::Monomorphic { class, profiled_type }
2893-
| ReceiverTypeResolution::SkewedPolymorphic { class, profiled_type } => (class, Some(profiled_type)),
2894-
ReceiverTypeResolution::Polymorphic | ReceiverTypeResolution::NoProfile => return Err(()),
2924+
| ReceiverTypeResolution::SkewedPolymorphic { class, profiled_type }
2925+
| ReceiverTypeResolution::SkewedMegamorphic { class, profiled_type } => (class, Some(profiled_type)),
2926+
ReceiverTypeResolution::Polymorphic | ReceiverTypeResolution::Megamorphic | ReceiverTypeResolution::NoProfile => return Err(()),
28952927
};
28962928

28972929
// Do method lookup

zjit/src/stats.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,15 @@ make_counters! {
165165
dynamic_send {
166166
// send_fallback_: Fallback reasons for send-ish instructions
167167
send_fallback_send_without_block_polymorphic,
168+
send_fallback_send_without_block_megamorphic,
168169
send_fallback_send_without_block_no_profiles,
169170
send_fallback_send_without_block_cfunc_not_variadic,
170171
send_fallback_send_without_block_cfunc_array_variadic,
171172
send_fallback_send_without_block_not_optimized_method_type,
172173
send_fallback_send_without_block_not_optimized_optimized_method_type,
173174
send_fallback_send_without_block_direct_too_many_args,
174175
send_fallback_send_polymorphic,
176+
send_fallback_send_megamorphic,
175177
send_fallback_send_no_profiles,
176178
send_fallback_send_not_optimized_method_type,
177179
send_fallback_ccall_with_frame_too_many_args,
@@ -422,6 +424,7 @@ pub fn send_fallback_counter(reason: crate::hir::SendFallbackReason) -> Counter
422424
use crate::stats::Counter::*;
423425
match reason {
424426
SendWithoutBlockPolymorphic => send_fallback_send_without_block_polymorphic,
427+
SendWithoutBlockMegamorphic => send_fallback_send_without_block_megamorphic,
425428
SendWithoutBlockNoProfiles => send_fallback_send_without_block_no_profiles,
426429
SendWithoutBlockCfuncNotVariadic => send_fallback_send_without_block_cfunc_not_variadic,
427430
SendWithoutBlockCfuncArrayVariadic => send_fallback_send_without_block_cfunc_array_variadic,
@@ -430,6 +433,7 @@ pub fn send_fallback_counter(reason: crate::hir::SendFallbackReason) -> Counter
430433
=> send_fallback_send_without_block_not_optimized_optimized_method_type,
431434
SendWithoutBlockDirectTooManyArgs => send_fallback_send_without_block_direct_too_many_args,
432435
SendPolymorphic => send_fallback_send_polymorphic,
436+
SendMegamorphic => send_fallback_send_megamorphic,
433437
SendNoProfiles => send_fallback_send_no_profiles,
434438
ComplexArgPass => send_fallback_one_or_more_complex_arg_pass,
435439
BmethodNonIseqProc => send_fallback_bmethod_non_iseq_proc,

0 commit comments

Comments
 (0)