summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2025-09-10 08:54:10 -0700
committerGitHub <noreply@github.com>2025-09-10 08:54:10 -0700
commitc0e01a271475ae765fc92e31245e42ea2b2d43f6 (patch)
tree0318198fa11b106a97daba1995879b8b8acdba1d
parent928fea3bfa86053c0bc6f7a5bf7559b115a676b5 (diff)
ZJIT: Compile ISEQs with forwardable parameters (#14491)
-rw-r--r--test/ruby/test_zjit.rb15
-rw-r--r--zjit/src/hir.rs36
-rw-r--r--zjit/src/stats.rs5
3 files changed, 33 insertions, 23 deletions
diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb
index 5f59f9fc02..f010995e58 100644
--- a/test/ruby/test_zjit.rb
+++ b/test/ruby/test_zjit.rb
@@ -439,6 +439,21 @@ class TestZJIT < Test::Unit::TestCase
}, call_threshold: 2
end
+ def test_forwardable_iseq
+ assert_compiles '1', %q{
+ def test(...) = 1
+ test
+ }
+ end
+
+ def test_sendforward
+ assert_runs '[1, 2]', %q{
+ def callee(a, b) = [a, b]
+ def test(...) = callee(...)
+ test(1, 2)
+ }, insns: [:sendforward]
+ end
+
def test_iseq_with_optional_arguments
assert_compiles '[[1, 2], [3, 4]]', %q{
def test(a, b = 2) = [a, b]
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs
index b7674b6a8c..aa05882a60 100644
--- a/zjit/src/hir.rs
+++ b/zjit/src/hir.rs
@@ -2966,16 +2966,8 @@ pub enum CallType {
}
#[derive(Clone, Debug, PartialEq)]
-pub enum ParameterType {
- /// For example, `foo(...)`. Interaction of JIT
- /// calling convention and side exits currently unsolved.
- Forwardable,
-}
-
-#[derive(Clone, Debug, PartialEq)]
pub enum ParseError {
StackUnderflow(FrameState),
- UnknownParameterType(ParameterType),
MalformedIseq(u32), // insn_idx into iseq_encoded
Validation(ValidationError),
NotAllowed,
@@ -3049,17 +3041,11 @@ impl ProfileOracle {
/// The index of the self parameter in the HIR function
pub const SELF_PARAM_IDX: usize = 0;
-fn filter_unknown_parameter_type(iseq: *const rb_iseq_t) -> Result<(), ParseError> {
- if unsafe { rb_get_iseq_flags_forwardable(iseq) } { return Err(ParseError::UnknownParameterType(ParameterType::Forwardable)); }
- Ok(())
-}
-
/// Compile ISEQ into High-level IR
pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
if !ZJITState::can_compile_iseq(iseq) {
return Err(ParseError::NotAllowed);
}
- filter_unknown_parameter_type(iseq)?;
let payload = get_or_create_iseq_payload(iseq);
let mut profiles = ProfileOracle::new(payload);
let mut fun = Function::new(iseq);
@@ -5198,13 +5184,23 @@ mod tests {
eval("
def test(...) = super(...)
");
- assert_compile_fails("test", ParseError::UnknownParameterType(ParameterType::Forwardable));
+ assert_snapshot!(hir_string("test"), @r"
+ fn test@<compiled>:2:
+ bb0(v0:BasicObject, v1:BasicObject):
+ SideExit UnhandledYARVInsn(invokesuperforward)
+ ");
}
#[test]
- fn test_cant_compile_forwardable() {
+ fn test_compile_forwardable() {
eval("def forwardable(...) = nil");
- assert_compile_fails("forwardable", ParseError::UnknownParameterType(ParameterType::Forwardable));
+ assert_snapshot!(hir_string("forwardable"), @r"
+ fn forwardable@<compiled>:1:
+ bb0(v0:BasicObject, v1:BasicObject):
+ v5:NilClass = Const Value(nil)
+ CheckInterrupts
+ Return v5
+ ");
}
// TODO(max): Figure out how to generate a call with OPT_SEND flag
@@ -5249,7 +5245,11 @@ mod tests {
eval("
def test(...) = foo(...)
");
- assert_compile_fails("test", ParseError::UnknownParameterType(ParameterType::Forwardable));
+ assert_snapshot!(hir_string("test"), @r"
+ fn test@<compiled>:2:
+ bb0(v0:BasicObject, v1:BasicObject):
+ SideExit UnhandledYARVInsn(sendforward)
+ ");
}
#[test]
diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs
index 67edfe3d2d..471704bc06 100644
--- a/zjit/src/stats.rs
+++ b/zjit/src/stats.rs
@@ -130,7 +130,6 @@ make_counters! {
compile_error_parse_malformed_iseq,
compile_error_parse_validation,
compile_error_parse_not_allowed,
- compile_error_parse_parameter_type_forwardable,
// The number of times YARV instructions are executed on JIT code
zjit_insn_count,
@@ -196,7 +195,6 @@ pub enum CompileError {
/// Return a raw pointer to the exit counter for a given CompileError
pub fn exit_counter_for_compile_error(compile_error: &CompileError) -> Counter {
use crate::hir::ParseError::*;
- use crate::hir::ParameterType::*;
use crate::stats::CompileError::*;
use crate::stats::Counter::*;
match compile_error {
@@ -210,9 +208,6 @@ pub fn exit_counter_for_compile_error(compile_error: &CompileError) -> Counter {
MalformedIseq(_) => compile_error_parse_malformed_iseq,
Validation(_) => compile_error_parse_validation,
NotAllowed => compile_error_parse_not_allowed,
- UnknownParameterType(parameter_type) => match parameter_type {
- Forwardable => compile_error_parse_parameter_type_forwardable,
- }
}
}
}