[Python-checkins] python/dist/src/Objects classobject.c, 2.172, 2.173 object.c, 2.210, 2.211

arigo at users.sourceforge.net arigo at users.sourceforge.net
Tue Oct 28 07:05:50 EST 2003


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

Modified Files:
	classobject.c object.c 
Log Message:
Deleting cyclic object comparison.
SF patch 825639
http://mail.python.org/pipermail/python-dev/2003-October/039445.html



Index: classobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v
retrieving revision 2.172
retrieving revision 2.173
diff -C2 -d -r2.172 -r2.173
*** classobject.c	12 Oct 2003 19:09:37 -0000	2.172
--- classobject.c	28 Oct 2003 12:05:47 -0000	2.173
***************
*** 1971,1975 ****
  instance_call(PyObject *func, PyObject *arg, PyObject *kw)
  {
- 	PyThreadState *tstate = PyThreadState_GET();
  	PyObject *res, *call = PyObject_GetAttrString(func, "__call__");
  	if (call == NULL) {
--- 1971,1974 ----
***************
*** 1991,2002 ****
  	   This bounces between instance_call() and PyObject_Call() without
  	   ever hitting eval_frame() (which has the main recursion check). */
! 	if (tstate->recursion_depth++ > Py_GetRecursionLimit()) {
! 		PyErr_SetString(PyExc_RuntimeError,
! 				"maximum __call__ recursion depth exceeded");
  		res = NULL;
  	}
! 	else
  		res = PyObject_Call(call, arg, kw);
! 	tstate->recursion_depth--;
  	Py_DECREF(call);
  	return res;
--- 1990,2000 ----
  	   This bounces between instance_call() and PyObject_Call() without
  	   ever hitting eval_frame() (which has the main recursion check). */
! 	if (Py_EnterRecursiveCall(" in __call__")) {
  		res = NULL;
  	}
! 	else {
  		res = PyObject_Call(call, arg, kw);
! 		Py_LeaveRecursiveCall();
! 	}
  	Py_DECREF(call);
  	return res;

Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.210
retrieving revision 2.211
diff -C2 -d -r2.210 -r2.211
*** object.c	15 Aug 2003 13:07:46 -0000	2.210
--- object.c	28 Oct 2003 12:05:47 -0000	2.211
***************
*** 741,858 ****
  }
  
- /* compare_nesting is incremented before calling compare (for
-    some types) and decremented on exit.  If the count exceeds the
-    nesting limit, enable code to detect circular data structures.
- 
-    This is a tunable parameter that should only affect the performance
-    of comparisons, nothing else.  Setting it high makes comparing deeply
-    nested non-cyclical data structures faster, but makes comparing cyclical
-    data structures slower.
- */
- #define NESTING_LIMIT 20
- 
- static int compare_nesting = 0;
- 
- static PyObject*
- get_inprogress_dict(void)
- {
- 	static PyObject *key;
- 	PyObject *tstate_dict, *inprogress;
- 
- 	if (key == NULL) {
- 		key = PyString_InternFromString("cmp_state");
- 		if (key == NULL)
- 			return NULL;
- 	}
- 
- 	tstate_dict = PyThreadState_GetDict();
- 	if (tstate_dict == NULL) {
- 		PyErr_BadInternalCall();
- 		return NULL;
- 	}
- 
- 	inprogress = PyDict_GetItem(tstate_dict, key);
- 	if (inprogress == NULL) {
- 		inprogress = PyDict_New();
- 		if (inprogress == NULL)
- 			return NULL;
- 		if (PyDict_SetItem(tstate_dict, key, inprogress) == -1) {
- 		    Py_DECREF(inprogress);
- 		    return NULL;
- 		}
- 		Py_DECREF(inprogress);
- 	}
- 
- 	return inprogress;
- }
- 
- /* If the comparison "v op w" is already in progress in this thread, returns
-  * a borrowed reference to Py_None (the caller must not decref).
-  * If it's not already in progress, returns "a token" which must eventually
-  * be passed to delete_token().  The caller must not decref this either
-  * (delete_token decrefs it).  The token must not survive beyond any point
-  * where v or w may die.
-  * If an error occurs (out-of-memory), returns NULL.
-  */
- static PyObject *
- check_recursion(PyObject *v, PyObject *w, int op)
- {
- 	PyObject *inprogress;
- 	PyObject *token;
- 	Py_uintptr_t iv = (Py_uintptr_t)v;
- 	Py_uintptr_t iw = (Py_uintptr_t)w;
- 	PyObject *x, *y, *z;
- 
- 	inprogress = get_inprogress_dict();
- 	if (inprogress == NULL)
- 		return NULL;
- 
- 	token = PyTuple_New(3);
- 	if (token == NULL)
- 		return NULL;
- 
- 	if (iv <= iw) {
- 		PyTuple_SET_ITEM(token, 0, x = PyLong_FromVoidPtr((void *)v));
- 		PyTuple_SET_ITEM(token, 1, y = PyLong_FromVoidPtr((void *)w));
- 		if (op >= 0)
- 			op = swapped_op[op];
- 	} else {
- 		PyTuple_SET_ITEM(token, 0, x = PyLong_FromVoidPtr((void *)w));
- 		PyTuple_SET_ITEM(token, 1, y = PyLong_FromVoidPtr((void *)v));
- 	}
- 	PyTuple_SET_ITEM(token, 2, z = PyInt_FromLong((long)op));
- 	if (x == NULL || y == NULL || z == NULL) {
- 		Py_DECREF(token);
- 		return NULL;
- 	}
- 
- 	if (PyDict_GetItem(inprogress, token) != NULL) {
- 		Py_DECREF(token);
- 		return Py_None; /* Without INCREF! */
- 	}
- 
- 	if (PyDict_SetItem(inprogress, token, token) < 0) {
- 		Py_DECREF(token);
- 		return NULL;
- 	}
- 
- 	return token;
- }
- 
- static void
- delete_token(PyObject *token)
- {
- 	PyObject *inprogress;
- 
- 	if (token == NULL || token == Py_None)
- 		return;
- 	inprogress = get_inprogress_dict();
- 	if (inprogress == NULL)
- 		PyErr_Clear();
- 	else
- 		PyDict_DelItem(inprogress, token);
- 	Py_DECREF(token);
- }
- 
  /* Compare v to w.  Return
     -1 if v <  w or exception (PyErr_Occurred() true in latter case).
--- 741,744 ----
***************
*** 868,877 ****
  	int result;
  
- #if defined(USE_STACKCHECK)
- 	if (PyOS_CheckStack()) {
- 		PyErr_SetString(PyExc_MemoryError, "Stack overflow");
- 		return -1;
- 	}
- #endif
  	if (v == NULL || w == NULL) {
  		PyErr_BadInternalCall();
--- 754,757 ----
***************
*** 881,909 ****
  		return 0;
  	vtp = v->ob_type;
! 	compare_nesting++;
! 	if (compare_nesting > NESTING_LIMIT &&
! 	    (vtp->tp_as_mapping || vtp->tp_as_sequence) &&
! 	    !PyString_CheckExact(v) &&
! 	    !PyTuple_CheckExact(v)) {
! 		/* try to detect circular data structures */
! 		PyObject *token = check_recursion(v, w, -1);
! 
! 		if (token == NULL) {
! 			result = -1;
! 		}
! 		else if (token == Py_None) {
! 			/* already comparing these objects.  assume
! 			   they're equal until shown otherwise */
!                         result = 0;
! 		}
! 		else {
! 			result = do_cmp(v, w);
! 			delete_token(token);
! 		}
! 	}
! 	else {
! 		result = do_cmp(v, w);
! 	}
! 	compare_nesting--;
  	return result < 0 ? -1 : result;
  }
