@@ -382,18 +382,24 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
382382 return NULL ;
383383 }
384384
385- PyObject * * pto_args = _PyTuple_ITEMS (pto -> args );
386- Py_ssize_t pto_nargs = PyTuple_GET_SIZE (pto -> args );
387- Py_ssize_t pto_nkwds = PyDict_GET_SIZE (pto -> kw );
385+ PyObject * result = NULL ;
386+ PyObject * partial_function = Py_NewRef (pto -> fn );
387+ PyObject * partial_args = Py_NewRef (pto -> args );
388+ PyObject * partial_keywords = Py_NewRef (pto -> kw );
389+
390+ PyObject * * pto_args = _PyTuple_ITEMS (partial_args );
391+ Py_ssize_t pto_nargs = PyTuple_GET_SIZE (partial_args );
392+ Py_ssize_t pto_nkwds = PyDict_GET_SIZE (partial_keywords );
388393 Py_ssize_t nkwds = kwnames == NULL ? 0 : PyTuple_GET_SIZE (kwnames );
389394 Py_ssize_t nargskw = nargs + nkwds ;
390395
391396 /* Special cases */
392397 if (!pto_nkwds ) {
393398 /* Fast path if we're called without arguments */
394399 if (nargskw == 0 ) {
395- return _PyObject_VectorcallTstate (tstate , pto -> fn , pto_args ,
396- pto_nargs , NULL );
400+ result = _PyObject_VectorcallTstate (tstate , partial_function , pto_args ,
401+ pto_nargs , NULL );
402+ goto done ;
397403 }
398404
399405 /* Use PY_VECTORCALL_ARGUMENTS_OFFSET to prepend a single
@@ -402,10 +408,10 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
402408 PyObject * * newargs = (PyObject * * )args - 1 ;
403409 PyObject * tmp = newargs [0 ];
404410 newargs [0 ] = pto_args [0 ];
405- PyObject * ret = _PyObject_VectorcallTstate (tstate , pto -> fn , newargs ,
406- nargs + 1 , kwnames );
411+ result = _PyObject_VectorcallTstate (tstate , partial_function , newargs ,
412+ nargs + 1 , kwnames );
407413 newargs [0 ] = tmp ;
408- return ret ;
414+ goto done ;
409415 }
410416 }
411417
@@ -435,7 +441,8 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
435441 else {
436442 stack = PyMem_Malloc (init_stack_size * sizeof (PyObject * ));
437443 if (stack == NULL ) {
438- return PyErr_NoMemory ();
444+ PyErr_NoMemory ();
445+ goto done ;
439446 }
440447 }
441448
@@ -457,13 +464,13 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
457464 for (Py_ssize_t i = 0 ; i < nkwds ; ++ i ) {
458465 key = PyTuple_GET_ITEM (kwnames , i );
459466 val = args [nargs + i ];
460- int contains = PyDict_Contains (pto -> kw , key );
467+ int contains = PyDict_Contains (partial_keywords , key );
461468 if (contains < 0 ) {
462469 goto error ;
463470 }
464471 else if (contains == 1 ) {
465472 if (pto_kw_merged == NULL ) {
466- pto_kw_merged = PyDict_Copy (pto -> kw );
473+ pto_kw_merged = PyDict_Copy (partial_keywords );
467474 if (pto_kw_merged == NULL ) {
468475 goto error ;
469476 }
@@ -496,7 +503,7 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
496503 /* Copy pto_keywords with overlapping call keywords merged
497504 * Note, tail is already coppied. */
498505 Py_ssize_t pos = 0 , i = 0 ;
499- PyObject * keyword_dict = n_merges ? pto_kw_merged : pto -> kw ;
506+ PyObject * keyword_dict = n_merges ? pto_kw_merged : partial_keywords ;
500507 Py_BEGIN_CRITICAL_SECTION (keyword_dict );
501508 while (PyDict_Next (keyword_dict , & pos , & key , & val )) {
502509 assert (i < pto_nkwds );
@@ -518,7 +525,8 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
518525 if (stack != small_stack ) {
519526 PyMem_Free (stack );
520527 }
521- return PyErr_NoMemory ();
528+ PyErr_NoMemory ();
529+ goto done ;
522530 }
523531 stack = tmp_stack ;
524532 }
@@ -547,21 +555,22 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
547555 memcpy (stack + pto_nargs , args , nargs * sizeof (PyObject * ));
548556 }
549557
550- PyObject * ret = _PyObject_VectorcallTstate (tstate , pto -> fn , stack ,
551- tot_nargs , tot_kwnames );
552- if (stack != small_stack ) {
553- PyMem_Free (stack );
554- }
558+ result = _PyObject_VectorcallTstate (tstate , partial_function , stack ,
559+ tot_nargs , tot_kwnames );
555560 if (pto_nkwds ) {
556561 Py_DECREF (tot_kwnames );
557562 }
558- return ret ;
559563
560564 error :
561565 if (stack != small_stack ) {
562566 PyMem_Free (stack );
563567 }
564- return NULL ;
568+
569+ done :
570+ Py_DECREF (partial_function );
571+ Py_DECREF (partial_args );
572+ Py_DECREF (partial_keywords );
573+ return result ;
565574}
566575
567576/* Set pto->vectorcall depending on the parameters of the partial object */
0 commit comments