@@ -14,6 +14,13 @@ use std::ffi::c_void;
1414use crate :: hir_type:: { types, Type } ;
1515use crate :: hir;
1616
17+ // Array iteration builtin functions (defined in array.c)
18+ unsafe extern "C" {
19+ fn ary_at_end ( ec : EcPtr , self_ : VALUE , index : VALUE ) -> VALUE ;
20+ fn ary_at ( ec : EcPtr , self_ : VALUE , index : VALUE ) -> VALUE ;
21+ fn fixnum_inc ( ec : EcPtr , self_ : VALUE , num : VALUE ) -> VALUE ;
22+ }
23+
1724pub struct Annotations {
1825 cfuncs : HashMap < * mut c_void , FnProperties > ,
1926 builtin_funcs : HashMap < * mut c_void , FnProperties > ,
@@ -270,6 +277,11 @@ pub fn init() -> Annotations {
270277 annotate_builtin ! ( rb_cSymbol, "name" , types:: StringExact ) ;
271278 annotate_builtin ! ( rb_cSymbol, "to_s" , types:: StringExact ) ;
272279
280+ // Array iteration builtins (used in with_jit Array#each, map, select, find)
281+ builtin_funcs. insert ( fixnum_inc as * mut c_void , FnProperties { inline : inline_fixnum_inc, return_type : types:: Fixnum , ..Default :: default ( ) } ) ;
282+ builtin_funcs. insert ( ary_at as * mut c_void , FnProperties { inline : inline_ary_at, ..Default :: default ( ) } ) ;
283+ builtin_funcs. insert ( ary_at_end as * mut c_void , FnProperties { inline : inline_ary_at_end, return_type : types:: BoolExact , ..Default :: default ( ) } ) ;
284+
273285 Annotations {
274286 cfuncs : std:: mem:: take ( cfuncs) ,
275287 builtin_funcs : std:: mem:: take ( builtin_funcs) ,
@@ -892,3 +904,33 @@ fn inline_kernel_class(fun: &mut hir::Function, block: hir::BlockId, _recv: hir:
892904 let real_class = unsafe { rb_class_real ( recv_class) } ;
893905 Some ( fun. push_insn ( block, hir:: Insn :: Const { val : hir:: Const :: Value ( real_class) } ) )
894906}
907+
908+ /// Inline `fixnum_inc(ec, self, num)` implies FixnumAdd(num, 1).
909+ /// num is always a Fixnum (starts at 0 and is incremented by fixnum_inc).
910+ fn inline_fixnum_inc ( fun : & mut hir:: Function , block : hir:: BlockId , _recv : hir:: InsnId , args : & [ hir:: InsnId ] , state : hir:: InsnId ) -> Option < hir:: InsnId > {
911+ let & [ _self, num] = args else { return None ; } ;
912+ let one = fun. push_insn ( block, hir:: Insn :: Const { val : hir:: Const :: Value ( VALUE :: fixnum_from_usize ( 1 ) ) } ) ;
913+ let result = fun. push_insn ( block, hir:: Insn :: FixnumAdd { left : num, right : one, state } ) ;
914+ Some ( result)
915+ }
916+
917+ /// Inline `ary_at(ec, self, index)` implies ArrayAref.
918+ /// Called from Array#each etc. where self is Array and index is in bounds.
919+ fn inline_ary_at ( fun : & mut hir:: Function , block : hir:: BlockId , _recv : hir:: InsnId , args : & [ hir:: InsnId ] , _state : hir:: InsnId ) -> Option < hir:: InsnId > {
920+ let & [ recv, index] = args else { return None ; } ;
921+ let recv = fun. push_insn ( block, hir:: Insn :: RefineType { val : recv, new_type : types:: Array } ) ;
922+ let index = fun. push_insn ( block, hir:: Insn :: UnboxFixnum { val : index } ) ;
923+ let result = fun. push_insn ( block, hir:: Insn :: ArrayAref { array : recv, index } ) ;
924+ Some ( result)
925+ }
926+
927+ /// Inline `ary_at_end(ec, self, index)` implies index >= ArrayLength(self).
928+ /// Called from Array#each etc. where self is Array and index is Fixnum.
929+ fn inline_ary_at_end ( fun : & mut hir:: Function , block : hir:: BlockId , _recv : hir:: InsnId , args : & [ hir:: InsnId ] , state : hir:: InsnId ) -> Option < hir:: InsnId > {
930+ let & [ recv, index] = args else { return None ; } ;
931+ let recv = fun. push_insn ( block, hir:: Insn :: RefineType { val : recv, new_type : types:: Array } ) ;
932+ let length_cint = fun. push_insn ( block, hir:: Insn :: ArrayLength { array : recv } ) ;
933+ let length = fun. push_insn ( block, hir:: Insn :: BoxFixnum { val : length_cint, state } ) ;
934+ let result = fun. push_insn ( block, hir:: Insn :: FixnumGe { left : index, right : length } ) ;
935+ Some ( result)
936+ }
0 commit comments