@@ -419,8 +419,13 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
419
419
PyObject * pto_kw_merged = NULL ; // pto_kw with duplicates merged (if any)
420
420
PyObject * tot_kwnames ;
421
421
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 ;
424
429
Py_ssize_t init_stack_size = tot_nargskw ;
425
430
if (pto_nkwds ) {
426
431
// If pto_nkwds, allocate additional space for temporary new keys
@@ -430,7 +435,6 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
430
435
stack = small_stack ;
431
436
}
432
437
else {
433
- /* NOTE, in theory size * elsize could overflow */
434
438
stack = PyMem_Malloc (init_stack_size * sizeof (PyObject * ));
435
439
if (stack == NULL ) {
436
440
return PyErr_NoMemory ();
@@ -482,36 +486,34 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
482
486
}
483
487
Py_ssize_t n_merges = nkwds - n_tail ;
484
488
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 );
487
491
for (Py_ssize_t i = 0 ; i < n_tail ; ++ i ) {
488
492
key = Py_NewRef (stack [tot_nargskw + i ]);
489
493
PyTuple_SET_ITEM (tot_kwnames , pto_nkwds + i , key );
490
494
}
491
495
492
- /* Copy pto_kw_merged to stack */
496
+ /* Copy pto_keywords with overlapping call keywords merged */
493
497
Py_ssize_t pos = 0 , i = 0 ;
494
498
while (PyDict_Next (n_merges ? pto_kw_merged : pto -> kw , & pos , & key , & val )) {
495
499
PyTuple_SET_ITEM (tot_kwnames , i , Py_NewRef (key ));
496
500
stack [tot_nargs + i ] = val ;
497
501
i ++ ;
498
502
}
503
+ Py_XDECREF (pto_kw_merged );
499
504
500
- /* Resize Stack */
501
- if (n_merges && stack != small_stack ) {
505
+ /* Resize Stack if the call has keywords */
506
+ if (nkwds && stack != small_stack ) {
502
507
tmp_stack = PyMem_Realloc (stack , (tot_nargskw - n_merges ) * sizeof (PyObject * ));
503
508
if (tmp_stack == NULL ) {
504
509
Py_DECREF (tot_kwnames );
505
- Py_XDECREF (pto_kw_merged );
506
510
if (stack != small_stack ) {
507
511
PyMem_Free (stack );
508
512
}
509
513
return PyErr_NoMemory ();
510
514
}
511
515
stack = tmp_stack ;
512
516
}
513
-
514
- Py_XDECREF (pto_kw_merged );
515
517
}
516
518
517
519
/* Copy Positionals to stack */
0 commit comments