@@ -701,9 +701,9 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
701701 }
702702 uint n_args = n_args_n_kw & 0xff ;
703703 uint n_kw = (n_args_n_kw >> 8 ) & 0xff ;
704- mp_obj_t pos_seq = args [n_args + 2 * n_kw ]; // may be MP_OBJ_NULL
704+ mp_uint_t star_args = mp_obj_get_int_truncated ( args [n_args + 2 * n_kw ]);
705705
706- 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 );
706+ 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 );
707707
708708 // We need to create the following array of objects:
709709 // args[0 .. n_args] unpacked(pos_seq) args[n_args .. n_args + 2 * n_kw] unpacked(kw_dict)
@@ -714,6 +714,20 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
714714 uint args2_alloc ;
715715 uint args2_len = 0 ;
716716
717+ // Try to get a hint for unpacked * args length
718+ uint list_len = 0 ;
719+
720+ if (star_args != 0 ) {
721+ for (uint i = 0 ; i < n_args ; i ++ ) {
722+ if (star_args & (1 << i )) {
723+ mp_obj_t len = mp_obj_len_maybe (args [i ]);
724+ if (len != MP_OBJ_NULL ) {
725+ list_len += mp_obj_get_int (len );
726+ }
727+ }
728+ }
729+ }
730+
717731 // Try to get a hint for the size of the kw_dict
718732 uint kw_dict_len = 0 ;
719733
@@ -727,8 +741,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
727741
728742 // Extract the pos_seq sequence to the new args array.
729743 // Note that it can be arbitrary iterator.
730- if (pos_seq == MP_OBJ_NULL ) {
731- // no sequence
744+ if (star_args == 0 ) {
745+ // no star args to unpack
732746
733747 // allocate memory for the new array of args
734748 args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len );
@@ -742,60 +756,69 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
742756 // copy the fixed pos args
743757 mp_seq_copy (args2 + args2_len , args , n_args , mp_obj_t );
744758 args2_len += n_args ;
745-
746- } else if (mp_obj_is_type (pos_seq , & mp_type_tuple ) || mp_obj_is_type (pos_seq , & mp_type_list )) {
747- // optimise the case of a tuple and list
748-
749- // get the items
750- size_t len ;
751- mp_obj_t * items ;
752- mp_obj_get_array (pos_seq , & len , & items );
753-
754- // allocate memory for the new array of args
755- args2_alloc = 1 + n_args + len + 2 * (n_kw + kw_dict_len );
756- args2 = mp_nonlocal_alloc (args2_alloc * sizeof (mp_obj_t ));
757-
758- // copy the self
759- if (self != MP_OBJ_NULL ) {
760- args2 [args2_len ++ ] = self ;
761- }
762-
763- // copy the fixed and variable position args
764- mp_seq_cat (args2 + args2_len , args , n_args , items , len , mp_obj_t );
765- args2_len += n_args + len ;
766-
767759 } else {
768- // generic iterator
760+ // at least one star arg to unpack
769761
770762 // allocate memory for the new array of args
771- args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len ) + 3 ;
763+ args2_alloc = 1 + n_args + list_len + 2 * (n_kw + kw_dict_len );
772764 args2 = mp_nonlocal_alloc (args2_alloc * sizeof (mp_obj_t ));
773765
774766 // copy the self
775767 if (self != MP_OBJ_NULL ) {
776768 args2 [args2_len ++ ] = self ;
777769 }
778770
779- // copy the fixed position args
780- mp_seq_copy (args2 + args2_len , args , n_args , mp_obj_t );
781- args2_len += n_args ;
782-
783- // extract the variable position args from the iterator
784- mp_obj_iter_buf_t iter_buf ;
785- mp_obj_t iterable = mp_getiter (pos_seq , & iter_buf );
786- mp_obj_t item ;
787- while ((item = mp_iternext (iterable )) != MP_OBJ_STOP_ITERATION ) {
788- if (args2_len >= args2_alloc ) {
789- args2 = mp_nonlocal_realloc (args2 , args2_alloc * sizeof (mp_obj_t ), args2_alloc * 2 * sizeof (mp_obj_t ));
790- args2_alloc *= 2 ;
771+ for (uint i = 0 ; i < n_args ; i ++ ) {
772+ mp_obj_t arg = args [i ];
773+ if (star_args & (1 << i )) {
774+ // star arg
775+ if (mp_obj_is_type (arg , & mp_type_tuple ) || mp_obj_is_type (arg , & mp_type_list )) {
776+ // optimise the case of a tuple and list
777+
778+ // get the items
779+ size_t len ;
780+ mp_obj_t * items ;
781+ mp_obj_get_array (arg , & len , & items );
782+
783+ // copy the items
784+ assert (args2_len + len <= args2_alloc );
785+ mp_seq_copy (args2 + args2_len , items , len , mp_obj_t );
786+ args2_len += len ;
787+ } else {
788+ // generic iterator
789+
790+ // extract the variable position args from the iterator
791+ mp_obj_iter_buf_t iter_buf ;
792+ mp_obj_t iterable = mp_getiter (arg , & iter_buf );
793+ mp_obj_t item ;
794+ while ((item = mp_iternext (iterable )) != MP_OBJ_STOP_ITERATION ) {
795+ if (args2_len >= args2_alloc ) {
796+ args2 = mp_nonlocal_realloc (args2 , args2_alloc * sizeof (mp_obj_t ),
797+ args2_alloc * 2 * sizeof (mp_obj_t ));
798+ args2_alloc *= 2 ;
799+ }
800+ args2 [args2_len ++ ] = item ;
801+ }
802+ }
803+ } else {
804+ // normal argument
805+ assert (args2_len < args2_alloc );
806+ args2 [args2_len ++ ] = arg ;
791807 }
792- args2 [args2_len ++ ] = item ;
793808 }
794809 }
795810
796811 // The size of the args2 array now is the number of positional args.
797812 uint pos_args_len = args2_len ;
798813
814+ // ensure there is still enough room for kw args
815+ if (args2_len + 2 * (n_kw + kw_dict_len ) > args2_alloc ) {
816+ uint new_alloc = args2_len + 2 * (n_kw + kw_dict_len );
817+ args2 = mp_nonlocal_realloc (args2 , args2_alloc * sizeof (mp_obj_t ),
818+ new_alloc * sizeof (mp_obj_t ));
819+ args2_alloc = new_alloc ;
820+ }
821+
799822 // Copy the kw args.
800823 for (uint i = 0 ; i < n_kw ; i ++ ) {
801824 mp_obj_t kw_key = args [n_args + i * 2 ];
0 commit comments