Skip to content

Commit 5a3f3f0

Browse files
authored
ZJIT: Parse getinstancevariable, setinstancevariable into HIR (#13413)
1 parent d96e9bd commit 5a3f3f0

File tree

1 file changed

+96
-4
lines changed

1 file changed

+96
-4
lines changed

zjit/src/hir.rs

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,10 @@ pub enum Insn {
338338
GetConstantPath { ic: *const iseq_inline_constant_cache },
339339

340340
//NewObject?
341-
//SetIvar {},
342-
//GetIvar {},
341+
/// Get an instance variable `id` from `self_val`
342+
GetIvar { self_val: InsnId, id: ID, state: InsnId },
343+
/// Set `self_val`'s instance variable `id` to `val`
344+
SetIvar { self_val: InsnId, id: ID, val: InsnId, state: InsnId },
343345

344346
/// Own a FrameState so that instructions can look up their dominating FrameState when
345347
/// generating deopt side-exits and frame reconstruction metadata. Does not directly generate
@@ -395,7 +397,7 @@ impl Insn {
395397
match self {
396398
Insn::ArraySet { .. } | Insn::Snapshot { .. } | Insn::Jump(_)
397399
| Insn::IfTrue { .. } | Insn::IfFalse { .. } | Insn::Return { .. }
398-
| Insn::PatchPoint { .. } => false,
400+
| Insn::PatchPoint { .. } | Insn::SetIvar { .. } => false,
399401
_ => true,
400402
}
401403
}
@@ -526,6 +528,8 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
526528
Ok(())
527529
},
528530
Insn::Snapshot { state } => write!(f, "Snapshot {}", state),
531+
Insn::GetIvar { self_val, id, .. } => write!(f, "GetIvar {self_val}, :{}", id.contents_lossy().into_owned()),
532+
Insn::SetIvar { self_val, id, val, .. } => write!(f, "SetIvar {self_val}, :{}, {val}", id.contents_lossy().into_owned()),
529533
insn => { write!(f, "{insn:?}") }
530534
}
531535
}
@@ -866,6 +870,8 @@ impl Function {
866870
Defined { .. } => todo!("find(Defined)"),
867871
NewArray { elements, state } => NewArray { elements: find_vec!(*elements), state: find!(*state) },
868872
ArrayMax { elements, state } => ArrayMax { elements: find_vec!(*elements), state: find!(*state) },
873+
&GetIvar { self_val, id, state } => GetIvar { self_val: find!(self_val), id, state },
874+
&SetIvar { self_val, id, val, state } => SetIvar { self_val: find!(self_val), id, val, state },
869875
}
870876
}
871877

@@ -891,7 +897,7 @@ impl Function {
891897
Insn::Param { .. } => unimplemented!("params should not be present in block.insns"),
892898
Insn::ArraySet { .. } | Insn::Snapshot { .. } | Insn::Jump(_)
893899
| Insn::IfTrue { .. } | Insn::IfFalse { .. } | Insn::Return { .. }
894-
| Insn::PatchPoint { .. } =>
900+
| Insn::PatchPoint { .. } | Insn::SetIvar { .. } =>
895901
panic!("Cannot infer type of instruction with no output"),
896902
Insn::Const { val: Const::Value(val) } => Type::from_value(*val),
897903
Insn::Const { val: Const::CBool(val) } => Type::from_cbool(*val),
@@ -933,6 +939,7 @@ impl Function {
933939
Insn::Defined { .. } => types::BasicObject,
934940
Insn::GetConstantPath { .. } => types::BasicObject,
935941
Insn::ArrayMax { .. } => types::BasicObject,
942+
Insn::GetIvar { .. } => types::BasicObject,
936943
}
937944
}
938945

@@ -1439,6 +1446,15 @@ impl Function {
14391446
worklist.push_back(state);
14401447
}
14411448
Insn::CCall { args, .. } => worklist.extend(args),
1449+
Insn::GetIvar { self_val, state, .. } => {
1450+
worklist.push_back(self_val);
1451+
worklist.push_back(state);
1452+
}
1453+
Insn::SetIvar { self_val, val, state, .. } => {
1454+
worklist.push_back(self_val);
1455+
worklist.push_back(val);
1456+
worklist.push_back(state);
1457+
}
14421458
}
14431459
}
14441460
// Now remove all unnecessary instructions
@@ -2096,6 +2112,22 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
20962112
let send = fun.push_insn(block, Insn::Send { self_val: recv, call_info: CallInfo { method_name }, cd, blockiseq, args, state: exit_id });
20972113
state.stack_push(send);
20982114
}
2115+
YARVINSN_getinstancevariable => {
2116+
let id = ID(get_arg(pc, 0).as_u64());
2117+
// ic is in arg 1
2118+
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
2119+
let self_val = fun.push_insn(block, Insn::PutSelf);
2120+
let result = fun.push_insn(block, Insn::GetIvar { self_val, id, state: exit_id });
2121+
state.stack_push(result);
2122+
}
2123+
YARVINSN_setinstancevariable => {
2124+
let id = ID(get_arg(pc, 0).as_u64());
2125+
// ic is in arg 1
2126+
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
2127+
let self_val = fun.push_insn(block, Insn::PutSelf);
2128+
let val = state.stack_pop()?;
2129+
fun.push_insn(block, Insn::SetIvar { self_val, id, val, state: exit_id });
2130+
}
20992131
_ => return Err(ParseError::UnknownOpcode(insn_name(opcode as usize))),
21002132
}
21012133

@@ -3042,6 +3074,37 @@ mod tests {
30423074
Return v6
30433075
"#]]);
30443076
}
3077+
3078+
#[test]
3079+
fn test_getinstancevariable() {
3080+
eval("
3081+
def test = @foo
3082+
test
3083+
");
3084+
assert_method_hir("test", expect![[r#"
3085+
fn test:
3086+
bb0():
3087+
v2:BasicObject = PutSelf
3088+
v3:BasicObject = GetIvar v2, :@foo
3089+
Return v3
3090+
"#]]);
3091+
}
3092+
3093+
#[test]
3094+
fn test_setinstancevariable() {
3095+
eval("
3096+
def test = @foo = 1
3097+
test
3098+
");
3099+
assert_method_hir("test", expect![[r#"
3100+
fn test:
3101+
bb0():
3102+
v1:Fixnum[1] = Const Value(1)
3103+
v3:BasicObject = PutSelf
3104+
SetIvar v3, :@foo, v1
3105+
Return v1
3106+
"#]]);
3107+
}
30453108
}
30463109

30473110
#[cfg(test)]
@@ -4097,4 +4160,33 @@ mod opt_tests {
40974160
Return v6
40984161
"#]]);
40994162
}
4163+
4164+
#[test]
4165+
fn test_getinstancevariable() {
4166+
eval("
4167+
def test = @foo
4168+
");
4169+
assert_optimized_method_hir("test", expect![[r#"
4170+
fn test:
4171+
bb0():
4172+
v2:BasicObject = PutSelf
4173+
v3:BasicObject = GetIvar v2, :@foo
4174+
Return v3
4175+
"#]]);
4176+
}
4177+
4178+
#[test]
4179+
fn test_setinstancevariable() {
4180+
eval("
4181+
def test = @foo = 1
4182+
");
4183+
assert_optimized_method_hir("test", expect![[r#"
4184+
fn test:
4185+
bb0():
4186+
v1:Fixnum[1] = Const Value(1)
4187+
v3:BasicObject = PutSelf
4188+
SetIvar v3, :@foo, v1
4189+
Return v1
4190+
"#]]);
4191+
}
41004192
}

0 commit comments

Comments
 (0)