Skip to content

Commit 849e2db

Browse files
committed
ZJIT: Parse newhash into HIR
1 parent 30c0307 commit 849e2db

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

zjit/src/hir.rs

Lines changed: 95 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,19 @@ 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+
for _ in 0..(count/2) {
1965+
let value = state.stack_pop()?;
1966+
let key = state.stack_pop()?;
1967+
elements.push((key, value));
1968+
}
1969+
elements.reverse();
1970+
state.stack_push(fun.push_insn(block, Insn::NewHash { elements, state: exit_id }));
1971+
}
19321972
YARVINSN_duphash => {
19331973
let val = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) });
19341974
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
@@ -2517,7 +2557,29 @@ mod tests {
25172557
"#]]);
25182558
}
25192559

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

25222584
#[test]
25232585
fn test_string_copy() {
@@ -3573,7 +3635,6 @@ mod opt_tests {
35733635
"#]]);
35743636
}
35753637

3576-
35773638
#[test]
35783639
fn test_eliminate_new_array() {
35793640
eval("
@@ -3608,6 +3669,38 @@ mod opt_tests {
36083669
"#]]);
36093670
}
36103671

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

0 commit comments

Comments
 (0)