From 1b0feb4ada9b1ff604f9d3100254f9071a96713f Mon Sep 17 00:00:00 2001 From: Jeremy Hylton Date: Fri, 11 May 2001 14:48:41 +0000 Subject: [PATCH] Variant of SF patch 423181 For rich comparisons, use instance_getattr2() when possible to avoid the expense of setting an AttributeError. Also intern the name_op[] table and use the interned strings rather than creating a new string and interning it each time through. --- Objects/classobject.c | 72 ++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/Objects/classobject.c b/Objects/classobject.c index 67732ca2289..43d28902774 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -1651,38 +1651,68 @@ instance_ipow(PyObject *v, PyObject *w, PyObject *z) /* Map rich comparison operators to their __xx__ namesakes */ -static char *name_op[] = { - "__lt__", - "__le__", - "__eq__", - "__ne__", - "__gt__", - "__ge__", -}; +#define NAME_OPS 6 +static PyObject **name_op = NULL; + +static int +init_name_op() +{ + int i; + char *_name_op[] = { + "__lt__", + "__le__", + "__eq__", + "__ne__", + "__gt__", + "__ge__", + }; + + name_op = (PyObject **)malloc(sizeof(PyObject *) * NAME_OPS); + if (name_op == NULL) + return -1; + for (i = 0; i < NAME_OPS; ++i) { + name_op[i] = PyString_InternFromString(_name_op[i]); + if (name_op[i] == NULL) + return -1; + } + return 0; +} static PyObject * half_richcompare(PyObject *v, PyObject *w, int op) { - PyObject *name; PyObject *method; PyObject *args; PyObject *res; assert(PyInstance_Check(v)); - name = PyString_InternFromString(name_op[op]); - if (name == NULL) - return NULL; - - method = PyObject_GetAttr(v, name); - Py_DECREF(name); - if (method == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + if (name_op == NULL) { + if (init_name_op() < 0) return NULL; - PyErr_Clear(); - res = Py_NotImplemented; - Py_INCREF(res); - return res; + } + /* If the instance doesn't define an __getattr__ method, use + instance_getattr2 directly because it will not set an + exception on failure. */ + if (((PyInstanceObject *)v)->in_class->cl_getattr == NULL) { + method = instance_getattr2((PyInstanceObject *)v, + name_op[op]); + if (method == NULL) { + assert(!PyErr_Occurred()); + res = Py_NotImplemented; + Py_INCREF(res); + return res; + } + } else { + method = PyObject_GetAttr(v, name_op[op]); + if (method == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + return NULL; + PyErr_Clear(); + res = Py_NotImplemented; + Py_INCREF(res); + return res; + } } args = Py_BuildValue("(O)", w);