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.
This commit is contained in:
parent
6278799f8e
commit
1b0feb4ada
|
@ -1651,38 +1651,68 @@ instance_ipow(PyObject *v, PyObject *w, PyObject *z)
|
||||||
|
|
||||||
|
|
||||||
/* Map rich comparison operators to their __xx__ namesakes */
|
/* Map rich comparison operators to their __xx__ namesakes */
|
||||||
static char *name_op[] = {
|
#define NAME_OPS 6
|
||||||
"__lt__",
|
static PyObject **name_op = NULL;
|
||||||
"__le__",
|
|
||||||
"__eq__",
|
static int
|
||||||
"__ne__",
|
init_name_op()
|
||||||
"__gt__",
|
{
|
||||||
"__ge__",
|
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 *
|
static PyObject *
|
||||||
half_richcompare(PyObject *v, PyObject *w, int op)
|
half_richcompare(PyObject *v, PyObject *w, int op)
|
||||||
{
|
{
|
||||||
PyObject *name;
|
|
||||||
PyObject *method;
|
PyObject *method;
|
||||||
PyObject *args;
|
PyObject *args;
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
|
|
||||||
assert(PyInstance_Check(v));
|
assert(PyInstance_Check(v));
|
||||||
|
|
||||||
name = PyString_InternFromString(name_op[op]);
|
if (name_op == NULL) {
|
||||||
if (name == NULL)
|
if (init_name_op() < 0)
|
||||||
return NULL;
|
|
||||||
|
|
||||||
method = PyObject_GetAttr(v, name);
|
|
||||||
Py_DECREF(name);
|
|
||||||
if (method == NULL) {
|
|
||||||
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
PyErr_Clear();
|
}
|
||||||
res = Py_NotImplemented;
|
/* If the instance doesn't define an __getattr__ method, use
|
||||||
Py_INCREF(res);
|
instance_getattr2 directly because it will not set an
|
||||||
return res;
|
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);
|
args = Py_BuildValue("(O)", w);
|
||||||
|
|
Loading…
Reference in New Issue