summaryrefslogtreecommitdiffstats
path: root/Objects/descrobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/descrobject.c')
-rw-r--r--Objects/descrobject.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 615f499..9ffbca7 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1313,7 +1313,7 @@ static PyMemberDef property_members[] = {
{"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
{"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
{"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
- {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), READONLY},
+ {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
{0}
};
@@ -1372,6 +1372,9 @@ 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) {
@@ -1382,7 +1385,29 @@ property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
return NULL;
}
- return PyObject_CallFunctionObjArgs(gs->prop_get, obj, 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);
+ 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;
}
static int
@@ -1584,6 +1609,14 @@ property_traverse(PyObject *self, visitproc visit, void *arg)
return 0;
}
+static int
+property_clear(PyObject *self)
+{
+ propertyobject *pp = (propertyobject *)self;
+ Py_CLEAR(pp->prop_doc);
+ return 0;
+}
+
PyTypeObject PyProperty_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"property", /* tp_name */
@@ -1609,7 +1642,7 @@ PyTypeObject PyProperty_Type = {
Py_TPFLAGS_BASETYPE, /* tp_flags */
property_doc, /* tp_doc */
property_traverse, /* tp_traverse */
- 0, /* tp_clear */
+ (inquiry)property_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */