@@ -419,8 +419,13 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
419419 PyObject * pto_kw_merged = NULL ; // pto_kw with duplicates merged (if any)
420420 PyObject * tot_kwnames ;
421421
422- /* Allocate Stack */
423- PyObject * * tmp_stack , * * stack , * small_stack [_PY_FASTCALL_SMALL_STACK ];
422+ /* Allocate Stack
423+ * Note, _PY_FASTCALL_SMALL_STACK is optimal for positional only
424+ * This case might have keyword arguments
425+ * furthermore, it might use extra stack space for temporary key storage
426+ * thus, double small_stack size is used, which is 10 * 8 = 80 bytes */
427+ PyObject * small_stack [_PY_FASTCALL_SMALL_STACK * 2 ];
428+ PyObject * * tmp_stack , * * stack ;
424429 Py_ssize_t init_stack_size = tot_nargskw ;
425430 if (pto_nkwds ) {
426431 // If pto_nkwds, allocate additional space for temporary new keys
@@ -430,7 +435,6 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
430435 stack = small_stack ;
431436 }
432437 else {
433- /* NOTE, in theory size * elsize could overflow */
434438 stack = PyMem_Malloc (init_stack_size * sizeof (PyObject * ));
435439 if (stack == NULL ) {
436440 return PyErr_NoMemory ();
@@ -482,36 +486,34 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
482486 }
483487 Py_ssize_t n_merges = nkwds - n_tail ;
484488
485- /* Create tot_kwnames */
486- tot_kwnames = PyTuple_New (pto_nkwds + n_tail );
489+ /* Create total kwnames */
490+ tot_kwnames = PyTuple_New (tot_nkwds - n_merges );
487491 for (Py_ssize_t i = 0 ; i < n_tail ; ++ i ) {
488492 key = Py_NewRef (stack [tot_nargskw + i ]);
489493 PyTuple_SET_ITEM (tot_kwnames , pto_nkwds + i , key );
490494 }
491495
492- /* Copy pto_kw_merged to stack */
496+ /* Copy pto_keywords with overlapping call keywords merged */
493497 Py_ssize_t pos = 0 , i = 0 ;
494498 while (PyDict_Next (n_merges ? pto_kw_merged : pto -> kw , & pos , & key , & val )) {
495499 PyTuple_SET_ITEM (tot_kwnames , i , Py_NewRef (key ));
496500 stack [tot_nargs + i ] = val ;
497501 i ++ ;
498502 }
503+ Py_XDECREF (pto_kw_merged );
499504
500- /* Resize Stack */
501- if (n_merges && stack != small_stack ) {
505+ /* Resize Stack if the call has keywords */
506+ if (nkwds && stack != small_stack ) {
502507 tmp_stack = PyMem_Realloc (stack , (tot_nargskw - n_merges ) * sizeof (PyObject * ));
503508 if (tmp_stack == NULL ) {
504509 Py_DECREF (tot_kwnames );
505- Py_XDECREF (pto_kw_merged );
506510 if (stack != small_stack ) {
507511 PyMem_Free (stack );
508512 }
509513 return PyErr_NoMemory ();
510514 }
511515 stack = tmp_stack ;
512516 }
513-
514- Py_XDECREF (pto_kw_merged );
515517 }
516518
517519 /* Copy Positionals to stack */
0 commit comments