Skip to content

Commit 6f0f84e

Browse files
committed
ZJIT: Parse opt_aref_with into HIR
1 parent 8070d5d commit 6f0f84e

File tree

1 file changed

+40
-5
lines changed

1 file changed

+40
-5
lines changed

zjit/src/hir.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@
44
#![allow(non_upper_case_globals)]
55

66
use crate::{
7-
cruby::*,
8-
options::{get_option, DumpHIR},
9-
profile::{get_or_create_iseq_payload, IseqPayload},
10-
state::ZJITState,
11-
cast::IntoUsize,
7+
cast::IntoUsize, cruby::*, options::{get_option, DumpHIR}, profile::{get_or_create_iseq_payload, IseqPayload}, state::ZJITState
128
};
139
use std::{
1410
cell::RefCell,
@@ -2195,7 +2191,32 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
21952191
n -= 1;
21962192
}
21972193
}
2194+
YARVINSN_opt_aref_with => {
2195+
// NB: opt_aref_with has an instruction argument for the call at get_arg(0)
2196+
let cd: *const rb_call_data = get_arg(pc, 1).as_ptr();
2197+
let call_info = unsafe { rb_get_call_data_ci(cd) };
2198+
if unknown_call_type(unsafe { rb_vm_ci_flag(call_info) }) {
2199+
// Unknown call type; side-exit into the interpreter
2200+
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
2201+
fun.push_insn(block, Insn::SideExit { state: exit_id });
2202+
break; // End the block
2203+
}
2204+
let argc = unsafe { vm_ci_argc((*cd).ci) };
2205+
2206+
let method_name = unsafe {
2207+
let mid = rb_vm_ci_mid(call_info);
2208+
mid.contents_lossy().into_owned()
2209+
};
2210+
2211+
assert_eq!(1, argc, "opt_aref_with should only be emitted for argc=1");
2212+
let aref_arg = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) });
2213+
let args = vec![aref_arg];
21982214

2215+
let recv = state.stack_pop()?;
2216+
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
2217+
let send = fun.push_insn(block, Insn::SendWithoutBlock { self_val: recv, call_info: CallInfo { method_name }, cd, args, state: exit_id });
2218+
state.stack_push(send);
2219+
}
21992220
YARVINSN_opt_neq => {
22002221
// NB: opt_neq has two cd; get_arg(0) is for eq and get_arg(1) is for neq
22012222
let cd: *const rb_call_data = get_arg(pc, 1).as_ptr();
@@ -3597,6 +3618,20 @@ mod tests {
35973618
"#]]);
35983619
}
35993620

3621+
#[test]
3622+
fn test_aref_with() {
3623+
eval("
3624+
def test(a) = a['string lit triggers aref_with']
3625+
");
3626+
assert_method_hir("test", expect![[r#"
3627+
fn test:
3628+
bb0(v0:BasicObject):
3629+
v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
3630+
v4:BasicObject = SendWithoutBlock v0, :[], v2
3631+
Return v4
3632+
"#]]);
3633+
}
3634+
36003635
#[test]
36013636
fn test_branchnil() {
36023637
eval("

0 commit comments

Comments
 (0)