summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Bernstein <ruby@bernsteinbear.com>2025-10-09 10:12:46 +0200
committerMax Bernstein <tekknolagi@gmail.com>2025-10-09 19:09:27 +0200
commitfc735e257d65ba09ebc62dd698fda35bf4f0a585 (patch)
treeaea7860855f348fde12231bac2c14a45fa2c775e
parente1c998ab917ba3a319ca0fd32f0857f1dbace906 (diff)
ZJIT: Allow marking CCallWithFrame elidable
Also mark Array#reverse as elidable.
-rw-r--r--zjit/src/cruby_methods.rs2
-rw-r--r--zjit/src/hir.rs35
2 files changed, 33 insertions, 4 deletions
diff --git a/zjit/src/cruby_methods.rs b/zjit/src/cruby_methods.rs
index 1df348bc9e..334d4e2337 100644
--- a/zjit/src/cruby_methods.rs
+++ b/zjit/src/cruby_methods.rs
@@ -173,7 +173,7 @@ pub fn init() -> Annotations {
annotate!(rb_cArray, "length", types::Fixnum, no_gc, leaf, elidable);
annotate!(rb_cArray, "size", types::Fixnum, no_gc, leaf, elidable);
annotate!(rb_cArray, "empty?", types::BoolExact, no_gc, leaf, elidable);
- annotate!(rb_cArray, "reverse", types::ArrayExact);
+ annotate!(rb_cArray, "reverse", types::ArrayExact, leaf, elidable);
annotate!(rb_cHash, "empty?", types::BoolExact, no_gc, leaf, elidable);
annotate!(rb_cNilClass, "nil?", types::TrueClass, no_gc, leaf, elidable);
annotate!(rb_mKernel, "nil?", types::FalseClass, no_gc, leaf, elidable);
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs
index 32024102cf..ec6746ec39 100644
--- a/zjit/src/hir.rs
+++ b/zjit/src/hir.rs
@@ -658,6 +658,7 @@ pub enum Insn {
name: ID,
state: InsnId,
return_type: Type,
+ elidable: bool,
},
/// Call a variadic C function with signature: func(int argc, VALUE *argv, VALUE recv)
@@ -846,6 +847,7 @@ impl Insn {
Insn::LoadIvarEmbedded { .. } => false,
Insn::LoadIvarExtended { .. } => false,
Insn::CCall { elidable, .. } => !elidable,
+ Insn::CCallWithFrame { elidable, .. } => !elidable,
Insn::ObjectAllocClass { .. } => false,
// TODO: NewRange is effects free if we can prove the two ends to be Fixnum,
// but we don't have type information here in `impl Insn`. See rb_range_new().
@@ -1565,7 +1567,7 @@ impl Function {
&ObjectAlloc { val, state } => ObjectAlloc { val: find!(val), state },
&ObjectAllocClass { class, state } => ObjectAllocClass { class, state: find!(state) },
&CCall { cfunc, ref args, name, return_type, elidable } => CCall { cfunc, args: find_vec!(args), name, return_type, elidable },
- &CCallWithFrame { cd, cfunc, ref args, cme, name, state, return_type } => CCallWithFrame { cd, cfunc, args: find_vec!(args), cme, name, state: find!(state), return_type },
+ &CCallWithFrame { cd, cfunc, ref args, cme, name, state, return_type, elidable } => CCallWithFrame { cd, cfunc, args: find_vec!(args), cme, name, state: find!(state), return_type, elidable },
&CCallVariadic { cfunc, recv, ref args, cme, name, state } => CCallVariadic {
cfunc, recv: find!(recv), args: find_vec!(args), cme, name, state
},
@@ -2349,15 +2351,15 @@ impl Function {
return_type: types::BasicObject,
elidable: false });
let return_type = props.return_type;
+ let elidable = props.elidable;
if props.leaf && props.no_gc {
- let elidable = props.elidable;
let ccall = fun.push_insn(block, Insn::CCall { cfunc, args: cfunc_args, name: method_id, return_type, elidable });
fun.make_equal_to(send_insn_id, ccall);
} else {
if get_option!(stats) {
count_not_inlined_cfunc(fun, block, method);
}
- let ccall = fun.push_insn(block, Insn::CCallWithFrame { cd, cfunc, args: cfunc_args, cme: method, name: method_id, state, return_type });
+ let ccall = fun.push_insn(block, Insn::CCallWithFrame { cd, cfunc, args: cfunc_args, cme: method, name: method_id, state, return_type, elidable });
fun.make_equal_to(send_insn_id, ccall);
}
@@ -12461,4 +12463,31 @@ mod opt_tests {
Return v22
");
}
+
+ #[test]
+ fn test_array_reverse_is_elidable() {
+ eval(r#"
+ def test
+ [].reverse
+ 5
+ end
+ "#);
+ assert_snapshot!(hir_string("test"), @r"
+ fn test@<compiled>:3:
+ bb0():
+ EntryPoint interpreter
+ v1:BasicObject = LoadSelf
+ Jump bb2(v1)
+ bb1(v4:BasicObject):
+ EntryPoint JIT(0)
+ Jump bb2(v4)
+ bb2(v6:BasicObject):
+ v11:ArrayExact = NewArray
+ PatchPoint MethodRedefined(Array@0x1000, reverse@0x1008, cme:0x1010)
+ PatchPoint NoSingletonClass(Array@0x1000)
+ v16:Fixnum[5] = Const Value(5)
+ CheckInterrupts
+ Return v16
+ ");
+ }
}