Skip to content

Commit 5d87dd6

Browse files
authored
ZJIT: Handle splatkw YARV instruction (ruby#16267)
The most common cases are nil and hash, so just cover those. If we need to convert to a hash, we can handle that later.
1 parent 68080fe commit 5d87dd6

7 files changed

Lines changed: 334 additions & 61 deletions

File tree

insns.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ splatkw
569569
(VALUE hash, VALUE block)
570570
(VALUE obj, VALUE block)
571571
// attr bool leaf = false; /* has rb_to_hash_type() */
572+
// attr bool zjit_profile = true;
572573
{
573574
if (NIL_P(hash)) {
574575
obj = Qnil;

yjit/src/cruby_bindings.inc.rs

Lines changed: 31 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

zjit/src/cruby_bindings.inc.rs

Lines changed: 31 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

zjit/src/hir.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,9 @@ pub enum SideExitReason {
522522
FixnumModByZero,
523523
FixnumDivByZero,
524524
BoxFixnumOverflow,
525+
SplatKwNotNilOrHash,
526+
SplatKwPolymorphic,
527+
SplatKwNotProfiled,
525528
}
526529

527530
#[derive(Debug, Clone, Copy)]
@@ -6708,6 +6711,33 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
67086711
};
67096712
state.stack_push(obj);
67106713
}
6714+
YARVINSN_splatkw => {
6715+
let block_val = state.stack_pop()?;
6716+
let hash = state.stack_pop()?;
6717+
// Get profiled type of hash (operand index 0)
6718+
let summary = profiles.payload.profile.get_operand_types(exit_state.insn_idx)
6719+
.and_then(|types| types.first())
6720+
.map(|dist| TypeDistributionSummary::new(dist));
6721+
let Some(summary) = summary else {
6722+
fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::SplatKwNotProfiled });
6723+
break; // End the block
6724+
};
6725+
if !summary.is_monomorphic() {
6726+
fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::SplatKwPolymorphic });
6727+
break; // End the block
6728+
}
6729+
let ty = Type::from_profiled_type(summary.bucket(0));
6730+
let obj = if ty.is_subtype(types::NilClass) {
6731+
fun.push_insn(block, Insn::GuardType { val: hash, guard_type: types::NilClass, state: exit_id })
6732+
} else if ty.is_subtype(types::HashExact) {
6733+
fun.push_insn(block, Insn::GuardType { val: hash, guard_type: types::HashExact, state: exit_id })
6734+
} else {
6735+
fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::SplatKwNotNilOrHash });
6736+
break; // End the block
6737+
};
6738+
state.stack_push(obj);
6739+
state.stack_push(block_val);
6740+
}
67116741
YARVINSN_concattoarray => {
67126742
let right = state.stack_pop()?;
67136743
let left = state.stack_pop()?;

0 commit comments

Comments
 (0)