ZJIT: Fix rest parameter not parsed into a BB parameter

Use total parameter size instead of lead parameter size when parsing
iseq into hir. Also, copy over IntoUsize for compile-time checked
u32->usize cast.
This commit is contained in:
Alan Wu 2025-05-08 22:18:09 +09:00
parent 074dce8370
commit 767e8e165a
Notes: git 2025-05-14 11:13:40 +00:00

View File

@ -6,6 +6,7 @@ use crate::{
options::{get_option, DumpHIR}, options::{get_option, DumpHIR},
profile::{self, get_or_create_iseq_payload}, profile::{self, get_or_create_iseq_payload},
state::ZJITState, state::ZJITState,
cast::IntoUsize,
}; };
use std::{cell::RefCell, collections::{HashMap, HashSet, VecDeque}, ffi::c_void, mem::{align_of, size_of}, ptr, slice::Iter}; use std::{cell::RefCell, collections::{HashMap, HashSet, VecDeque}, ffi::c_void, mem::{align_of, size_of}, ptr, slice::Iter};
use crate::hir_type::{Type, types}; use crate::hir_type::{Type, types};
@ -1674,15 +1675,9 @@ pub enum ParseError {
UnhandledCallType(CallType), UnhandledCallType(CallType),
} }
fn num_lead_params(iseq: *const rb_iseq_t) -> usize {
let result = unsafe { rb_get_iseq_body_param_lead_num(iseq) };
assert!(result >= 0, "Can't have negative # of parameters");
result as usize
}
/// Return the number of locals in the current ISEQ (includes parameters) /// Return the number of locals in the current ISEQ (includes parameters)
fn num_locals(iseq: *const rb_iseq_t) -> usize { fn num_locals(iseq: *const rb_iseq_t) -> usize {
(unsafe { get_iseq_body_local_table_size(iseq) }) as usize (unsafe { get_iseq_body_local_table_size(iseq) }).as_usize()
} }
/// If we can't handle the type of send (yet), bail out. /// If we can't handle the type of send (yet), bail out.
@ -1717,9 +1712,13 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
// Iteratively fill out basic blocks using a queue // Iteratively fill out basic blocks using a queue
// TODO(max): Basic block arguments at edges // TODO(max): Basic block arguments at edges
let mut queue = std::collections::VecDeque::new(); let mut queue = std::collections::VecDeque::new();
// The HIR function will have the same number of parameter as the iseq so
// we properly handle calls from the interpreter. Roughly speaking, each
// item between commas in the source increase the parameter count by one,
// regardless of parameter kind.
let mut entry_state = FrameState::new(iseq); let mut entry_state = FrameState::new(iseq);
for idx in 0..num_locals(iseq) { for idx in 0..num_locals(iseq) {
if idx < num_lead_params(iseq) { if idx < unsafe { get_iseq_body_param_size(iseq) }.as_usize() {
entry_state.locals.push(fun.push_insn(fun.entry_block, Insn::Param { idx })); entry_state.locals.push(fun.push_insn(fun.entry_block, Insn::Param { idx }));
} else { } else {
entry_state.locals.push(fun.push_insn(fun.entry_block, Insn::Const { val: Const::Value(Qnil) })); entry_state.locals.push(fun.push_insn(fun.entry_block, Insn::Const { val: Const::Value(Qnil) }));