void *PyMem_Malloc(size_t nbytes){ return PyMem_MALLOC(nbytes);} void *PyMem_Realloc(void *p, size_t nbytes){ return PyMem_REALLOC(p, nbytes);} voidPyMem_Free(void *p){ PyMem_FREE(p);} /* These methods are used to control infinite recursion in repr, str, print, etc. Container objects that may recursively contain themselves, e.g. builtin dictionaries and lists, should used Py_ReprEnter() and Py_ReprLeave() to avoid infinite recursion. Py_ReprEnter() returns 0 the first time it is called for a particular object and 1 every time thereafter. It returns -1 if an exception occurred. Py_ReprLeave() has no return value. See dictobject.c and listobject.c for examples of use.*/ #define KEY "Py_Repr" intPy_ReprEnter(PyObject *obj){ PyObject *dict; PyObject *list; Py_ssize_t i; dict = PyThreadState_GetDict(); if (dict == NULL) return 0; list = PyDict_GetItemString(dict, KEY); if (list == NULL) { list = PyList_New(0); if (list == NULL) return -1; if (PyDict_SetItemString(dict, KEY, list) < 0) return -1; Py_DECREF(list); } i = PyList_GET_SIZE(list); while (--i >= 0) { if (PyList_GET_ITEM(list, i) == obj) return 1; } PyList_Append(list, obj); return 0;} voidPy_ReprLeave(PyObject *obj){ PyObject *dict; PyObject *list; Py_ssize_t i; dict = PyThreadState_GetDict(); if (dict == NULL) return; list = PyDict_GetItemString(dict, KEY); if (list == NULL || !PyList_Check(list)) return; i = PyList_GET_SIZE(list); /* Count backwards because we always expect obj to be list[-1] */ while (--i >= 0) { if (PyList_GET_ITEM(list, i) == obj) { PyList_SetSlice(list, i, i + 1, NULL); break; } }} /* Trashcan support. */ /* Current call-stack depth of tp_dealloc calls. */int _PyTrash_delete_nesting = 0; /* List of objects that still need to be cleaned up, singly linked via their * gc headers' gc_prev pointers. */PyObject *_PyTrash_delete_later = NULL; /* Add op to the _PyTrash_delete_later list. Called when the current * call-stack depth gets large. op must be a currently untracked gc'ed * object, with refcount 0. Py_DECREF must already have been called on it. */void_PyTrash_deposit_object(PyObject *op){ assert(PyObject_IS_GC(op)); assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED); assert(op->ob_refcnt == 0); _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *)_PyTrash_delete_later; _PyTrash_delete_later = op;} /* Dealloccate all the objects in the _PyTrash_delete_later list. Called when * the call-stack unwinds again. */void_PyTrash_destroy_chain(void){ while (_PyTrash_delete_later) { PyObject *op = _PyTrash_delete_later; destructor dealloc = op->ob_type->tp_dealloc; _PyTrash_delete_later = (PyObject*) _Py_AS_GC(op)->gc.gc_prev; /* Call the deallocator directly. This used to try to * fool Py_DECREF into calling it indirectly, but * Py_DECREF was already called on this object, and in * assorted non-release builds calling Py_DECREF again ends * up distorting allocation statistics. */ assert(op->ob_refcnt == 0); ++_PyTrash_delete_nesting; (*dealloc)(op); --_PyTrash_delete_nesting; }} #ifdef __cplusplus}#endif Lines 2001–2139 of 2139. Previous lines
void * PyMem_Malloc(size_t nbytes) { return PyMem_MALLOC(nbytes); } void * PyMem_Realloc(void *p, size_t nbytes) { return PyMem_REALLOC(p, nbytes); } void PyMem_Free(void *p) { PyMem_FREE(p); } /* These methods are used to control infinite recursion in repr, str, print, etc. Container objects that may recursively contain themselves, e.g. builtin dictionaries and lists, should used Py_ReprEnter() and Py_ReprLeave() to avoid infinite recursion. Py_ReprEnter() returns 0 the first time it is called for a particular object and 1 every time thereafter. It returns -1 if an exception occurred. Py_ReprLeave() has no return value. See dictobject.c and listobject.c for examples of use. */ #define KEY "Py_Repr" int Py_ReprEnter(PyObject *obj) { PyObject *dict; PyObject *list; Py_ssize_t i; dict = PyThreadState_GetDict(); if (dict == NULL) return 0; list = PyDict_GetItemString(dict, KEY); if (list == NULL) { list = PyList_New(0); if (list == NULL) return -1; if (PyDict_SetItemString(dict, KEY, list) < 0) return -1; Py_DECREF(list); } i = PyList_GET_SIZE(list); while (--i >= 0) { if (PyList_GET_ITEM(list, i) == obj) return 1; } PyList_Append(list, obj); return 0; } void Py_ReprLeave(PyObject *obj) { PyObject *dict; PyObject *list; Py_ssize_t i; dict = PyThreadState_GetDict(); if (dict == NULL) return; list = PyDict_GetItemString(dict, KEY); if (list == NULL || !PyList_Check(list)) return; i = PyList_GET_SIZE(list); /* Count backwards because we always expect obj to be list[-1] */ while (--i >= 0) { if (PyList_GET_ITEM(list, i) == obj) { PyList_SetSlice(list, i, i + 1, NULL); break; } } } /* Trashcan support. */ /* Current call-stack depth of tp_dealloc calls. */ int _PyTrash_delete_nesting = 0; /* List of objects that still need to be cleaned up, singly linked via their * gc headers' gc_prev pointers. */ PyObject *_PyTrash_delete_later = NULL; /* Add op to the _PyTrash_delete_later list. Called when the current * call-stack depth gets large. op must be a currently untracked gc'ed * object, with refcount 0. Py_DECREF must already have been called on it. */ void _PyTrash_deposit_object(PyObject *op) { assert(PyObject_IS_GC(op)); assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED); assert(op->ob_refcnt == 0); _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *)_PyTrash_delete_later; _PyTrash_delete_later = op; } /* Dealloccate all the objects in the _PyTrash_delete_later list. Called when * the call-stack unwinds again. */ void _PyTrash_destroy_chain(void) { while (_PyTrash_delete_later) { PyObject *op = _PyTrash_delete_later; destructor dealloc = op->ob_type->tp_dealloc; _PyTrash_delete_later = (PyObject*) _Py_AS_GC(op)->gc.gc_prev; /* Call the deallocator directly. This used to try to * fool Py_DECREF into calling it indirectly, but * Py_DECREF was already called on this object, and in * assorted non-release builds calling Py_DECREF again ends * up distorting allocation statistics. */ assert(op->ob_refcnt == 0); ++_PyTrash_delete_nesting; (*dealloc)(op); --_PyTrash_delete_nesting; } } #ifdef __cplusplus } #endif