diff --git a/Include/internal/pycore_freelist_state.h b/Include/internal/pycore_freelist_state.h index 46e2a82ea03456..266703a63b61f1 100644 --- a/Include/internal/pycore_freelist_state.h +++ b/Include/internal/pycore_freelist_state.h @@ -31,6 +31,7 @@ extern "C" { # define Py_pycfunctionobject_MAXFREELIST 16 # define Py_pycmethodobject_MAXFREELIST 16 # define Py_pymethodobjects_MAXFREELIST 20 +# define Py_tracebacks_MAXFREELIST 8 // A generic freelist of either PyObjects or other data structures. struct _Py_freelist { @@ -66,6 +67,7 @@ struct _Py_freelists { struct _Py_freelist pycfunctionobject; struct _Py_freelist pycmethodobject; struct _Py_freelist pymethodobjects; + struct _Py_freelist tracebacks; }; #ifdef __cplusplus diff --git a/Objects/object.c b/Objects/object.c index f8206e5d3eca32..757e54aa1d487d 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -956,6 +956,7 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization) clear_freelist(&freelists->pycfunctionobject, is_finalization, PyObject_GC_Del); clear_freelist(&freelists->pycmethodobject, is_finalization, PyObject_GC_Del); clear_freelist(&freelists->pymethodobjects, is_finalization, free_object); + clear_freelist(&freelists->tracebacks, is_finalization, PyObject_GC_Del); } /* diff --git a/Python/traceback.c b/Python/traceback.c index 7dc72d48274567..7e99dcb5a99249 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -4,6 +4,7 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_CallMethod() #include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH +#include "pycore_freelist.h" // _Py_FREELIST_POP() #include "pycore_frame.h" // PyFrameObject #include "pycore_interp.h" // PyInterpreterState.gc #include "pycore_interpframe.h" // _PyFrame_GetCode() @@ -79,15 +80,16 @@ tb_create_raw(PyTracebackObject *next, PyFrameObject *frame, int lasti, int lineno) { PyTracebackObject *tb; - if ((next != NULL && !PyTraceBack_Check(next)) || - frame == NULL || !PyFrame_Check(frame)) { - PyErr_BadInternalCall(); - return NULL; + assert(next == NULL || PyTraceBack_Check(next)); + assert(frame != NULL); + assert(PyFrame_Check(frame)); + tb = _Py_FREELIST_POP(PyTracebackObject, tracebacks); + if (tb == NULL) { + tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type); } - tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type); if (tb != NULL) { tb->tb_next = (PyTracebackObject*)Py_XNewRef(next); - tb->tb_frame = (PyFrameObject*)Py_XNewRef(frame); + tb->tb_frame = (PyFrameObject*)Py_NewRef(frame); tb->tb_lasti = lasti; tb->tb_lineno = lineno; PyObject_GC_Track(tb); @@ -237,7 +239,7 @@ tb_dealloc(PyObject *op) PyObject_GC_UnTrack(tb); Py_XDECREF(tb->tb_next); Py_XDECREF(tb->tb_frame); - PyObject_GC_Del(tb); + _Py_FREELIST_FREE(tracebacks, tb, PyObject_GC_Del); } static int