@@ -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 } ,
@@ -2975,9 +2976,23 @@ impl Function {
29752976 return Err ( ( ) ) ;
29762977 }
29772978
2978- // Find the `argc` (arity) of the C method, which describes the parameters it expects
2979+ let ci_flags = unsafe { vm_ci_flag ( call_info) } ;
2980+
2981+ // When seeing &block argument, fall back to dynamic dispatch for now
2982+ // TODO: Support block forwarding
2983+ if unspecializable_call_type ( ci_flags) {
2984+ fun. count_complex_call_features ( block, ci_flags) ;
2985+ fun. set_dynamic_send_reason ( send_insn_id, ComplexArgPass ) ;
2986+ return Err ( ( ) ) ;
2987+ }
2988+
2989+ let blockiseq = if blockiseq. is_null ( ) { None } else { Some ( blockiseq) } ;
2990+
29792991 let cfunc = unsafe { get_cme_def_body_cfunc ( cme) } ;
2992+ // Find the `argc` (arity) of the C method, which describes the parameters it expects
29802993 let cfunc_argc = unsafe { get_mct_argc ( cfunc) } ;
2994+ let cfunc_ptr = unsafe { get_mct_func ( cfunc) } . cast ( ) ;
2995+
29812996 match cfunc_argc {
29822997 0 .. => {
29832998 // (self, arg0, arg1, ..., argc) form
@@ -2987,16 +3002,6 @@ impl Function {
29873002 return Err ( ( ) ) ;
29883003 }
29893004
2990- let ci_flags = unsafe { vm_ci_flag ( call_info) } ;
2991-
2992- // When seeing &block argument, fall back to dynamic dispatch for now
2993- // TODO: Support block forwarding
2994- if unspecializable_call_type ( ci_flags) {
2995- fun. count_complex_call_features ( block, ci_flags) ;
2996- fun. set_dynamic_send_reason ( send_insn_id, ComplexArgPass ) ;
2997- return Err ( ( ) ) ;
2998- }
2999-
30003005 // Commit to the replacement. Put PatchPoint.
30013006 fun. gen_patch_points_for_optimized_ccall ( block, recv_class, method_id, cme, state) ;
30023007 if recv_class. instance_can_have_singleton_class ( ) {
@@ -3009,17 +3014,14 @@ impl Function {
30093014 fun. insn_types [ recv. 0 ] = fun. infer_type ( recv) ;
30103015 }
30113016
3012- let blockiseq = if blockiseq. is_null ( ) { None } else { Some ( blockiseq) } ;
3013-
30143017 // Emit a call
3015- let cfunc = unsafe { get_mct_func ( cfunc) } . cast ( ) ;
30163018 let mut cfunc_args = vec ! [ recv] ;
30173019 cfunc_args. append ( & mut args) ;
30183020
30193021 let name = rust_str_to_id ( & qualified_method_name ( unsafe { ( * cme) . owner } , unsafe { ( * cme) . called_id } ) ) ;
30203022 let ccall = fun. push_insn ( block, Insn :: CCallWithFrame {
30213023 cd,
3022- cfunc,
3024+ cfunc : cfunc_ptr ,
30233025 args : cfunc_args,
30243026 cme,
30253027 name,
@@ -3033,9 +3035,37 @@ impl Function {
30333035 }
30343036 // Variadic method
30353037 -1 => {
3038+ // The method gets a pointer to the first argument
30363039 // func(int argc, VALUE *argv, VALUE recv)
3037- fun. set_dynamic_send_reason ( send_insn_id, SendCfuncVariadic ) ;
3038- Err ( ( ) )
3040+ fun. gen_patch_points_for_optimized_ccall ( block, recv_class, method_id, cme, state) ;
3041+
3042+ if recv_class. instance_can_have_singleton_class ( ) {
3043+ fun. push_insn ( block, Insn :: PatchPoint { invariant : Invariant :: NoSingletonClass { klass : recv_class } , state } ) ;
3044+ }
3045+ if let Some ( profiled_type) = profiled_type {
3046+ // Guard receiver class
3047+ recv = fun. push_insn ( block, Insn :: GuardType { val : recv, guard_type : Type :: from_profiled_type ( profiled_type) , state } ) ;
3048+ fun. insn_types [ recv. 0 ] = fun. infer_type ( recv) ;
3049+ }
3050+
3051+ if get_option ! ( stats) {
3052+ count_not_inlined_cfunc ( fun, block, cme) ;
3053+ }
3054+
3055+ let ccall = fun. push_insn ( block, Insn :: CCallVariadic {
3056+ cfunc : cfunc_ptr,
3057+ recv,
3058+ args,
3059+ cme,
3060+ name : method_id,
3061+ state,
3062+ return_type : types:: BasicObject ,
3063+ elidable : false ,
3064+ blockiseq
3065+ } ) ;
3066+
3067+ fun. make_equal_to ( send_insn_id, ccall) ;
3068+ Ok ( ( ) )
30393069 }
30403070 -2 => {
30413071 // (self, args_ruby_array)
@@ -3238,6 +3268,7 @@ impl Function {
32383268 state,
32393269 return_type,
32403270 elidable,
3271+ blockiseq : None ,
32413272 } ) ;
32423273
32433274 fun. make_equal_to ( send_insn_id, ccall) ;
0 commit comments