ZJIT: Parse opt_aref_with into HIR
This commit is contained in:
parent
8070d5d97d
commit
6f0f84e5dd
Notes:
git
2025-06-04 10:23:44 +00:00
@ -4,11 +4,7 @@
|
|||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cruby::*,
|
cast::IntoUsize, cruby::*, options::{get_option, DumpHIR}, profile::{get_or_create_iseq_payload, IseqPayload}, state::ZJITState
|
||||||
options::{get_option, DumpHIR},
|
|
||||||
profile::{get_or_create_iseq_payload, IseqPayload},
|
|
||||||
state::ZJITState,
|
|
||||||
cast::IntoUsize,
|
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
@ -2195,7 +2191,32 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
|||||||
n -= 1;
|
n -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
YARVINSN_opt_aref_with => {
|
||||||
|
// NB: opt_aref_with has an instruction argument for the call at get_arg(0)
|
||||||
|
let cd: *const rb_call_data = get_arg(pc, 1).as_ptr();
|
||||||
|
let call_info = unsafe { rb_get_call_data_ci(cd) };
|
||||||
|
if unknown_call_type(unsafe { rb_vm_ci_flag(call_info) }) {
|
||||||
|
// Unknown call type; side-exit into the interpreter
|
||||||
|
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
|
||||||
|
fun.push_insn(block, Insn::SideExit { state: exit_id });
|
||||||
|
break; // End the block
|
||||||
|
}
|
||||||
|
let argc = unsafe { vm_ci_argc((*cd).ci) };
|
||||||
|
|
||||||
|
let method_name = unsafe {
|
||||||
|
let mid = rb_vm_ci_mid(call_info);
|
||||||
|
mid.contents_lossy().into_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(1, argc, "opt_aref_with should only be emitted for argc=1");
|
||||||
|
let aref_arg = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) });
|
||||||
|
let args = vec![aref_arg];
|
||||||
|
|
||||||
|
let recv = state.stack_pop()?;
|
||||||
|
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
|
||||||
|
let send = fun.push_insn(block, Insn::SendWithoutBlock { self_val: recv, call_info: CallInfo { method_name }, cd, args, state: exit_id });
|
||||||
|
state.stack_push(send);
|
||||||
|
}
|
||||||
YARVINSN_opt_neq => {
|
YARVINSN_opt_neq => {
|
||||||
// NB: opt_neq has two cd; get_arg(0) is for eq and get_arg(1) is for neq
|
// NB: opt_neq has two cd; get_arg(0) is for eq and get_arg(1) is for neq
|
||||||
let cd: *const rb_call_data = get_arg(pc, 1).as_ptr();
|
let cd: *const rb_call_data = get_arg(pc, 1).as_ptr();
|
||||||
@ -3597,6 +3618,20 @@ mod tests {
|
|||||||
"#]]);
|
"#]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_aref_with() {
|
||||||
|
eval("
|
||||||
|
def test(a) = a['string lit triggers aref_with']
|
||||||
|
");
|
||||||
|
assert_method_hir("test", expect![[r#"
|
||||||
|
fn test:
|
||||||
|
bb0(v0:BasicObject):
|
||||||
|
v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
|
||||||
|
v4:BasicObject = SendWithoutBlock v0, :[], v2
|
||||||
|
Return v4
|
||||||
|
"#]]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_branchnil() {
|
fn test_branchnil() {
|
||||||
eval("
|
eval("
|
||||||
|
Loading…
x
Reference in New Issue
Block a user