Skip to content

Commit 9112dae

Browse files
authored
gh-130706: Add a fast path to _Py_Dealloc() for non-GC objects. (gh-158645)
1 parent fc3cd8e commit 9112dae

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add a fast path to ``_Py_Dealloc()`` for non-GC objects. Patch by Donghee
2+
Na.

‎Objects/object.c‎

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3306,8 +3306,8 @@ next" object in the chain to 0. This can easily lead to stack overflows.
33063306
To avoid that, if the C stack is nearing its limit, instead of calling
33073307
dealloc on the object, it is added to a queue to be freed later when the
33083308
stack is shallower */
3309-
void
3310-
_Py_Dealloc(PyObject *op)
3309+
static Py_NO_INLINE void
3310+
py_dealloc(PyObject *op)
33113311
{
33123312
PyTypeObject *type = Py_TYPE(op);
33133313
unsigned long gc_flag = type->tp_flags & Py_TPFLAGS_HAVE_GC;
@@ -3372,6 +3372,28 @@ _Py_Dealloc(PyObject *op)
33723372
}
33733373
}
33743374

3375+
/*
3376+
* gh-130706: Keep the GC/reftracer path in the non-inlined py_dealloc().
3377+
* Inlining it makes the compiler save callee-saved registers at entry,
3378+
* so the non-GC objects path would have unnecessary register spills.
3379+
*/
3380+
void
3381+
_Py_Dealloc(PyObject *op)
3382+
{
3383+
#if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS)
3384+
// gh-130706: Avoid unnecessary register spills for non-GC objects.
3385+
PyTypeObject *type = Py_TYPE(op);
3386+
if (_PyRuntime.ref_tracer.tracer_func == NULL
3387+
&& !(type->tp_flags & Py_TPFLAGS_HAVE_GC))
3388+
{
3389+
type->tp_dealloc(op);
3390+
return;
3391+
}
3392+
#endif
3393+
// GC objects (trashcan), reftracer set, or debug builds.
3394+
py_dealloc(op);
3395+
}
3396+
33753397

33763398
PyObject **
33773399
PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)

0 commit comments

Comments
 (0)