@@ -692,9 +692,9 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
692
692
}
693
693
uint n_args = n_args_n_kw & 0xff ;
694
694
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 ]);
696
696
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 );
698
698
699
699
// We need to create the following array of objects:
700
700
// 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_
705
705
uint args2_alloc ;
706
706
uint args2_len = 0 ;
707
707
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
+
708
722
// Try to get a hint for the size of the kw_dict
709
723
uint kw_dict_len = 0 ;
710
724
@@ -718,8 +732,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
718
732
719
733
// Extract the pos_seq sequence to the new args array.
720
734
// 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
723
737
724
738
// allocate memory for the new array of args
725
739
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_
733
747
// copy the fixed pos args
734
748
mp_seq_copy (args2 + args2_len , args , n_args , mp_obj_t );
735
749
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
-
758
750
} else {
759
- // generic iterator
751
+ // at least one star arg to unpack
760
752
761
753
// 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 );
763
755
args2 = mp_nonlocal_alloc (args2_alloc * sizeof (mp_obj_t ));
764
756
765
757
// copy the self
766
758
if (self != MP_OBJ_NULL ) {
767
759
args2 [args2_len ++ ] = self ;
768
760
}
769
761
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 ;
782
798
}
783
- args2 [args2_len ++ ] = item ;
784
799
}
785
800
}
786
801
787
802
// The size of the args2 array now is the number of positional args.
788
803
uint pos_args_len = args2_len ;
789
804
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
+
790
813
// Copy the kw args.
791
814
for (uint i = 0 ; i < n_kw ; i ++ ) {
792
815
mp_obj_t kw_key = args [n_args + i * 2 ];
0 commit comments