diff options
| author | Max Bernstein <max@bernsteinbear.com> | 2026-01-11 16:25:13 -0500 |
|---|---|---|
| committer | Max Bernstein <tekknolagi@gmail.com> | 2026-01-12 16:43:49 -0500 |
| commit | 5cec11f45a9b6282e9bc402b599dd95159b86649 (patch) | |
| tree | ae021a26a60b941af5a7dcb0fb2085788c009a25 | |
| parent | a1ba9f5733711a7665b57977d78940e07ff281a5 (diff) | |
ZJIT: Inline Array#length
| -rw-r--r-- | zjit/src/cruby_methods.rs | 14 | ||||
| -rw-r--r-- | zjit/src/hir.rs | 1 | ||||
| -rw-r--r-- | zjit/src/hir/opt_tests.rs | 50 |
3 files changed, 37 insertions, 28 deletions
diff --git a/zjit/src/cruby_methods.rs b/zjit/src/cruby_methods.rs index 4aa9068cb1..e6c26148cf 100644 --- a/zjit/src/cruby_methods.rs +++ b/zjit/src/cruby_methods.rs @@ -219,8 +219,7 @@ pub fn init() -> Annotations { annotate!(rb_cString, "ascii_only?", types::BoolExact, no_gc, leaf); annotate!(rb_cModule, "name", types::StringExact.union(types::NilClass), no_gc, leaf, elidable); annotate!(rb_cModule, "===", inline_module_eqq, types::BoolExact, no_gc, leaf); - annotate!(rb_cArray, "length", types::Fixnum, no_gc, leaf, elidable); - annotate!(rb_cArray, "size", types::Fixnum, no_gc, leaf, elidable); + annotate!(rb_cArray, "length", inline_array_length, types::Fixnum, no_gc, leaf, elidable); annotate!(rb_cArray, "empty?", types::BoolExact, no_gc, leaf, elidable); annotate!(rb_cArray, "reverse", types::ArrayExact, leaf, elidable); annotate!(rb_cArray, "join", types::StringExact); @@ -537,6 +536,17 @@ fn inline_module_eqq(fun: &mut hir::Function, block: hir::BlockId, recv: hir::In None } +fn inline_array_length(fun: &mut hir::Function, block: hir::BlockId, recv: hir::InsnId, args: &[hir::InsnId], state: hir::InsnId) -> Option<hir::InsnId> { + let &[] = args else { return None; }; + if fun.likely_a(recv, types::Array, state) { + let recv = fun.coerce_to(block, recv, types::Array, state); + let length_cint = fun.push_insn(block, hir::Insn::ArrayLength { array: recv }); + let result = fun.push_insn(block, hir::Insn::BoxFixnum { val: length_cint, state }); + return Some(result); + } + None +} + fn inline_integer_succ(fun: &mut hir::Function, block: hir::BlockId, recv: hir::InsnId, args: &[hir::InsnId], state: hir::InsnId) -> Option<hir::InsnId> { if !args.is_empty() { return None; } if fun.likely_a(recv, types::Fixnum, state) { diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index c6a104fbd1..41ddb3ae69 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -1027,6 +1027,7 @@ impl Insn { // NewHash's operands may be hashed and compared for equality, which could have // side-effects. Insn::NewHash { elements, .. } => !elements.is_empty(), + Insn::ArrayLength { .. } => false, Insn::ArrayDup { .. } => false, Insn::HashDup { .. } => false, Insn::Test { .. } => false, diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs index 3ad07596b7..4fc47dc611 100644 --- a/zjit/src/hir/opt_tests.rs +++ b/zjit/src/hir/opt_tests.rs @@ -2291,7 +2291,7 @@ mod hir_opt_tests { fn eliminate_array_length() { eval(" def test - x = [].length + [].length 5 end "); @@ -2300,21 +2300,18 @@ mod hir_opt_tests { bb0(): EntryPoint interpreter v1:BasicObject = LoadSelf - v2:NilClass = Const Value(nil) - Jump bb2(v1, v2) - bb1(v5:BasicObject): + Jump bb2(v1) + bb1(v4:BasicObject): EntryPoint JIT(0) - v6:NilClass = Const Value(nil) - Jump bb2(v5, v6) - bb2(v8:BasicObject, v9:NilClass): - v13:ArrayExact = NewArray + Jump bb2(v4) + bb2(v6:BasicObject): + v10:ArrayExact = NewArray PatchPoint MethodRedefined(Array@0x1000, length@0x1008, cme:0x1010) PatchPoint NoSingletonClass(Array@0x1000) IncrCounter inline_cfunc_optimized_send_count - v29:Fixnum = CCall v13, :Array#length@0x1038 - v20:Fixnum[5] = Const Value(5) + v17:Fixnum[5] = Const Value(5) CheckInterrupts - Return v20 + Return v17 "); } @@ -2435,7 +2432,7 @@ mod hir_opt_tests { fn eliminate_array_size() { eval(" def test - x = [].size + [].size 5 end "); @@ -2444,21 +2441,18 @@ mod hir_opt_tests { bb0(): EntryPoint interpreter v1:BasicObject = LoadSelf - v2:NilClass = Const Value(nil) - Jump bb2(v1, v2) - bb1(v5:BasicObject): + Jump bb2(v1) + bb1(v4:BasicObject): EntryPoint JIT(0) - v6:NilClass = Const Value(nil) - Jump bb2(v5, v6) - bb2(v8:BasicObject, v9:NilClass): - v13:ArrayExact = NewArray + Jump bb2(v4) + bb2(v6:BasicObject): + v10:ArrayExact = NewArray PatchPoint MethodRedefined(Array@0x1000, size@0x1008, cme:0x1010) PatchPoint NoSingletonClass(Array@0x1000) IncrCounter inline_cfunc_optimized_send_count - v29:Fixnum = CCall v13, :Array#size@0x1038 - v20:Fixnum[5] = Const Value(5) + v17:Fixnum[5] = Const Value(5) CheckInterrupts - Return v20 + Return v17 "); } @@ -3554,8 +3548,9 @@ mod hir_opt_tests { v18:ArrayExact = NewArray v11, v12 PatchPoint MethodRedefined(Array@0x1000, length@0x1008, cme:0x1010) PatchPoint NoSingletonClass(Array@0x1000) + v29:CInt64 = ArrayLength v18 + v30:Fixnum = BoxFixnum v29 IncrCounter inline_cfunc_optimized_send_count - v30:Fixnum = CCall v18, :Array#length@0x1038 CheckInterrupts Return v30 "); @@ -3581,8 +3576,9 @@ mod hir_opt_tests { v18:ArrayExact = NewArray v11, v12 PatchPoint MethodRedefined(Array@0x1000, size@0x1008, cme:0x1010) PatchPoint NoSingletonClass(Array@0x1000) + v29:CInt64 = ArrayLength v18 + v30:Fixnum = BoxFixnum v29 IncrCounter inline_cfunc_optimized_send_count - v30:Fixnum = CCall v18, :Array#size@0x1038 CheckInterrupts Return v30 "); @@ -7170,8 +7166,9 @@ mod hir_opt_tests { PatchPoint MethodRedefined(Array@0x1000, length@0x1008, cme:0x1010) PatchPoint NoSingletonClass(Array@0x1000) v23:ArrayExact = GuardType v9, ArrayExact + v24:CInt64 = ArrayLength v23 + v25:Fixnum = BoxFixnum v24 IncrCounter inline_cfunc_optimized_send_count - v25:Fixnum = CCall v23, :Array#length@0x1038 CheckInterrupts Return v25 "); @@ -7198,8 +7195,9 @@ mod hir_opt_tests { PatchPoint MethodRedefined(Array@0x1000, size@0x1008, cme:0x1010) PatchPoint NoSingletonClass(Array@0x1000) v23:ArrayExact = GuardType v9, ArrayExact + v24:CInt64 = ArrayLength v23 + v25:Fixnum = BoxFixnum v24 IncrCounter inline_cfunc_optimized_send_count - v25:Fixnum = CCall v23, :Array#size@0x1038 CheckInterrupts Return v25 "); |
