]> granicus.if.org Git - python/commitdiff
Issue #24276: Fixed optimization of property descriptor getter.
authorSerhiy Storchaka <storchaka@gmail.com>
Sun, 24 May 2015 18:38:06 +0000 (21:38 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Sun, 24 May 2015 18:38:06 +0000 (21:38 +0300)
Misc/NEWS
Objects/descrobject.c

index ef2a0f0e874241cb0fbe14a8f1567e45b175d36e..88818b6579460da58fe328464d628dfc45e23fc4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ Release date: 2015-05-24
 Core and Builtins
 -----------------
 
+- Issue #24276: Fixed optimization of property descriptor getter.
+
 - Issue #24268: PEP 489: Multi-phase extension module initialization
 
 - Issue #23955: Add pyvenv.cfg option to suppress registry/environment
index 24b24e730da9b865bcb1fb1988c75c8aec7d8fb5..1a69b6b2c6a1d58cb46be23c0ef619b62fb9d050 100644 (file)
@@ -1372,7 +1372,8 @@ property_dealloc(PyObject *self)
 static PyObject *
 property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
 {
-    static PyObject *args = NULL;
+    static PyObject * volatile cached_args = NULL;
+    PyObject *args;
     PyObject *ret;
     propertyobject *gs = (propertyobject *)self;
 
@@ -1384,12 +1385,28 @@ property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
         PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
         return NULL;
     }
-    if (!args && !(args = PyTuple_New(1))) {
-        return NULL;
+    args = cached_args;
+    if (!args || Py_REFCNT(args) != 1) {
+        Py_CLEAR(cached_args);
+        if (!(cached_args = args = PyTuple_New(1)))
+            return NULL;
     }
+    Py_INCREF(args);
+    assert (Py_REFCNT(args) == 2);
+    Py_INCREF(obj);
     PyTuple_SET_ITEM(args, 0, obj);
     ret = PyObject_Call(gs->prop_get, args, NULL);
-    PyTuple_SET_ITEM(args, 0, NULL);
+    if (args == cached_args) {
+        if (Py_REFCNT(args) == 2) {
+            obj = PyTuple_GET_ITEM(args, 0);
+            PyTuple_SET_ITEM(args, 0, NULL);
+            Py_XDECREF(obj);
+        }
+        else {
+            Py_CLEAR(cached_args);
+        }
+    }
+    Py_DECREF(args);
     return ret;
 }