@@ -5468,8 +5468,8 @@ fn gen_send_iseq(
54685468 return CantCompile ;
54695469 }
54705470
5471- if iseq_has_rest && unsafe { get_iseq_flags_has_kw ( iseq) } {
5472- gen_counter_incr ! ( asm, send_iseq_has_rest_and_kw ) ;
5471+ if iseq_has_rest && unsafe { get_iseq_flags_has_kw ( iseq) } && supplying_kws {
5472+ gen_counter_incr ! ( asm, send_iseq_has_rest_and_kw_supplying ) ;
54735473 return CantCompile ;
54745474 }
54755475
@@ -5800,6 +5800,92 @@ fn gen_send_iseq(
58005800 handle_opt_send_shift_stack ( asm, argc, ctx) ;
58015801 }
58025802
5803+ if iseq_has_rest {
5804+ // We are going to allocate so setting pc and sp.
5805+ jit_save_pc ( jit, asm) ;
5806+ gen_save_sp ( asm, ctx) ;
5807+
5808+ if flags & VM_CALL_ARGS_SPLAT != 0 {
5809+ let non_rest_arg_count = argc - 1 ;
5810+ // We start by dupping the array because someone else might have
5811+ // a reference to it.
5812+ let array = ctx. stack_pop ( 1 ) ;
5813+ let array = asm. ccall (
5814+ rb_ary_dup as * const u8 ,
5815+ vec ! [ array] ,
5816+ ) ;
5817+ if non_rest_arg_count > required_num {
5818+ // If we have more arguments than required, we need to prepend
5819+ // the items from the stack onto the array.
5820+ let diff = ( non_rest_arg_count - required_num) as u32 ;
5821+
5822+ // diff is >0 so no need to worry about null pointer
5823+ asm. comment ( "load pointer to array elements" ) ;
5824+ let offset_magnitude = SIZEOF_VALUE as u32 * diff;
5825+ let values_opnd = ctx. sp_opnd ( -( offset_magnitude as isize ) ) ;
5826+ let values_ptr = asm. lea ( values_opnd) ;
5827+
5828+ asm. comment ( "prepend stack values to rest array" ) ;
5829+ let array = asm. ccall (
5830+ rb_yjit_rb_ary_unshift_m as * const u8 ,
5831+ vec ! [ Opnd :: UImm ( diff as u64 ) , values_ptr, array] ,
5832+ ) ;
5833+ ctx. stack_pop ( diff as usize ) ;
5834+
5835+ let stack_ret = ctx. stack_push ( Type :: TArray ) ;
5836+ asm. mov ( stack_ret, array) ;
5837+ // We now should have the required arguments
5838+ // and an array of all the rest arguments
5839+ argc = required_num + 1 ;
5840+ } else if non_rest_arg_count < required_num {
5841+ // If we have fewer arguments than required, we need to take some
5842+ // from the array and move them to the stack.
5843+ let diff = ( required_num - non_rest_arg_count) as u32 ;
5844+ // This moves the arguments onto the stack. But it doesn't modify the array.
5845+ move_rest_args_to_stack ( array, diff, ctx, asm, ocb, side_exit) ;
5846+
5847+ // We will now slice the array to give us a new array of the correct size
5848+ let ret = asm. ccall ( rb_yjit_rb_ary_subseq_length as * const u8 , vec ! [ array, Opnd :: UImm ( diff as u64 ) ] ) ;
5849+ let stack_ret = ctx. stack_push ( Type :: TArray ) ;
5850+ asm. mov ( stack_ret, ret) ;
5851+
5852+ // We now should have the required arguments
5853+ // and an array of all the rest arguments
5854+ argc = required_num + 1 ;
5855+ } else {
5856+ // The arguments are equal so we can just push to the stack
5857+ assert ! ( non_rest_arg_count == required_num) ;
5858+ let stack_ret = ctx. stack_push ( Type :: TArray ) ;
5859+ asm. mov ( stack_ret, array) ;
5860+ }
5861+ } else {
5862+ assert ! ( argc >= required_num) ;
5863+ let n = ( argc - required_num) as u32 ;
5864+ argc = required_num + 1 ;
5865+ // If n is 0, then elts is never going to be read, so we can just pass null
5866+ let values_ptr = if n == 0 {
5867+ Opnd :: UImm ( 0 )
5868+ } else {
5869+ asm. comment ( "load pointer to array elements" ) ;
5870+ let offset_magnitude = SIZEOF_VALUE as u32 * n;
5871+ let values_opnd = ctx. sp_opnd ( -( offset_magnitude as isize ) ) ;
5872+ asm. lea ( values_opnd)
5873+ } ;
5874+
5875+ let new_ary = asm. ccall (
5876+ rb_ec_ary_new_from_values as * const u8 ,
5877+ vec ! [
5878+ EC ,
5879+ Opnd :: UImm ( n. into( ) ) ,
5880+ values_ptr
5881+ ]
5882+ ) ;
5883+ ctx. stack_pop ( n. as_usize ( ) ) ;
5884+ let stack_ret = ctx. stack_push ( Type :: CArray ) ;
5885+ asm. mov ( stack_ret, new_ary) ;
5886+ }
5887+ }
5888+
58035889 if doing_kw_call {
58045890 // Here we're calling a method with keyword arguments and specifying
58055891 // keyword arguments at this call site.
@@ -5966,93 +6052,7 @@ fn gen_send_iseq(
59666052 argc = lead_num;
59676053 }
59686054
5969- if iseq_has_rest {
5970-
5971- // We are going to allocate so setting pc and sp.
5972- jit_save_pc ( jit, asm) ;
5973- gen_save_sp ( asm, ctx) ;
5974-
5975- if flags & VM_CALL_ARGS_SPLAT != 0 {
5976- let non_rest_arg_count = argc - 1 ;
5977- // We start by dupping the array because someone else might have
5978- // a reference to it.
5979- let array = ctx. stack_pop ( 1 ) ;
5980- let array = asm. ccall (
5981- rb_ary_dup as * const u8 ,
5982- vec ! [ array] ,
5983- ) ;
5984- if non_rest_arg_count > required_num {
5985- // If we have more arguments than required, we need to prepend
5986- // the items from the stack onto the array.
5987- let diff = ( non_rest_arg_count - required_num) as u32 ;
5988-
5989- // diff is >0 so no need to worry about null pointer
5990- asm. comment ( "load pointer to array elements" ) ;
5991- let offset_magnitude = SIZEOF_VALUE as u32 * diff;
5992- let values_opnd = ctx. sp_opnd ( -( offset_magnitude as isize ) ) ;
5993- let values_ptr = asm. lea ( values_opnd) ;
5994-
5995- asm. comment ( "prepend stack values to rest array" ) ;
5996- let array = asm. ccall (
5997- rb_yjit_rb_ary_unshift_m as * const u8 ,
5998- vec ! [ Opnd :: UImm ( diff as u64 ) , values_ptr, array] ,
5999- ) ;
6000- ctx. stack_pop ( diff as usize ) ;
6001-
6002- let stack_ret = ctx. stack_push ( Type :: TArray ) ;
6003- asm. mov ( stack_ret, array) ;
6004- // We now should have the required arguments
6005- // and an array of all the rest arguments
6006- argc = required_num + 1 ;
6007- } else if non_rest_arg_count < required_num {
6008- // If we have fewer arguments than required, we need to take some
6009- // from the array and move them to the stack.
6010- let diff = ( required_num - non_rest_arg_count) as u32 ;
6011- // This moves the arguments onto the stack. But it doesn't modify the array.
6012- move_rest_args_to_stack ( array, diff, ctx, asm, ocb, side_exit) ;
6013-
6014- // We will now slice the array to give us a new array of the correct size
6015- let ret = asm. ccall ( rb_yjit_rb_ary_subseq_length as * const u8 , vec ! [ array, Opnd :: UImm ( diff as u64 ) ] ) ;
6016- let stack_ret = ctx. stack_push ( Type :: TArray ) ;
6017- asm. mov ( stack_ret, ret) ;
60186055
6019- // We now should have the required arguments
6020- // and an array of all the rest arguments
6021- argc = required_num + 1 ;
6022- } else {
6023- // The arguments are equal so we can just push to the stack
6024- assert ! ( non_rest_arg_count == required_num) ;
6025- let stack_ret = ctx. stack_push ( Type :: TArray ) ;
6026- asm. mov ( stack_ret, array) ;
6027- }
6028- } else {
6029- assert ! ( argc >= required_num) ;
6030- let n = ( argc - required_num) as u32 ;
6031- argc = required_num + 1 ;
6032- // If n is 0, then elts is never going to be read, so we can just pass null
6033- let values_ptr = if n == 0 {
6034- Opnd :: UImm ( 0 )
6035- } else {
6036- asm. comment ( "load pointer to array elements" ) ;
6037- let offset_magnitude = SIZEOF_VALUE as u32 * n;
6038- let values_opnd = ctx. sp_opnd ( -( offset_magnitude as isize ) ) ;
6039- asm. lea ( values_opnd)
6040- } ;
6041-
6042- let new_ary = asm. ccall (
6043- rb_ec_ary_new_from_values as * const u8 ,
6044- vec ! [
6045- EC ,
6046- Opnd :: UImm ( n. into( ) ) ,
6047- values_ptr
6048- ]
6049- ) ;
6050-
6051- ctx. stack_pop ( n. as_usize ( ) ) ;
6052- let stack_ret = ctx. stack_push ( Type :: CArray ) ;
6053- asm. mov ( stack_ret, new_ary) ;
6054- }
6055- }
60566056
60576057 // Points to the receiver operand on the stack unless a captured environment is used
60586058 let recv = match captured_opnd {
0 commit comments