@@ -674,9 +674,9 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
674674 }
675675 uint n_args = n_args_n_kw & 0xff ;
676676
3ADC
uint n_kw = (n_args_n_kw >> 8 ) & 0xff ;
677- mp_obj_t pos_seq = args [n_args + 2 * n_kw ]; // may be MP_OBJ_NULL
677+ mp_uint_t star_args = mp_obj_get_int_truncated ( args [n_args + 2 * n_kw ]);
678678
679- DEBUG_OP_printf ("call method var (fun=%p, self=%p, n_args=%u, n_kw=%u, args=%p, seq=%p )\n" , fun , self , n_args , n_kw , args , pos_seq );
679+ DEBUG_OP_printf ("call method var (fun=%p, self=%p, n_args=%u, n_kw=%u, args=%p, map=%u )\n" , fun , self , n_args , n_kw , args , star_args );
680680
681681 // We need to create the following array of objects:
682682 // args[0 .. n_args] unpacked(pos_seq) args[n_args .. n_args + 2 * n_kw] unpacked(kw_dict)
@@ -687,6 +687,20 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
687687 uint args2_alloc ;
688688 uint args2_len = 0 ;
689689
690+ // Try to get a hint for unpacked * args length
691+ uint list_len = 0 ;
692+
693+ if (star_args != 0 ) {
694+ for (uint i = 0 ; i < n_args ; i ++ ) {
695+ if (star_args & (1 << i )) {
696+ mp_obj_t len = mp_obj_len_maybe (args [i ]);
697+ if (len != MP_OBJ_NULL ) {
698+ list_len += mp_obj_get_int (len );
699+ }
700+ }
701+ }
702+ }
703+
690704 // Try to get a hint for the size of the kw_dict
691705 uint kw_dict_len = 0 ;
692706
@@ -700,8 +714,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
700714
701715 // Extract the pos_seq sequence to the new args array.
702716 // Note that it can be arbitrary iterator.
703- if (pos_seq == MP_OBJ_NULL ) {
704- // no sequence
717+ if (star_args == 0 ) {
718+ // no star args to unpack
705719
706720 // allocate memory for the new array of args
707721 args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len );
@@ -715,60 +729,69 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
715729 // copy the fixed pos args
716730 mp_seq_copy (args2 + args2_len , args , n_args , mp_obj_t );
717731 args2_len += n_args ;
718-
719- } else if (mp_obj_is_type (pos_seq , & mp_type_tuple ) || mp_obj_is_type (pos_seq , & mp_type_list )) {
720- // optimise the case of a tuple and list
721-
722- // get the items
723- size_t len ;
724- mp_obj_t * items ;
725- mp_obj_get_array (pos_seq , & len , & items );
726-
727- // allocate memory for the new array of args
728- args2_alloc = 1 + n_args + len + 2 * (n_kw + kw_dict_len );
729- args2 = mp_nonlocal_alloc (args2_alloc * sizeof (mp_obj_t ));
730-
731- // copy the self
732- if (self != MP_OBJ_NULL ) {
733- args2 [args2_len ++ ] = self ;
734- }
735-
736- // copy the fixed and variable position args
737- mp_seq_cat (args2 + args2_len , args , n_args , items , len , mp_obj_t );
738- args2_len += n_args + len ;
739-
740732 } else {
741- // generic iterator
733+ // at least one star arg to unpack
742734
743735 // allocate memory for the new array of args
744- args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len ) + 3 ;
736+ args2_alloc = 1 + n_args + list_len + 2 * (n_kw + kw_dict_len );
745737 args2 = mp_nonlocal_alloc (args2_alloc * sizeof (mp_obj_t ));
746738
747739 // copy the self
748740 if (self != MP_OBJ_NULL ) {
749741 args2 [args2_len ++ ] = self ;
750742 }
751743
752- // copy the fixed position args
753- mp_seq_copy (args2 + args2_len , args , n_args , mp_obj_t );
754- args2_len += n_args ;
755-
756- // extract the variable position args from the iterator
757- mp_obj_iter_buf_t iter_buf ;
758- mp_obj_t iterable = mp_getiter (pos_seq , & iter_buf );
759- mp_obj_t item ;
760- while ((item = mp_iternext (iterable )) != MP_OBJ_STOP_ITERATION ) {
761- if (args2_len >= args2_alloc ) {
762- args2 = mp_nonlocal_realloc (args2 , args2_alloc * sizeof (mp_obj_t ), args2_alloc * 2 * sizeof (mp_obj_t ));
763- args2_alloc *= 2 ;
744+ for (uint i = 0 ; i < n_args ; i ++ ) {
745+ mp_obj_t arg = args [i ];
746+ if (star_args & (1 << i )) {
747+ // star arg
748+ if (mp_obj_is_type (arg , & mp_type_tuple ) || mp_obj_is_type (arg , & mp_type_list )) {
749+ // optimise the case of a tuple and list
750+
751+ // get the items
752+ size_t len ;
753+ mp_obj_t * items ;
754+ mp_obj_get_array (arg , & len , & items );
755+
756+ // copy the items
757+ assert (args2_len + len <= args2_alloc );
758+ mp_seq_copy (args2 + args2_len , items , len , mp_obj_t );
759+ args2_len += len ;
760+ } else {
761+ // generic iterator
762+
763+ // extract the variable position args from the iterator
764+ mp_obj_iter_buf_t iter_buf ;
765+ mp_obj_t iterable = mp_getiter (arg , & iter_buf );
766+ mp_obj_t item ;
767+ while ((item = mp_iternext (iterable )) != MP_OBJ_STOP_ITERATION ) {
768+ if (args2_len >= args2_alloc ) {
769+ args2 = mp_nonlocal_realloc (args2 , args2_alloc * sizeof (mp_obj_t ),
770+ args2_alloc * 2 * sizeof (mp_obj_t ));
771+ args2_alloc *= 2 ;
772+ }
773+ args2 [args2_len ++ ] = item ;
774+ }
775+ }
776+ } else {
777+ // normal argument
778+ assert (args2_len < args2_alloc );
779+ args2 [args2_len ++ ] = arg ;
764780 }
765- args2 [args2_len ++ ] = item ;
766781 }
767782 }
768783
769784 // The size of the args2 array now is the number of positional args.
770785 uint pos_args_len = args2_len ;
771786
787+ // ensure there is still enough room for kw args
788+ if (args2_len + 2 * (n_kw + kw_dict_len ) > args2_alloc ) {
789+ uint new_alloc = args2_len + 2 * (n_kw + kw_dict_len );
790+ args2 = mp_nonlocal_realloc (args2 , args2_alloc * sizeof (mp_obj_t ),
791+ new_alloc * sizeof (mp_obj_t ));
792+ args2_alloc = new_alloc ;
793+ }
794+
772795 // Copy the kw args.
773796 for (uint i = 0 ; i < n_kw ; i ++ ) {
774797 mp_obj_t kw_key = args [n_args + i * 2 ];
0 commit comments