summaryrefslogtreecommitdiffstats
path: root/Include
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2013-05-27 21:46:14 (GMT)
committerBenjamin Peterson <benjamin@python.org>2013-05-27 21:46:14 (GMT)
commitda5eb5a31c31d0ba18a6b5f36be6ee40a01a2f2c (patch)
tree9e7d5bd957ee03a5b35800abcb7775e5761760b6 /Include
parente7b47dda645938469e764e1ca3a1fab746f7540f (diff)
downloadcpython-da5eb5a31c31d0ba18a6b5f36be6ee40a01a2f2c.zip
cpython-da5eb5a31c31d0ba18a6b5f36be6ee40a01a2f2c.tar.gz
cpython-da5eb5a31c31d0ba18a6b5f36be6ee40a01a2f2c.tar.bz2
don't expand the operand to Py_XINCREF/XDECREF/CLEAR/DECREF multiple times (closes #17206)
A patch from Illia Polosukhin.
Diffstat (limited to 'Include')
-rw-r--r--Include/object.h34
1 files changed, 20 insertions, 14 deletions
diff --git a/Include/object.h b/Include/object.h
index ad58450..221b4a2 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -680,12 +680,6 @@ is not considered to be a reference to the type object, to save
complications in the deallocation function. (This is actually a
decision that's up to the implementer of each new type so if you want,
you can count such references to the type object.)
-
-*** WARNING*** The Py_DECREF macro must have a side-effect-free argument
-since it may evaluate its argument multiple times. (The alternative
-would be to mace it a proper function or assign it to a global temporary
-variable first, both of which are slower; and in a multi-threaded
-environment the global variable trick is not safe.)
*/
/* First define a pile of simple helper macros, one set per special
@@ -764,15 +758,16 @@ PyAPI_FUNC(void) _Py_Dealloc(PyObject *);
#define Py_INCREF(op) ( \
_Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \
- ((PyObject*)(op))->ob_refcnt++)
+ ((PyObject *)(op))->ob_refcnt++)
#define Py_DECREF(op) \
do { \
+ PyObject *_py_decref_tmp = (PyObject *)(op); \
if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \
- --((PyObject*)(op))->ob_refcnt != 0) \
- _Py_CHECK_REFCNT(op) \
+ --(_py_decref_tmp)->ob_refcnt != 0) \
+ _Py_CHECK_REFCNT(_py_decref_tmp) \
else \
- _Py_Dealloc((PyObject *)(op)); \
+ _Py_Dealloc(_py_decref_tmp); \
} while (0)
/* Safely decref `op` and set `op` to NULL, especially useful in tp_clear
@@ -811,16 +806,27 @@ PyAPI_FUNC(void) _Py_Dealloc(PyObject *);
*/
#define Py_CLEAR(op) \
do { \
- if (op) { \
- PyObject *_py_tmp = (PyObject *)(op); \
+ PyObject *_py_tmp = (PyObject *)(op); \
+ if (_py_tmp != NULL) { \
(op) = NULL; \
Py_DECREF(_py_tmp); \
} \
} while (0)
/* Macros to use in case the object pointer may be NULL: */
-#define Py_XINCREF(op) do { if ((op) == NULL) ; else Py_INCREF(op); } while (0)
-#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
+#define Py_XINCREF(op) \
+ do { \
+ PyObject *_py_xincref_tmp = (PyObject *)(op); \
+ if (_py_xincref_tmp != NULL) \
+ Py_INCREF(_py_xincref_tmp); \
+ } while (0)
+
+#define Py_XDECREF(op) \
+ do { \
+ PyObject *_py_xdecref_tmp = (PyObject *)(op); \
+ if (_py_xdecref_tmp != NULL) \
+ Py_DECREF(_py_xdecref_tmp); \
+ } while (0)
/*
These are provided as conveniences to Python runtime embedders, so that