--- 761,768 ----
  		return 0;
  	vtp = v->ob_type;
! 	if (Py_EnterRecursiveCall(" in cmp"))
! 		return -1;
! 	result = do_cmp(v, w);
! 	Py_LeaveRecursiveCall();
  	return result < 0 ? -1 : result;
  }
***************
*** 976,1014 ****
  
  	assert(Py_LT <= op && op <= Py_GE);
  
! 	compare_nesting++;
! 	if (compare_nesting > NESTING_LIMIT &&
! 	    (v->ob_type->tp_as_mapping || v->ob_type->tp_as_sequence) &&
! 	    !PyString_CheckExact(v) &&
! 	    !PyTuple_CheckExact(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.
! 			   assume they're equal until shown otherwise */
! 			if (op == Py_EQ)
! 				res = Py_True;
! 			else if (op == Py_NE)
! 				res = Py_False;
! 			else {
! 				PyErr_SetString(PyExc_ValueError,
! 					"can't order recursive values");
! 				res = NULL;
! 			}
! 			Py_XINCREF(res);
! 		}
! 		else {
! 			res = do_richcmp(v, w, op);
! 			delete_token(token);
! 		}
! 		goto Done;
! 	}
! 
! 	/* 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)) {
--- 835,842 ----
  
  	assert(Py_LT <= op && op <= Py_GE);
+ 	if (Py_EnterRecursiveCall(" in cmp"))
+ 		return NULL;
  
! 	/* 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)) {
***************
*** 1042,1046 ****
  	res = do_richcmp(v, w, op);
  Done:
! 	compare_nesting--;
  	return res;
  }
--- 870,874 ----
  	res = do_richcmp(v, w, op);
  Done:
! 	Py_LeaveRecursiveCall();
  	return res;
  }





More information about the Python-checkins mailing list