# HG changeset patch # User Franz Glasner # Date 1641494223 -3600 # Node ID 81238ea2dbe3ceb794a30629f1a4fa7610afd360 # Parent bb160a1e67d7a92e977c6a9b4a015ba8f180054e Implement and use more helper functions. Improve comments. diff -r bb160a1e67d7 -r 81238ea2dbe3 configmix/_py_helper.h --- a/configmix/_py_helper.h Thu Jan 06 18:50:09 2022 +0100 +++ b/configmix/_py_helper.h Thu Jan 06 19:37:03 2022 +0100 @@ -13,6 +13,9 @@ #if PY_VERSION_HEX < 0x030A0000 +/* + * Return a new owned reference to an object + */ static inline PyObject * Py_NewRef(PyObject *obj) @@ -22,6 +25,9 @@ } +/* + * Return a new owned reference to an object when the input can be NULL + */ static inline PyObject * Py_XNewRef(PyObject *obj) @@ -67,4 +73,74 @@ return (obj1 != obj2); } + +/** + * Copy from source to destination and make an owned reference. + * Also safely clear the destination before. + */ +static inline +void +py_assign(PyObject **dest, PyObject *src) +{ + Py_XDECREF(*dest); + *dest = Py_NewRef(src); +} + + +/** + * Copy from source to destination and make an owned reference. + * Also safely clear the destination before. The source object may be NULL. + */ +static inline +void +py_assign_x(PyObject **dest, PyObject *src) +{ + Py_XDECREF(*dest); + *dest = Py_XNewRef(src); +} + + +/* + * Transfer from a borrowed reference to an owned one and clear the source. + * Also safely clear the destination before. + */ +static inline +void +py_transfer_borrowed(PyObject **dest, PyObject **src) +{ + Py_XDECREF(*dest); + *dest = Py_NewRef(*src); + *src = NULL; +} + + +/* + * Transfer from a borrowed reference to an owned one and clear the source. + * Also safely clear the destination before. The source object may be NULL. + */ +static inline +void +py_transfer_x_borrowed(PyObject **dest, PyObject **src) +{ + Py_XDECREF(*dest); + *dest = Py_XNewRef(*src); + *src = NULL; +} + + +/* + * Transfer ownership from a owned reference to an owned one and clear the + * source. + * Also safely clear the destination before. + */ +static inline +void +py_transfer_owned(PyObject **dest, PyObject **src) +{ + Py_XDECREF(*dest); + *dest = *src; + *src = NULL; +} + + #endif diff -r bb160a1e67d7 -r 81238ea2dbe3 configmix/_speedups.c --- a/configmix/_speedups.c Thu Jan 06 18:50:09 2022 +0100 +++ b/configmix/_speedups.c Thu Jan 06 19:37:03 2022 +0100 @@ -569,8 +569,7 @@ if (tmp == NULL) { goto error; } - Py_DECREF(filters); - filters = tmp; tmp = NULL; + py_transfer_owned(&filters, &tmp); if (PyObject_Not(filters)) { py_clear_ref(&filters); @@ -586,6 +585,7 @@ goto error; } PyTuple_SetItem(res, 1, filters); /* steals */ + filters = NULL; return res; } @@ -601,8 +601,7 @@ if (tmp == NULL) { goto error; } - Py_DECREF(filters); - filters = tmp; tmp = NULL; + py_transfer_owned(&filters, &tmp); res = PyTuple_New(2); if (res == NULL) { @@ -820,10 +819,9 @@ goto error; } /* Unpack the result tuple */ - tmp2 = PyTuple_GetItem(tmp, 0); /* borrowed -- cannot fail */ - Py_DECREF(varname); - varname = Py_NewRef(tmp2); tmp2 = NULL; - /* borrowed -- cannot fail -- want own */ + /* borrowed -- cannot fail -- need ownership */ + varname = Py_NewRef(PyTuple_GetItem(tmp, 0)); + /* borrowed -- cannot fail -- want ownership */ filters = Py_NewRef(PyTuple_GetItem(tmp, 1)); py_clear_ref(&tmp); @@ -863,7 +861,7 @@ goto error; } /* unpack the result */ - /* borrowed -- but want own */ + /* borrowed -- cannot fail -- but want ownership */ varvalue = Py_NewRef(PyTuple_GetItem(tmp, 0)); cacheable = PyObject_IsTrue(PyTuple_GetItem(tmp, 1)); py_clear_ref(&tmp); @@ -953,7 +951,6 @@ Py_ssize_t s_len; Py_ssize_t start, rest, end; PyObject *tmp; - PyObject *tmp2; PyObject *result = NULL; PyObject *varname = NULL; PyObject *varvalue = NULL; @@ -1020,7 +1017,7 @@ py_clear_ref(&tmp); goto error; } - py_clear_ref(&tmp); + py_clear_ref(&tmp); } end = PyUnicode_Find(s, sstate->ENDTOK, start+2, s_len, 1); if (end == -2) { @@ -1046,10 +1043,9 @@ goto error; } /* Unpack the result tuple */ - tmp2 = PyTuple_GetItem(tmp, 0); /* borrowed -- cannot fail */ - Py_DECREF(varname); - varname = Py_NewRef(tmp2); tmp2 = NULL; - /* borrowed -- cannot fail -- need ownership */ + /* borrowed -- cannot fail -- need ownership */ + varname = Py_NewRef(PyTuple_GetItem(tmp, 0)); + /* borrowed -- cannot fail -- need ownership */ filters = Py_NewRef(PyTuple_GetItem(tmp, 1)); py_clear_ref(&tmp); @@ -1088,7 +1084,7 @@ goto error; } /* unpack the result */ - /* borrowed -- but want own */ + /* borrowed -- but want own */ varvalue = Py_NewRef(PyTuple_GetItem(tmp, 0)); cacheable = PyObject_IsTrue(PyTuple_GetItem(tmp, 1)); py_clear_ref(&tmp); @@ -1105,8 +1101,7 @@ if (tmp == NULL) { goto error; } - Py_DECREF(varvalue); - varvalue = tmp; tmp = NULL; + py_transfer_owned(&varvalue, &tmp); py_clear_ref(&filters); @@ -1117,8 +1112,7 @@ * the whole `s` is just one expansion */ if ((start == 0) && (rest == s_len)) { - Py_DECREF(result); - result = varvalue; varvalue = NULL; + py_transfer_owned(&result, &varvalue); goto success; /* break out early */ } @@ -1151,15 +1145,14 @@ py_clear_ref(&tmp); goto error; } - py_clear_ref(&tmp); + py_clear_ref(&tmp); } tmp = PyUnicode_Join(sstate->EMPTY_STR, result); if (tmp == NULL) { goto error; } - Py_DECREF(result); - result = tmp; tmp = NULL; + py_transfer_owned(&result, &tmp); success: if (use_cache) {