Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 67754e9

Browse files
committed
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.
1 parent 9930061 commit 67754e9

1 file changed

Lines changed: 35 additions & 31 deletions

File tree

Objects/object.c

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -825,32 +825,6 @@ static PyObject *
825825
do_richcmp(PyObject *v, PyObject *w, int op)
826826
{
827827
PyObject *res;
828-
cmpfunc f;
829-
830-
/* If the types are equal, don't bother with coercions etc.
831-
Instances are special-cased in try_3way_compare, since
832-
a result of 2 does *not* mean one value being greater
833-
than the other. */
834-
if (v->ob_type == w->ob_type
835-
&& (f = v->ob_type->tp_compare) != NULL
836-
&& !PyInstance_Check(v)) {
837-
int c;
838-
richcmpfunc f1;
839-
if ((f1 = RICHCOMPARE(v->ob_type)) != NULL) {
840-
/* If the type has richcmp, try it first.
841-
try_rich_compare would try it two-sided,
842-
which is not needed since we've a single
843-
type only. */
844-
res = (*f1)(v, w, op);
845-
if (res != Py_NotImplemented)
846-
return res;
847-
Py_DECREF(res);
848-
}
849-
c = (*f)(v, w);
850-
if (c < 0 && PyErr_Occurred())
851-
return NULL;
852-
return convert_3way_to_object(op, c);
853-
}
854828

855829
res = try_rich_compare(v, w, op);
856830
if (res != Py_NotImplemented)
@@ -862,8 +836,6 @@ do_richcmp(PyObject *v, PyObject *w, int op)
862836

863837
/* Return:
864838
NULL for exception;
865-
NotImplemented if this particular rich comparison is not implemented or
866-
undefined;
867839
some object not equal to NotImplemented if it is implemented
868840
(this latter object may not be a Boolean).
869841
*/
@@ -880,11 +852,12 @@ PyObject_RichCompare(PyObject *v, PyObject *w, int op)
880852
|| (v->ob_type->tp_as_sequence
881853
&& !PyString_Check(v)
882854
&& !PyTuple_Check(v)))) {
855+
883856
/* try to detect circular data structures */
884857
PyObject *token = check_recursion(v, w, op);
885-
886858
if (token == NULL) {
887859
res = NULL;
860+
goto Done;
888861
}
889862
else if (token == Py_None) {
890863
/* already comparing these objects with this operator.
@@ -904,10 +877,41 @@ PyObject_RichCompare(PyObject *v, PyObject *w, int op)
904877
res = do_richcmp(v, w, op);
905878
delete_token(token);
906879
}
880+
goto Done;
907881
}
908-
else {
909-
res = do_richcmp(v, w, op);
882+
883+
/* No nesting extremism.
884+
If the types are equal, and not old-style instances, try to
885+
get out cheap (don't bother with coercions etc.). */
886+
if (v->ob_type == w->ob_type && !PyInstance_Check(v)) {
887+
cmpfunc fcmp;
888+
richcmpfunc frich = RICHCOMPARE(v->ob_type);
889+
/* If the type has richcmp, try it first. try_rich_compare
890+
tries it two-sided, which is not needed since we've a
891+
single type only. */
892+
if (frich != NULL) {
893+
res = (*frich)(v, w, op);
894+
if (res != Py_NotImplemented)
895+
goto Done;
896+
Py_DECREF(res);
897+
}
898+
/* No richcmp, or this particular richmp not implemented.
899+
Try 3-way cmp. */
900+
fcmp = v->ob_type->tp_compare;
901+
if (fcmp != NULL) {
902+
int c = (*fcmp)(v, w);
903+
if (c < 0 && PyErr_Occurred()) {
904+
res = NULL;
905+
goto Done;
906+
}
907+
res = convert_3way_to_object(op, c);
908+
goto Done;
909+
}
910910
}
911+
912+
/* Fast path not taken, or couldn't deliver a useful result. */
913+
res = do_richcmp(v, w, op);
914+
Done:
911915
compare_nesting--;
912916
return res;
913917
}

0 commit comments

Comments
 (0)