]> granicus.if.org Git - python/commitdiff
bpo-30156: Remove property_descr_get() optimization (GH-9541)
authorVictor Stinner <vstinner@redhat.com>
Mon, 1 Oct 2018 10:03:22 +0000 (03:03 -0700)
committerGitHub <noreply@github.com>
Mon, 1 Oct 2018 10:03:22 +0000 (03:03 -0700)
property_descr_get() uses a "cached" tuple to optimize function
calls. But this tuple can be discovered in debug mode with
sys.getobjects(). Remove the optimization, it's not really worth it
and it causes 3 different crashes last years.

Microbenchmark:

./python -m perf timeit -v \
    -s "from collections import namedtuple; P = namedtuple('P', 'x y'); p = P(1, 2)" \
    --duplicate 1024 "p.x"

Result:

Mean +- std dev: [ref] 32.8 ns +- 0.8 ns -> [patch] 40.4 ns +- 1.3 ns: 1.23x slower (+23%)

Misc/NEWS.d/next/Core and Builtins/2018-09-24-17-51-15.bpo-30156.pH0j5j.rst [new file with mode: 0644]
Objects/descrobject.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-09-24-17-51-15.bpo-30156.pH0j5j.rst b/Misc/NEWS.d/next/Core and Builtins/2018-09-24-17-51-15.bpo-30156.pH0j5j.rst
new file mode 100644 (file)
index 0000000..7086ff4
--- /dev/null
@@ -0,0 +1,4 @@
+The C function ``property_descr_get()`` uses a "cached" tuple to optimize
+function calls. But this tuple can be discovered in debug mode with
+:func:`sys.getobjects()`. Remove the optimization, it's not really worth it
+and it causes 3 different crashes last years.
index b1bee904ec86bbafafd3e0d821722419c3f55503..82afa8c63f866001a3dbd2eb2fe8c82889c14827 100644 (file)
@@ -1331,42 +1331,19 @@ property_dealloc(PyObject *self)
 static PyObject *
 property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
 {
-    static PyObject * volatile cached_args = NULL;
-    PyObject *args;
-    PyObject *ret;
-    propertyobject *gs = (propertyobject *)self;
-
     if (obj == NULL || obj == Py_None) {
         Py_INCREF(self);
         return self;
     }
+
+    propertyobject *gs = (propertyobject *)self;
     if (gs->prop_get == NULL) {
         PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
         return NULL;
     }
-    args = cached_args;
-    cached_args = NULL;
-    if (!args) {
-        args = PyTuple_New(1);
-        if (!args)
-            return NULL;
-        _PyObject_GC_UNTRACK(args);
-    }
-    Py_INCREF(obj);
-    PyTuple_SET_ITEM(args, 0, obj);
-    ret = PyObject_Call(gs->prop_get, args, NULL);
-    if (cached_args == NULL && Py_REFCNT(args) == 1) {
-        assert(PyTuple_GET_SIZE(args) == 1);
-        assert(PyTuple_GET_ITEM(args, 0) == obj);
-        cached_args = args;
-        Py_DECREF(obj);
-    }
-    else {
-        assert(Py_REFCNT(args) >= 1);
-        _PyObject_GC_TRACK(args);
-        Py_DECREF(args);
-    }
-    return ret;
+
+    PyObject *args[1] = {obj};
+    return _PyObject_FastCall(gs->prop_get, args, 1);
 }
 
 static int