@@ -692,9 +692,9 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
692692 }
693693 uint n_args = n_args_n_kw & 0xff ;
694694 uint n_kw = (n_args_n_kw >> 8 ) & 0xff ;
695- mp_obj_t pos_seq = args [n_args + 2 * n_kw ]; // may be MP_OBJ_NULL
695+ mp_uint_t star_args = mp_obj_get_int_truncated ( args [n_args + 2 * n_kw ]);
696696
697- 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 );
697+ 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 );
698698
699699 // We need to create the following array of objects:
700700 // args[0 .. n_args] unpacked(pos_seq) args[n_args .. n_args + 2 * n_kw] unpacked(kw_dict)
@@ -705,6 +705,20 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
705705 uint args2_alloc ;
706706 uint args2_len = 0 ;
707707
708+ // Try to get a hint for unpacked * args length
709+ uint list_len = 0 ;
710+
711+ if (star_args != 0 ) {
712+ for (uint i = 0 ; i < n_args ; i ++ ) {
713+ if (star_args & (1 << i )) {
714+ mp_obj_t len = mp_obj_len_maybe (args [i ]);
715+ if (len != MP_OBJ_NULL ) {
716+ list_len += mp_obj_get_int (len );
717+ }
718+ }
719+ }
720+ }
721+
708722 // Try to get a hint for the size of the kw_dict
709723 uint kw_dict_len = 0 ;
710724
@@ -718,8 +732,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
718732
719733 // Extract the pos_seq sequence to the new args array.
720734 <
9B60
td data-grid-cell-id="diff-eca4e26b5e481a060f702d7f8e7bc9e704e388f55415fce4273c9ad7f61b50fc-720-734-2" data-line-anchor="diff-eca4e26b5e481a060f702d7f8e7bc9e704e388f55415fce4273c9ad7f61b50fcR734" data-selected="false" role="gridcell" style="background-color:var(--bgColor-default);padding-right:24px" tabindex="-1" valign="top" class="focusable-grid-cell diff-text-cell right-side-diff-cell left-side"> // Note that it can be arbitrary iterator.
721- if (pos_seq == MP_OBJ_NULL ) {
722- // no sequence
735+ if (star_args == 0 ) {
736+ // no star args to unpack
723737
724738 // allocate memory for the new array of args
725739 args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len );
@@ -733,60 +747,69 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
733747 // copy the fixed pos args
734748 mp_seq_copy (args2 + args2_len , args , n_args , mp_obj_t );
735749 args2_len += n_args ;
736-
737- } else if (mp_obj_is_type (pos_seq , & mp_type_tuple ) || mp_obj_is_type (pos_seq , & mp_type_list )) {
738- // optimise the case of a tuple and list
739-
740- // get the items
741- size_t len ;
742- mp_obj_t * items ;
743- mp_obj_get_array (pos_seq , & len , & items );
744-
745- // allocate memory for the new array of args
746- args2_alloc = 1 + n_args + len + 2 * (n_kw + kw_dict_len );
747- args2 = mp_nonlocal_alloc (args2_alloc * sizeof (mp_obj_t ));
748-
749- // copy the self
750- if (self != MP_OBJ_NULL ) {
751- args2 [args2_len ++ ] = self ;
752- }
753-
754- // copy the fixed and variable position args
755- mp_seq_cat (args2 + args2_len , args , n_args , items , len , mp_obj_t );
756- args2_len += n_args + len ;
757-
758750 } else {
759- // generic iterator
751+ // at least one star arg to unpack
760752
761753 // allocate memory for the new array of args
762- args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len ) + 3 ;
754+ args2_alloc = 1 + n_args + list_len + 2 * (n_kw + kw_dict_len );
763755 args2 = mp_nonlocal_alloc (args2_alloc * sizeof (mp_obj_t ));
764756
765757 // copy the self
766758 if (self != MP_OBJ_NULL ) {
767759 args2 [args2_len ++ ] = self ;
768760 }
769761
770- // copy the fixed position args
771- mp_seq_copy (args2 + args2_len , args , n_args , mp_obj_t );
772- args2_len += n_args ;
773-
774- // extract the variable position args from the iterator
775- mp_obj_iter_buf_t iter_buf ;
776- mp_obj_t iterable = mp_getiter (pos_seq , & iter_buf );
777- mp_obj_t item ;
778- while ((item = mp_iternext (iterable )) != MP_OBJ_STOP_ITERATION ) {
779- if (args2_len >= args2_alloc ) {
780- args2 = mp_nonlocal_realloc (args2 , args2_alloc * sizeof (mp_obj_t ), args2_alloc * 2 * sizeof (mp_obj_t ));
781- args2_alloc *= 2 ;
762+ for (uint i = 0 ; i < n_args ; i ++ ) {
763+ mp_obj_t arg = args [i ];
764+ if (star_args & (1 << i )) {
765+ // star arg
766+ if (mp_obj_is_type (arg , & mp_type_tuple ) || mp_obj_is_type (arg , & mp_type_list )) {
767+ // optimise the case of a tuple and list
768+
769+ // get the items
770+ size_t len ;
771+ mp_obj_t * items ;
772+ mp_obj_get_array (arg , & len , & items );
773+
774+ // copy the items
775+ assert (args2_len + len <= args2_alloc );
776+ mp_seq_copy (args2 + args2_len , items , len , mp_obj_t );
777+ args2_len += len ;
778+ } else {
779+ // generic iterator
780+
781+ // extract the variable position args from the iterator
782+ mp_obj_iter_buf_t iter_buf ;
783+ mp_obj_t iterable = mp_getiter (arg , & iter_buf );
784+ mp_obj_t item ;
785+ while ((item = mp_iternext (iterable )) != MP_OBJ_STOP_ITERATION ) {
786+ if (args2_len >= args2_alloc ) {
787+ args2 = mp_nonlocal_realloc (args2 , args2_alloc * sizeof (mp_obj_t ),
788+ args2_alloc * 2 * sizeof (mp_obj_t ));
789+ args2_alloc *= 2 ;
790+ }
791+ args2 [args2_len ++ ] = item ;
792+ }
793+ }
794+ } else {
795+ // normal argument
796+ assert (args2_len < args2_alloc );
797+ args2 [args2_len ++ ] = arg ;
782798 }
783- args2 [args2_len ++ ] = item ;
784799 }
785800 }
786801
787802 // The size of the args2 array now is the number of positional args.
788803 uint pos_args_len = args2_len ;
789804
805+ // ensure there is still enough room for kw args
806+ if (args2_len + 2 * (n_kw + kw_dict_len ) > args2_alloc ) {
807+ uint new_alloc = args2_len + 2 * (n_kw + kw_dict_len );
808+ args2 = mp_nonlocal_realloc (args2 , args2_alloc * sizeof (mp_obj_t ),
809+ new_alloc * sizeof (mp_obj_t ));
810+ args2_alloc = new_alloc ;
811+ }
812+
790813 // Copy the kw args.
791814 for (uint i = 0 ; i < n_kw ; i ++ ) {
792815 mp_obj_t kw_key = args [n_args + i * 2 ];
0 commit comments