https://github.com/python/cpython/commit/3feccd170e647b00141b61742a61ae3a0651d527
commit: 3feccd170e647b00141b61742a61ae3a0651d527
branch: main
author: Pieter Eendebak <[email protected]>
committer: eendebakpt <[email protected]>
date: 2026-11-06T10:42:50+01:00
summary:

gh-161242: Add a freelist for traceback objects (#161243)

* Add a freelist for traceback objects

A traceback object is created for every raised exception. Keep up to 8
of them on a per-thread freelist, and replace the argument check in
tb_create_raw() with asserts since all callers validate their arguments.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* Apply suggestion from @eendebakpt

* Apply suggestion from @eendebakpt

---------

Co-authored-by: Claude Fable 5.1 <[email protected]>

files:
M Include/internal/pycore_freelist_state.h
M Objects/object.c
M Python/traceback.c

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

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to