@@ -804,6 +804,7 @@ pub enum Insn {
804804 state : InsnId ,
805805 return_type : Type ,
806806 elidable : bool ,
807+ blockiseq : Option < IseqPtr > ,
807808 } ,
808809
809810 /// Un-optimized fallback implementation (dynamic dispatch) for send-ish instructions
@@ -1920,8 +1921,8 @@ impl Function {
19201921 elidable,
19211922 blockiseq,
19221923 } ,
1923- & CCallVariadic { cfunc, recv, ref args, cme, name, state, return_type, elidable } => CCallVariadic {
1924- cfunc, recv : find ! ( recv) , args : find_vec ! ( args) , cme, name, state, return_type, elidable
1924+ & CCallVariadic { cfunc, recv, ref args, cme, name, state, return_type, elidable, blockiseq } => CCallVariadic {
1925+ cfunc, recv : find ! ( recv) , args : find_vec ! ( args) , cme, name, state, return_type, elidable, blockiseq
19251926 } ,
19261927 & Defined { op_type, obj, pushval, v, state } => Defined { op_type, obj, pushval, v : find ! ( v) , state : find ! ( state) } ,
19271928 & DefinedIvar { self_val, pushval, id, state } => DefinedIvar { self_val : find ! ( self_val) , pushval, id, state } ,
@@ -2989,9 +2990,23 @@ impl Function {
29892990 return Err ( ( ) ) ;
29902991 }
29912992
2992- // Find the `argc` (arity) of the C method, which describes the parameters it expects
2993+ let ci_flags = unsafe { vm_ci_flag ( call_info) } ;
2994+
2995+ // When seeing &block argument, fall back to dynamic dispatch for now
2996+ // TODO: Support block forwarding
2997+ if unspecializable_call_type ( ci_flags) {
2998+ fun. count_complex_call_features ( block, ci_flags) ;
2999+ fun. set_dynamic_send_reason ( send_insn_id, ComplexArgPass ) ;
3000+ return Err ( ( ) ) ;
3001+ }
3002+
3003+ let blockiseq = if blockiseq. is_null ( ) { None } else { Some ( blockiseq) } ;
3004+
29933005 let cfunc = unsafe { get_cme_def_body_cfunc ( cme) } ;
3006+ // Find the `argc` (arity) of the C method, which describes the parameters it expects
29943007 let cfunc_argc = unsafe { get_mct_argc ( cfunc) } ;
3008+ let cfunc_ptr = unsafe { get_mct_func ( cfunc) } . cast ( ) ;
3009+
29953010 match cfunc_argc {
29963011 0 .. => {
29973012 // (self, arg0, arg1, ..., argc) form
@@ -3001,16 +3016,6 @@ impl Function {
30013016 return Err ( ( ) ) ;
30023017 }
30033018
3004- let ci_flags = unsafe { vm_ci_flag ( call_info) } ;
3005-
3006- // When seeing &block argument, fall back to dynamic dispatch for now
3007- // TODO: Support block forwarding
3008- if unspecializable_call_type ( ci_flags) {
3009- fun. count_complex_call_features ( block, ci_flags) ;
3010- fun. set_dynamic_send_reason ( send_insn_id, ComplexArgPass ) ;
3011- return Err ( ( ) ) ;
3012- }
3013-
30143019 // Commit to the replacement. Put PatchPoint.
30153020 fun. gen_patch_points_for_optimized_ccall ( block, recv_class, method_id, cme, state) ;
30163021 if recv_class. instance_can_have_singleton_class ( ) {
@@ -3023,17 +3028,14 @@ impl Function {
30233028 fun. insn_types [ recv. 0 ] = fun. infer_type ( recv) ;
30243029 }
30253030
3026- let blockiseq = if blockiseq. is_null ( ) { None } else { Some ( blockiseq) } ;
3027-
30283031 // Emit a call
3029- let cfunc = unsafe { get_mct_func ( cfunc) } . cast ( ) ;
30303032 let mut cfunc_args = vec ! [ recv] ;
30313033 cfunc_args. append ( & mut args) ;
30323034
30333035 let name = rust_str_to_id ( & qualified_method_name ( unsafe { ( * cme) . owner } , unsafe { ( * cme) . called_id } ) ) ;
30343036 let ccall = fun. push_insn ( block, Insn :: CCallWithFrame {
30353037 cd,
3036- cfunc,
3038+ cfunc : cfunc_ptr ,
30373039 args : cfunc_args,
30383040 cme,
30393041 name,
@@ -3047,9 +3049,37 @@ impl Function {
30473049 }
30483050 // Variadic method
30493051 -1 => {
3052+ // The method gets a pointer to the first argument
30503053 // func(int argc, VALUE *argv, VALUE recv)
3051- fun. set_dynamic_send_reason ( send_insn_id, SendCfuncVariadic ) ;
3052- Err ( ( ) )
3054+ fun. gen_patch_points_for_optimized_ccall ( block, recv_class, method_id, cme, state) ;
3055+
3056+ if recv_class. instance_can_have_singleton_class ( ) {
3057+ fun. push_insn ( block, Insn :: PatchPoint { invariant : Invariant :: NoSingletonClass { klass : recv_class } , state } ) ;
3058+ }
3059+ if let Some ( profiled_type) = profiled_type {
3060+ // Guard receiver class
3061+ recv = fun. push_insn ( block, Insn :: GuardType { val : recv, guard_type : Type :: from_profiled_type ( profiled_type) , state } ) ;
3062+ fun. insn_types [ recv. 0 ] = fun. infer_type ( recv) ;
3063+ }
3064+
3065+ if get_option ! ( stats) {
3066+ count_not_inlined_cfunc ( fun, block, cme) ;
3067+ }
3068+
3069+ let ccall = fun. push_insn ( block, Insn :: CCallVariadic {
3070+ cfunc : cfunc_ptr,
3071+ recv,
3072+ args,
3073+ cme,
3074+ name : method_id,
3075+ state,
3076+ return_type : types:: BasicObject ,
3077+ elidable : false ,
3078+ blockiseq
3079+ } ) ;
3080+
3081+ fun. make_equal_to ( send_insn_id, ccall) ;
3082+ Ok ( ( ) )
30533083 }
30543084 -2 => {
30553085 // (self, args_ruby_array)
@@ -3252,6 +3282,7 @@ impl Function {
32523282 state,
32533283 return_type,
32543284 elidable,
3285+ blockiseq : None ,
32553286 } ) ;
32563287
32573288 fun. make_equal_to ( send_insn_id, ccall) ;
0 commit comments