Skip to content

Commit 64c2140

Browse files
committed
ZJIT: Parse newhash into HIR
1 parent b0f77c9 commit 64c2140

File tree

1 file changed

+96
-2
lines changed

1 file changed

+96
-2
lines changed

zjit/src/hir.rs

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ pub enum Insn {
327327
StringIntern { val: InsnId },
328328

329329
NewArray { elements: Vec<InsnId>, state: InsnId },
330+
/// NewHash contains a vec of (key, value) pairs
331+
NewHash { elements: Vec<(InsnId,InsnId)>, state: InsnId },
330332
ArraySet { array: InsnId, idx: usize, val: InsnId },
331333
ArrayDup { val: InsnId, state: InsnId },
332334
ArrayMax { elements: Vec<InsnId>, state: InsnId },
@@ -425,6 +427,7 @@ impl Insn {
425427
Insn::Param { .. } => false,
426428
Insn::StringCopy { .. } => false,
427429
Insn::NewArray { .. } => false,
430+
Insn::NewHash { .. } => false,
428431
Insn::ArrayDup { .. } => false,
429432
Insn::HashDup { .. } => false,
430433
Insn::Test { .. } => false,
@@ -467,6 +470,15 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
467470
}
468471
Ok(())
469472
}
473+
Insn::NewHash { elements, .. } => {
474+
write!(f, "NewHash")?;
475+
let mut prefix = " ";
476+
for (key, value) in elements {
477+
write!(f, "{prefix}{key}: {value}")?;
478+
prefix = ", ";
479+
}
480+
Ok(())
481+
}
470482
Insn::ArrayMax { elements, .. } => {
471483
write!(f, "ArrayMax")?;
472484
let mut prefix = " ";
@@ -874,6 +886,13 @@ impl Function {
874886
&CCall { cfun, ref args, name, return_type, elidable } => CCall { cfun: cfun, args: args.iter().map(|arg| find!(*arg)).collect(), name: name, return_type: return_type, elidable },
875887
Defined { .. } => todo!("find(Defined)"),
876888
NewArray { elements, state } => NewArray { elements: find_vec!(*elements), state: find!(*state) },
889+
&NewHash { ref elements, state } => {
890+
let mut found_elements = vec![];
891+
for &(key, value) in elements {
892+
found_elements.push((find!(key), find!(value)));
893+
}
894+
NewHash { elements: found_elements, state: find!(state) }
895+
}
877896
ArrayMax { elements, state } => ArrayMax { elements: find_vec!(*elements), state: find!(*state) },
878897
&GetIvar { self_val, id, state } => GetIvar { self_val: find!(self_val), id, state },
879898
&SetIvar { self_val, id, val, state } => SetIvar { self_val: find!(self_val), id, val, state },
@@ -923,6 +942,7 @@ impl Function {
923942
Insn::StringIntern { .. } => types::StringExact,
924943
Insn::NewArray { .. } => types::ArrayExact,
925944
Insn::ArrayDup { .. } => types::ArrayExact,
945+
Insn::NewHash { .. } => types::HashExact,
926946
Insn::HashDup { .. } => types::HashExact,
927947
Insn::CCall { return_type, .. } => *return_type,
928948
Insn::GuardType { val, guard_type, .. } => self.type_of(*val).intersection(*guard_type),
@@ -1396,6 +1416,13 @@ impl Function {
13961416
worklist.extend(elements);
13971417
worklist.push_back(state);
13981418
}
1419+
Insn::NewHash { elements, state } => {
1420+
for (key, value) in elements {
1421+
worklist.push_back(key);
1422+
worklist.push_back(value);
1423+
}
1424+
worklist.push_back(state);
1425+
}
13991426
Insn::StringCopy { val }
14001427
| Insn::StringIntern { val }
14011428
| Insn::Return { val }
@@ -1929,6 +1956,20 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
19291956
let insn_id = fun.push_insn(block, Insn::ArrayDup { val, state: exit_id });
19301957
state.stack_push(insn_id);
19311958
}
1959+
YARVINSN_newhash => {
1960+
let count = get_arg(pc, 0).as_usize();
1961+
assert!(count % 2 == 0, "newhash count should be even");
1962+
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
1963+
let mut elements = vec![];
1964+
eprintln!("count: {count}, state before: {state}");
1965+
for _ in 0..(count/2) {
1966+
let value = state.stack_pop()?;
1967+
let key = state.stack_pop()?;
1968+
elements.push((key, value));
1969+
}
1970+
elements.reverse();
1971+
state.stack_push(fun.push_insn(block, Insn::NewHash { elements, state: exit_id }));
1972+
}
19321973
YARVINSN_duphash => {
19331974
let val = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) });
19341975
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
@@ -2517,7 +2558,29 @@ mod tests {
25172558
"#]]);
25182559
}
25192560

2520-
// TODO(max): Test newhash when we have it
2561+
#[test]
2562+
fn test_new_hash_empty() {
2563+
eval("def test = {}");
2564+
assert_method_hir("test", expect![[r#"
2565+
fn test:
2566+
bb0():
2567+
v2:HashExact = NewHash
2568+
Return v2
2569+
"#]]);
2570+
}
2571+
2572+
#[test]
2573+
fn test_new_hash_with_elements() {
2574+
eval("def test(aval, bval) = {a: aval, b: bval}");
2575+
assert_method_hir("test", expect![[r#"
2576+
fn test:
2577+
bb0(v0:BasicObject, v1:BasicObject):
2578+
v3:StaticSymbol[VALUE(0x1000)] = Const Value(VALUE(0x1000))
2579+
v4:StaticSymbol[VALUE(0x1008)] = Const Value(VALUE(0x1008))
2580+
v6:HashExact = NewHash v3: v0, v4: v1
2581+
Return v6
2582+
"#]]);
2583+
}
25212584

25222585
#[test]
25232586
fn test_string_copy() {
@@ -3573,7 +3636,6 @@ mod opt_tests {
35733636
"#]]);
35743637
}
35753638

3576-
35773639
#[test]
35783640
fn test_eliminate_new_array() {
35793641
eval("
@@ -3608,6 +3670,38 @@ mod opt_tests {
36083670
"#]]);
36093671
}
36103672

3673+
#[test]
3674+
fn test_eliminate_new_hash() {
3675+
eval("
3676+
def test()
3677+
c = {}
3678+
5
3679+
end
3680+
");
3681+
assert_optimized_method_hir("test", expect![[r#"
3682+
fn test:
3683+
bb0():
3684+
v4:Fixnum[5] = Const Value(5)
3685+
Return v4
3686+
"#]]);
3687+
}
3688+
3689+
#[test]
3690+
fn test_eliminate_new_hash_with_elements() {
3691+
eval("
3692+
def test(aval, bval)
3693+
c = {a: aval, b: bval}
3694+
5
3695+
end
3696+
");
3697+
assert_optimized_method_hir("test", expect![[r#"
3698+
fn test:
3699+
bb0(v0:BasicObject, v1:BasicObject):
3700+
v8:Fixnum[5] = Const Value(5)
3701+
Return v8
3702+
"#]]);
3703+
}
3704+
36113705
#[test]
36123706
fn test_eliminate_array_dup() {
36133707
eval("

0 commit comments

Comments
 (0)