summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Lo <stan.lo@shopify.com>2025-09-19 19:52:34 +0100
committerMax Bernstein <tekknolagi@gmail.com>2025-09-19 17:18:59 -0400
commit2ad3fbb9c79673bed3bad57c89f4a6fc3729c2b6 (patch)
tree73254592ddaa70d2f71cdb18f2610c2559cb7437
parent642188fb87a42c04d5672f4c9d16644d6cbcb207 (diff)
ZJIT: Simplify NewHash HIR and Codegen
We can use `Vec<Opnd>` instead of `Vec<(Opnd, Opnd)>` in NewHash HIR as it's the only usage of such type, which requires special handling.
-rw-r--r--zjit/src/codegen.rs19
-rw-r--r--zjit/src/hir.rs29
2 files changed, 15 insertions, 33 deletions
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index e0fd6cf2bd..7185c171c1 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -346,7 +346,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
Insn::Const { val: Const::Value(val) } => gen_const(*val),
Insn::Const { .. } => panic!("Unexpected Const in gen_insn: {insn}"),
Insn::NewArray { elements, state } => gen_new_array(asm, opnds!(elements), &function.frame_state(*state)),
- Insn::NewHash { elements, state } => gen_new_hash(jit, asm, elements, &function.frame_state(*state)),
+ Insn::NewHash { elements, state } => gen_new_hash(jit, asm, opnds!(elements), &function.frame_state(*state)),
Insn::NewRange { low, high, flag, state } => gen_new_range(jit, asm, opnd!(low), opnd!(high), *flag, &function.frame_state(*state)),
Insn::NewRangeFixnum { low, high, flag, state } => gen_new_range_fixnum(asm, opnd!(low), opnd!(high), *flag, &function.frame_state(*state)),
Insn::ArrayDup { val, state } => gen_array_dup(asm, opnd!(val), &function.frame_state(*state)),
@@ -1259,7 +1259,7 @@ fn gen_new_array(
fn gen_new_hash(
jit: &mut JITState,
asm: &mut Assembler,
- elements: &[(InsnId, InsnId)],
+ elements: Vec<Opnd>,
state: &FrameState,
) -> lir::Opnd {
gen_prepare_non_leaf_call(jit, asm, state);
@@ -1268,19 +1268,10 @@ fn gen_new_hash(
let new_hash = asm_ccall!(asm, rb_hash_new_with_size, lir::Opnd::Imm(cap));
if !elements.is_empty() {
- let mut pairs = Vec::new();
- for (key_id, val_id) in elements.iter() {
- let key = jit.get_opnd(*key_id);
- let val = jit.get_opnd(*val_id);
- pairs.push(key);
- pairs.push(val);
- }
-
- let argv = gen_push_opnds(jit, asm, &pairs);
- let argc = (elements.len() * 2) as ::std::os::raw::c_long;
- asm_ccall!(asm, rb_hash_bulk_insert, lir::Opnd::Imm(argc), argv, new_hash);
+ let argv = gen_push_opnds(jit, asm, &elements);
+ asm_ccall!(asm, rb_hash_bulk_insert, elements.len().into(), argv, new_hash);
- gen_pop_opnds(asm, &pairs);
+ gen_pop_opnds(asm, &elements);
}
new_hash
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs
index 08bdd5311f..1cc0294929 100644
--- a/zjit/src/hir.rs
+++ b/zjit/src/hir.rs
@@ -549,7 +549,7 @@ pub enum Insn {
ToNewArray { val: InsnId, state: InsnId },
NewArray { elements: Vec<InsnId>, state: InsnId },
/// NewHash contains a vec of (key, value) pairs
- NewHash { elements: Vec<(InsnId,InsnId)>, state: InsnId },
+ NewHash { elements: Vec<InsnId>, state: InsnId },
NewRange { low: InsnId, high: InsnId, flag: RangeType, state: InsnId },
NewRangeFixnum { low: InsnId, high: InsnId, flag: RangeType, state: InsnId },
ArrayDup { val: InsnId, state: InsnId },
@@ -816,9 +816,11 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
Insn::NewHash { elements, .. } => {
write!(f, "NewHash")?;
let mut prefix = " ";
- for (key, value) in elements {
- write!(f, "{prefix}{key}: {value}")?;
- prefix = ", ";
+ for chunk in elements.chunks(2) {
+ if let [key, value] = chunk {
+ write!(f, "{prefix}{key}: {value}")?;
+ prefix = ", ";
+ }
}
Ok(())
}
@@ -1462,13 +1464,7 @@ impl Function {
&Defined { op_type, obj, pushval, v, state } => Defined { op_type, obj, pushval, v: find!(v), state: find!(state) },
&DefinedIvar { self_val, pushval, id, state } => DefinedIvar { self_val: find!(self_val), pushval, id, state },
&NewArray { ref elements, state } => NewArray { elements: find_vec!(elements), state: find!(state) },
- &NewHash { ref elements, state } => {
- let mut found_elements = vec![];
- for &(key, value) in elements {
- found_elements.push((find!(key), find!(value)));
- }
- NewHash { elements: found_elements, state: find!(state) }
- }
+ &NewHash { ref elements, state } => NewHash { elements: find_vec!(elements), state: find!(state) },
&NewRange { low, high, flag, state } => NewRange { low: find!(low), high: find!(high), flag, state: find!(state) },
&NewRangeFixnum { low, high, flag, state } => NewRangeFixnum { low: find!(low), high: find!(high), flag, state: find!(state) },
&ArrayMax { ref elements, state } => ArrayMax { elements: find_vec!(elements), state: find!(state) },
@@ -2369,17 +2365,11 @@ impl Function {
worklist.push_back(state);
}
&Insn::ArrayMax { ref elements, state }
+ | &Insn::NewHash { ref elements, state }
| &Insn::NewArray { ref elements, state } => {
worklist.extend(elements);
worklist.push_back(state);
}
- &Insn::NewHash { ref elements, state } => {
- for &(key, value) in elements {
- worklist.push_back(key);
- worklist.push_back(value);
- }
- worklist.push_back(state);
- }
&Insn::NewRange { low, high, state, .. }
| &Insn::NewRangeFixnum { low, high, state, .. } => {
worklist.push_back(low);
@@ -3430,7 +3420,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
for _ in 0..(count/2) {
let value = state.stack_pop()?;
let key = state.stack_pop()?;
- elements.push((key, value));
+ elements.push(value);
+ elements.push(key);
}
elements.reverse();
state.stack_push(fun.push_insn(block, Insn::NewHash { elements, state: exit_id }));