[Python-checkins] CVS: python/dist/src/Objects object.c,2.131,2.132 typeobject.c,2.16,2.17

Martin v. L?wis loewis@users.sourceforge.net
Sat, 09 Jun 2001 00:34:07 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv9798/Objects

Modified Files:
	object.c typeobject.c 
Log Message:
Patch #424475: Speed-up tp_compare usage, by special-casing the common
case of objects with equal types which support tp_compare. Give
type objects a tp_compare function.
Also add c<0 tests before a few PyErr_Occurred tests.


Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.131
retrieving revision 2.132
diff -C2 -r2.131 -r2.132
*** object.c	2001/05/11 03:36:45	2.131
--- object.c	2001/06/09 07:34:05	2.132
***************
*** 478,491 ****
  		return (*w->ob_type->tp_compare)(v, w);
  
- 	/* If the types are equal, don't bother with coercions etc. */
- 	if (v->ob_type == w->ob_type) {
- 		if ((f = v->ob_type->tp_compare) == NULL)
- 			return 2;
- 		c = (*f)(v, w);
- 		if (PyErr_Occurred())
- 			return -2;
- 		return c < 0 ? -1 : c > 0 ? 1 : 0;
- 	}
- 
  	/* Try coercion; if it fails, give up */
  	c = PyNumber_CoerceEx(&v, &w);
--- 478,481 ----
***************
*** 500,504 ****
  		Py_DECREF(v);
  		Py_DECREF(w);
! 		if (PyErr_Occurred())
  			return -2;
  		return c < 0 ? -1 : c > 0 ? 1 : 0;
--- 490,494 ----
  		Py_DECREF(v);
  		Py_DECREF(w);
! 		if (c < 0 && PyErr_Occurred())
  			return -2;
  		return c < 0 ? -1 : c > 0 ? 1 : 0;
***************
*** 510,514 ****
  		Py_DECREF(v);
  		Py_DECREF(w);
! 		if (PyErr_Occurred())
  			return -2;
  		return c < 0 ? 1 : c > 0 ? -1 : 0; /* negated! */
--- 500,504 ----
  		Py_DECREF(v);
  		Py_DECREF(w);
! 		if (c < 0 && PyErr_Occurred())
  			return -2;
  		return c < 0 ? 1 : c > 0 ? -1 : 0; /* negated! */
***************
*** 591,594 ****
--- 581,586 ----
      0 if v == w;
      1 if v > w;
+    If the object implements a tp_compare function, it returns
+    whatever this function returns (whether with an exception or not).
  */
  static int
***************
*** 596,600 ****
--- 588,596 ----
  {
  	int c;
+ 	cmpfunc f;
  
+ 	if (v->ob_type == w->ob_type
+ 	    && (f = v->ob_type->tp_compare) != NULL)
+ 		return (*f)(v, w);
  	c = try_rich_to_3way_compare(v, w);
  	if (c < 2)
***************
*** 761,774 ****
  
  static PyObject *
! try_3way_to_rich_compare(PyObject *v, PyObject *w, int op)
  {
- 	int c;
  	PyObject *result;
- 
- 	c = try_3way_compare(v, w);
- 	if (c >= 2)
- 		c = default_3way_compare(v, w);
- 	if (c <= -2)
- 		return NULL;
  	switch (op) {
  	case Py_LT: c = c <  0; break;
--- 757,763 ----
  
  static PyObject *
! convert_3way_to_object(int op, int c)
  {
  	PyObject *result;
  	switch (op) {
  	case Py_LT: c = c <  0; break;
***************
*** 783,791 ****
--- 772,820 ----
  	return result;
  }
+ 	
  
  static PyObject *
+ try_3way_to_rich_compare(PyObject *v, PyObject *w, int op)
+ {
+ 	int c;
+ 
+ 	c = try_3way_compare(v, w);
+ 	if (c >= 2)
+ 		c = default_3way_compare(v, w);
+ 	if (c <= -2)
+ 		return NULL;
+ 	return convert_3way_to_object(op, c);
+ }
+ 
+ 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);

Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16
retrieving revision 2.17
diff -C2 -r2.16 -r2.17
*** typeobject.c	2000/09/01 23:29:27	2.16
--- typeobject.c	2001/06/09 07:34:05	2.17
***************
*** 24,27 ****
--- 24,37 ----
  }
  
+ static int
+ type_compare(PyObject *v, PyObject *w)
+ {
+ 	/* This is called with type objects only. So we
+ 	   can just compare the addresses. */
+ 	Py_uintptr_t vv = (Py_uintptr_t)v;
+ 	Py_uintptr_t ww = (Py_uintptr_t)w;
+ 	return (vv < ww) ? -1 : (vv > ww) ? 1 : 0;
+ }
+ 
  static PyObject *
  type_repr(PyTypeObject *v)
***************
*** 42,51 ****
  	(getattrfunc)type_getattr, /*tp_getattr*/
  	0,			/*tp_setattr*/
! 	0,			/*tp_compare*/
  	(reprfunc)type_repr,	/*tp_repr*/
  	0,			/*tp_as_number*/
  	0,			/*tp_as_sequence*/
  	0,			/*tp_as_mapping*/
! 	0,			/*tp_hash*/
  	0,			/*tp_call*/
  	0,			/*tp_str*/
--- 52,61 ----
  	(getattrfunc)type_getattr, /*tp_getattr*/
  	0,			/*tp_setattr*/
! 	type_compare,		/*tp_compare*/
  	(reprfunc)type_repr,	/*tp_repr*/
  	0,			/*tp_as_number*/
  	0,			/*tp_as_sequence*/
  	0,			/*tp_as_mapping*/
! 	_Py_HashPointer,	/*tp_hash*/
  	0,			/*tp_call*/
  	0,			/*tp_str*/