[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