summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-11-04 07:29:31 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-11-04 07:29:31 (GMT)
commit67754e993ea681dcdd6d13e396411524922ba89a (patch)
tree7827ba2d331fe6d106b8f56bb32a011f4f7cf302
parent9930061ce28b1fc60d267ae3474c74a41e655cd5 (diff)
downloadcpython-67754e993ea681dcdd6d13e396411524922ba89a.zip
cpython-67754e993ea681dcdd6d13e396411524922ba89a.tar.gz
cpython-67754e993ea681dcdd6d13e396411524922ba89a.tar.bz2
Rehabilitated the fast-path richcmp code, and sped it up. It wasn't
helping for types that defined tp_richcmp but not tp_compare, although that's when it's most valuable, and strings moved into that category since the fast path was first introduced. Now it helps for same-type non-Instance objects that define rich or 3-way compares. For all the edits here, the rest just amounts to moving the fast path from do_richcmp into PyObject_RichCompare, saving a layer of function call (measurable on my box!). This loses when NESTING_LIMIT is exceeded, but I don't care about that (fast-paths are for normal cases, not pathologies). Also added a tasteful <wink> label to get out of PyObject_RichCompare, as the if/else nesting in this routine was getting incomprehensible.
-rw-r--r--Objects/object.c66
1 files changed, 35 insertions, 31 deletions
diff --git a/Objects/object.c b/Objects/object.c
index 7c6819d..07ca47c 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -825,32 +825,6 @@ static PyObject *
do_richcmp(PyObject *v, PyObject *w, int op)
{
PyObject *res;
- cmpfunc f;
-
- /* If the types are equal, don't bother with coercions etc.
- Instances are special-cased in try_3way_compare, since
- a result of 2 does *not* mean one value being greater
- than the other. */
- if (v->ob_type == w->ob_type
- && (f = v->ob_type->tp_compare) != NULL
- && !PyInstance_Check(v)) {
- int c;
- richcmpfunc f1;
- if ((f1 = RICHCOMPARE(v->ob_type)) != NULL) {
- /* If the type has richcmp, try it first.
- try_rich_compare would try it two-sided,
- which is not needed since we've a single
- type only. */
- res = (*f1)(v, w, op);
- if (res != Py_NotImplemented)
- return res;
- Py_DECREF(res);
- }
- c = (*f)(v, w);
- if (c < 0 && PyErr_Occurred())
- return NULL;
- return convert_3way_to_object(op, c);
- }
res = try_rich_compare(v, w, op);
if (res != Py_NotImplemented)
@@ -862,8 +836,6 @@ do_richcmp(PyObject *v, PyObject *w, int op)
/* Return:
NULL for exception;
- NotImplemented if this particular rich comparison is not implemented or
- undefined;
some object not equal to NotImplemented if it is implemented
(this latter object may not be a Boolean).
*/
@@ -880,11 +852,12 @@ PyObject_RichCompare(PyObject *v, PyObject *w, int op)
|| (v->ob_type->tp_as_sequence
&& !PyString_Check(v)
&& !PyTuple_Check(v)))) {
+
/* try to detect circular data structures */
PyObject *token = check_recursion(v, w, op);
-
if (token == NULL) {
res = NULL;
+ goto Done;
}
else if (token == Py_None) {
/* already comparing these objects with this operator.
@@ -904,10 +877,41 @@ PyObject_RichCompare(PyObject *v, PyObject *w, int op)
res = do_richcmp(v, w, op);
delete_token(token);
}
+ goto Done;
}
- else {
- res = do_richcmp(v, w, op);
+
+ /* No nesting extremism.
+ If the types are equal, and not old-style instances, try to
+ get out cheap (don't bother with coercions etc.). */
+ if (v->ob_type == w->ob_type && !PyInstance_Check(v)) {
+ cmpfunc fcmp;
+ richcmpfunc frich = RICHCOMPARE(v->ob_type);
+ /* If the type has richcmp, try it first. try_rich_compare
+ tries it two-sided, which is not needed since we've a
+ single type only. */
+ if (frich != NULL) {
+ res = (*frich)(v, w, op);
+ if (res != Py_NotImplemented)
+ goto Done;
+ Py_DECREF(res);
+ }
+ /* No richcmp, or this particular richmp not implemented.
+ Try 3-way cmp. */
+ fcmp = v->ob_type->tp_compare;
+ if (fcmp != NULL) {
+ int c = (*fcmp)(v, w);
+ if (c < 0 && PyErr_Occurred()) {
+ res = NULL;
+ goto Done;
+ }
+ res = convert_3way_to_object(op, c);
+ goto Done;
+ }
}
+
+ /* Fast path not taken, or couldn't deliver a useful result. */
+ res = do_richcmp(v, w, op);
+Done:
compare_nesting--;
return res;
}