cpython: aff41a6421c2 (original) (raw)
Mercurial > cpython
changeset 83937:aff41a6421c2
don't expand the operand to Py_XINCREF/XDECREF/CLEAR/DECREF multiple times (closes #17206) A patch from Illia Polosukhin. [#17206]
Benjamin Peterson benjamin@python.org | |
---|---|
date | Mon, 27 May 2013 14:46:14 -0700 |
parents | 39e0be9106c1 |
children | 789f8bbf0ae7 |
files | Include/object.h Misc/ACKS Misc/NEWS Modules/_testcapimodule.c |
diffstat | 4 files changed, 71 insertions(+), 14 deletions(-)[+] [-] Include/object.h 34 Misc/ACKS 1 Misc/NEWS 4 Modules/_testcapimodule.c 46 |
line wrap: on
line diff
--- a/Include/object.h +++ b/Include/object.h @@ -680,12 +680,6 @@ is not considered to be a reference to t 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) ( [](#l1.18) _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA [](#l1.19)
#define Py_DECREF(op) [](#l1.23) do { [](#l1.24)
PyObject *_py_decref_tmp = (PyObject *)(op); \[](#l1.25) if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \[](#l1.26)
--((PyObject*)(op))->ob_refcnt != 0) \[](#l1.27)
_Py_CHECK_REFCNT(op) \[](#l1.28)
--(_py_decref_tmp)->ob_refcnt != 0) \[](#l1.29)
_Py_CHECK_REFCNT(_py_decref_tmp) \[](#l1.30) else \[](#l1.31)
_Py_Dealloc((PyObject *)(op)); \[](#l1.32)
} while (0) /* Safely decref_Py_Dealloc(_py_decref_tmp); \[](#l1.33)
op
and setop
to NULL, especially useful in tp_clear @@ -811,16 +806,27 @@ PyAPI_FUNC(void) _Py_Dealloc(PyObject *) */
#define Py_CLEAR(op) [](#l1.39) do { [](#l1.40)
if (op) { \[](#l1.41)
PyObject *_py_tmp = (PyObject *)(op); \[](#l1.42)
PyObject *_py_tmp = (PyObject *)(op); \[](#l1.43)
} 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) [](#l1.53)if (_py_tmp != NULL) { \[](#l1.44) (op) = NULL; \[](#l1.45) Py_DECREF(_py_tmp); \[](#l1.46) } \[](#l1.47)
- do { [](#l1.54)
PyObject *_py_xincref_tmp = (PyObject *)(op); \[](#l1.55)
if (_py_xincref_tmp != NULL) \[](#l1.56)
Py_INCREF(_py_xincref_tmp); \[](#l1.57)
- } while (0)
+ +#define Py_XDECREF(op) [](#l1.60)
- do { [](#l1.61)
PyObject *_py_xdecref_tmp = (PyObject *)(op); \[](#l1.62)
if (_py_xdecref_tmp != NULL) \[](#l1.63)
Py_DECREF(_py_xdecref_tmp); \[](#l1.64)
- } while (0)
/* These are provided as conveniences to Python runtime embedders, so that
--- a/Misc/ACKS +++ b/Misc/ACKS @@ -983,6 +983,7 @@ Oleg Plakhotnyuk Remi Pointel Ariel Poliak Guilherme Polo +Illia Polosukhin Michael Pomraning Iustin Pop Claudiu Popa
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ What's New in Python 3.4.0 Alpha 1? Core and Builtins ----------------- +- Issue #17206: Py_CLEAR(), Py_DECREF(), Py_XINCREF() and Py_XDECREF() now
- Issue #17937: Try harder to collect cyclic garbage at shutdown.
- Issue #12370: Prevent class bodies from interfering with the class
--- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2468,6 +2468,48 @@ test_pytime_object_to_timespec(PyObject return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec); } +static PyObject * +_test_incref(PyObject *ob) +{
+} + +static PyObject * +test_xincref_doesnt_leak(PyObject *ob) +{
- PyObject *obj = PyLong_FromLong(0);
- Py_XINCREF(_test_incref(obj));
- Py_DECREF(obj);
- Py_DECREF(obj);
- Py_DECREF(obj);
- Py_RETURN_NONE;
+} + +static PyObject * +test_incref_doesnt_leak(PyObject *ob) +{
- PyObject *obj = PyLong_FromLong(0);
- Py_INCREF(_test_incref(obj));
- Py_DECREF(obj);
- Py_DECREF(obj);
- Py_DECREF(obj);
- Py_RETURN_NONE;
+} + +static PyObject * +test_xdecref_doesnt_leak(PyObject *ob) +{
+} + +static PyObject * +test_decref_doesnt_leak(PyObject *ob) +{
+} static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -2478,6 +2520,10 @@ static PyMethodDef TestMethods[] = { {"test_dict_iteration", (PyCFunction)test_dict_iteration,METH_NOARGS}, {"test_lazy_hash_inheritance", (PyCFunction)test_lazy_hash_inheritance,METH_NOARGS}, {"test_long_api", (PyCFunction)test_long_api, METH_NOARGS},
- {"test_xincref_doesnt_leak",(PyCFunction)test_xincref_doesnt_leak, METH_NOARGS},
- {"test_incref_doesnt_leak", (PyCFunction)test_incref_doesnt_leak, METH_NOARGS},
- {"test_xdecref_doesnt_leak",(PyCFunction)test_xdecref_doesnt_leak, METH_NOARGS},
- {"test_decref_doesnt_leak", (PyCFunction)test_decref_doesnt_leak, METH_NOARGS}, {"test_long_and_overflow", (PyCFunction)test_long_and_overflow, METH_NOARGS}, {"test_long_as_double", (PyCFunction)test_long_as_double,METH_NOARGS},