Skip to content

Commit d4d5bae

Browse files
authored
gh-111968: Refactor _PyXXX_Fini to integrate with _PyObject_ClearFreeLists (gh-114899)
1 parent 5643856 commit d4d5bae

20 files changed

+38
-107
lines changed

Diff for: Include/internal/pycore_context.h

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ extern PyTypeObject _PyContextTokenMissing_Type;
1414
/* runtime lifecycle */
1515

1616
PyStatus _PyContext_Init(PyInterpreterState *);
17-
void _PyContext_Fini(_PyFreeListState *);
1817

1918

2019
/* other API */

Diff for: Include/internal/pycore_floatobject.h

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ extern "C" {
1515

1616
extern void _PyFloat_InitState(PyInterpreterState *);
1717
extern PyStatus _PyFloat_InitTypes(PyInterpreterState *);
18-
extern void _PyFloat_Fini(_PyFreeListState *);
1918
extern void _PyFloat_FiniType(PyInterpreterState *);
2019

2120

Diff for: Include/internal/pycore_freelist.h

+10
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ typedef struct _Py_freelist_state {
125125
struct _Py_object_stack_state object_stacks;
126126
} _PyFreeListState;
127127

128+
extern void _PyObject_ClearFreeLists(_PyFreeListState *state, int is_finalization);
129+
extern void _PyTuple_ClearFreeList(_PyFreeListState *state, int is_finalization);
130+
extern void _PyFloat_ClearFreeList(_PyFreeListState *state, int is_finalization);
131+
extern void _PyList_ClearFreeList(_PyFreeListState *state, int is_finalization);
132+
extern void _PySlice_ClearFreeList(_PyFreeListState *state, int is_finalization);
133+
extern void _PyDict_ClearFreeList(_PyFreeListState *state, int is_finalization);
134+
extern void _PyAsyncGen_ClearFreeLists(_PyFreeListState *state, int is_finalization);
135+
extern void _PyContext_ClearFreeList(_PyFreeListState *state, int is_finalization);
136+
extern void _PyObjectStackChunk_ClearFreeList(_PyFreeListState *state, int is_finalization);
137+
128138
#ifdef __cplusplus
129139
}
130140
#endif

Diff for: Include/internal/pycore_gc.h

-8
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,6 @@ extern PyObject *_PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs);
279279

280280
// Functions to clear types free lists
281281
extern void _PyGC_ClearAllFreeLists(PyInterpreterState *interp);
282-
extern void _Py_ClearFreeLists(_PyFreeListState *state, int is_finalization);
283-
extern void _PyTuple_ClearFreeList(_PyFreeListState *state, int is_finalization);
284-
extern void _PyFloat_ClearFreeList(_PyFreeListState *state, int is_finalization);
285-
extern void _PyList_ClearFreeList(_PyFreeListState *state, int is_finalization);
286-
extern void _PySlice_ClearCache(_PyFreeListState *state);
287-
extern void _PyDict_ClearFreeList(_PyFreeListState *state, int is_finalization);
288-
extern void _PyAsyncGen_ClearFreeLists(_PyFreeListState *state, int is_finalization);
289-
extern void _PyContext_ClearFreeList(_PyFreeListState *state, int is_finalization);
290282
extern void _Py_ScheduleGC(PyInterpreterState *interp);
291283
extern void _Py_RunGC(PyThreadState *tstate);
292284

Diff for: Include/internal/pycore_genobject.h

-4
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ extern PyTypeObject _PyCoroWrapper_Type;
2626
extern PyTypeObject _PyAsyncGenWrappedValue_Type;
2727
extern PyTypeObject _PyAsyncGenAThrow_Type;
2828

29-
/* runtime lifecycle */
30-
31-
extern void _PyAsyncGen_Fini(_PyFreeListState *);
32-
3329
#ifdef __cplusplus
3430
}
3531
#endif

Diff for: Include/internal/pycore_list.h

-6
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@ extern "C" {
1313
extern PyObject* _PyList_Extend(PyListObject *, PyObject *);
1414
extern void _PyList_DebugMallocStats(FILE *out);
1515

16-
17-
/* runtime lifecycle */
18-
19-
extern void _PyList_Fini(_PyFreeListState *);
20-
21-
2216
#define _PyList_ITEMS(op) _Py_RVALUE(_PyList_CAST(op)->ob_item)
2317

2418
extern int

Diff for: Include/internal/pycore_object_stack.h

-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ _PyObjectStackChunk_New(void);
3434
extern void
3535
_PyObjectStackChunk_Free(_PyObjectStackChunk *);
3636

37-
extern void
38-
_PyObjectStackChunk_ClearFreeList(_PyFreeListState *state, int is_finalization);
39-
4037
// Push an item onto the stack. Return -1 on allocation failure, 0 on success.
4138
static inline int
4239
_PyObjectStack_Push(_PyObjectStack *stack, PyObject *obj)

Diff for: Include/internal/pycore_sliceobject.h

-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ extern "C" {
1111

1212
/* runtime lifecycle */
1313

14-
extern void _PySlice_Fini(_PyFreeListState *);
15-
1614
extern PyObject *
1715
_PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop);
1816

Diff for: Include/internal/pycore_tuple.h

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ extern void _PyTuple_DebugMallocStats(FILE *out);
1414
/* runtime lifecycle */
1515

1616
extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
17-
extern void _PyTuple_Fini(_PyFreeListState *);
1817

1918

2019
/* other API */

Diff for: Objects/floatobject.c

-10
Original file line numberDiff line numberDiff line change
@@ -2010,16 +2010,6 @@ _PyFloat_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization)
20102010
#endif
20112011
}
20122012

2013-
void
2014-
_PyFloat_Fini(_PyFreeListState *state)
2015-
{
2016-
// With Py_GIL_DISABLED:
2017-
// the freelists for the current thread state have already been cleared.
2018-
#ifndef Py_GIL_DISABLED
2019-
_PyFloat_ClearFreeList(state, 1);
2020-
#endif
2021-
}
2022-
20232013
void
20242014
_PyFloat_FiniType(PyInterpreterState *interp)
20252015
{

Diff for: Objects/genobject.c

-11
Original file line numberDiff line numberDiff line change
@@ -1682,17 +1682,6 @@ _PyAsyncGen_ClearFreeLists(_PyFreeListState *freelist_state, int is_finalization
16821682
#endif
16831683
}
16841684

1685-
void
1686-
_PyAsyncGen_Fini(_PyFreeListState *state)
1687-
{
1688-
// With Py_GIL_DISABLED:
1689-
// the freelists for the current thread state have already been cleared.
1690-
#ifndef Py_GIL_DISABLED
1691-
_PyAsyncGen_ClearFreeLists(state, 1);
1692-
#endif
1693-
}
1694-
1695-
16961685
static PyObject *
16971686
async_gen_unwrap_value(PyAsyncGenObject *gen, PyObject *result)
16981687
{

Diff for: Objects/listobject.c

-10
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,6 @@ _PyList_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization)
135135
#endif
136136
}
137137

138-
void
139-
_PyList_Fini(_PyFreeListState *state)
140-
{
141-
// With Py_GIL_DISABLED:
142-
// the freelists for the current thread state have already been cleared.
143-
#ifndef Py_GIL_DISABLED
144-
_PyList_ClearFreeList(state, 1);
145-
#endif
146-
}
147-
148138
/* Print summary info about the state of the optimized allocator */
149139
void
150140
_PyList_DebugMallocStats(FILE *out)

Diff for: Objects/object.c

+15
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,21 @@ PyObject_Bytes(PyObject *v)
793793
return PyBytes_FromObject(v);
794794
}
795795

796+
void
797+
_PyObject_ClearFreeLists(_PyFreeListState *state, int is_finalization)
798+
{
799+
// In the free-threaded build, freelists are per-PyThreadState and cleared in PyThreadState_Clear()
800+
// In the default build, freelists are per-interpreter and cleared in finalize_interp_types()
801+
_PyFloat_ClearFreeList(state, is_finalization);
802+
_PyTuple_ClearFreeList(state, is_finalization);
803+
_PyList_ClearFreeList(state, is_finalization);
804+
_PyDict_ClearFreeList(state, is_finalization);
805+
_PyContext_ClearFreeList(state, is_finalization);
806+
_PyAsyncGen_ClearFreeLists(state, is_finalization);
807+
// Only be cleared if is_finalization is true.
808+
_PyObjectStackChunk_ClearFreeList(state, is_finalization);
809+
_PySlice_ClearFreeList(state, is_finalization);
810+
}
796811

797812
/*
798813
def _PyObject_FunctionStr(x):

Diff for: Objects/sliceobject.c

+4-8
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,11 @@ PyObject _Py_EllipsisObject = _PyObject_HEAD_INIT(&PyEllipsis_Type);
103103

104104
/* Slice object implementation */
105105

106-
void _PySlice_ClearCache(_PyFreeListState *state)
106+
void _PySlice_ClearFreeList(_PyFreeListState *state, int is_finalization)
107107
{
108+
if (!is_finalization) {
109+
return;
110+
}
108111
#ifdef WITH_FREELISTS
109112
PySliceObject *obj = state->slices.slice_cache;
110113
if (obj != NULL) {
@@ -114,13 +117,6 @@ void _PySlice_ClearCache(_PyFreeListState *state)
114117
#endif
115118
}
116119

117-
void _PySlice_Fini(_PyFreeListState *state)
118-
{
119-
#ifdef WITH_FREELISTS
120-
_PySlice_ClearCache(state);
121-
#endif
122-
}
123-
124120
/* start, stop, and step are python objects with None indicating no
125121
index is present.
126122
*/

Diff for: Objects/tupleobject.c

-5
Original file line numberDiff line numberDiff line change
@@ -964,11 +964,6 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
964964

965965
static void maybe_freelist_clear(_PyFreeListState *, int);
966966

967-
void
968-
_PyTuple_Fini(_PyFreeListState *state)
969-
{
970-
maybe_freelist_clear(state, 1);
971-
}
972967

973968
void
974969
_PyTuple_ClearFreeList(_PyFreeListState *state, int is_finalization)

Diff for: Python/context.c

-11
Original file line numberDiff line numberDiff line change
@@ -1284,17 +1284,6 @@ _PyContext_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization)
12841284
}
12851285

12861286

1287-
void
1288-
_PyContext_Fini(_PyFreeListState *state)
1289-
{
1290-
// With Py_GIL_DISABLED:
1291-
// the freelists for the current thread state have already been cleared.
1292-
#ifndef Py_GIL_DISABLED
1293-
_PyContext_ClearFreeList(state, 1);
1294-
#endif
1295-
}
1296-
1297-
12981287
PyStatus
12991288
_PyContext_Init(PyInterpreterState *interp)
13001289
{

Diff for: Python/gc_free_threading.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1721,7 +1721,7 @@ _PyGC_ClearAllFreeLists(PyInterpreterState *interp)
17211721
HEAD_LOCK(&_PyRuntime);
17221722
_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)interp->threads.head;
17231723
while (tstate != NULL) {
1724-
_Py_ClearFreeLists(&tstate->freelist_state, 0);
1724+
_PyObject_ClearFreeLists(&tstate->freelist_state, 0);
17251725
tstate = (_PyThreadStateImpl *)tstate->base.next;
17261726
}
17271727
HEAD_UNLOCK(&_PyRuntime);

Diff for: Python/gc_gil.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
void
1212
_PyGC_ClearAllFreeLists(PyInterpreterState *interp)
1313
{
14-
_Py_ClearFreeLists(&interp->freelist_state, 0);
14+
_PyObject_ClearFreeLists(&interp->freelist_state, 0);
1515
}
1616

1717
#endif

Diff for: Python/pylifecycle.c

+5-7
Original file line numberDiff line numberDiff line change
@@ -1790,16 +1790,14 @@ finalize_interp_types(PyInterpreterState *interp)
17901790
// a dict internally.
17911791
_PyUnicode_ClearInterned(interp);
17921792

1793-
_PyDict_Fini(interp);
17941793
_PyUnicode_Fini(interp);
17951794

1795+
#ifndef Py_GIL_DISABLED
1796+
// With Py_GIL_DISABLED:
1797+
// the freelists for the current thread state have already been cleared.
17961798
_PyFreeListState *state = _PyFreeListState_GET();
1797-
_PyTuple_Fini(state);
1798-
_PyList_Fini(state);
1799-
_PyFloat_Fini(state);
1800-
_PySlice_Fini(state);
1801-
_PyContext_Fini(state);
1802-
_PyAsyncGen_Fini(state);
1799+
_PyObject_ClearFreeLists(state, 1);
1800+
#endif
18031801

18041802
#ifdef Py_DEBUG
18051803
_PyStaticObjects_CheckRefcnt(interp);

Diff for: Python/pystate.c

+2-17
Original file line numberDiff line numberDiff line change
@@ -1468,20 +1468,6 @@ clear_datastack(PyThreadState *tstate)
14681468
}
14691469
}
14701470

1471-
void
1472-
_Py_ClearFreeLists(_PyFreeListState *state, int is_finalization)
1473-
{
1474-
// In the free-threaded build, freelists are per-PyThreadState and cleared in PyThreadState_Clear()
1475-
// In the default build, freelists are per-interpreter and cleared in finalize_interp_types()
1476-
_PyFloat_ClearFreeList(state, is_finalization);
1477-
_PyTuple_ClearFreeList(state, is_finalization);
1478-
_PyList_ClearFreeList(state, is_finalization);
1479-
_PyDict_ClearFreeList(state, is_finalization);
1480-
_PyContext_ClearFreeList(state, is_finalization);
1481-
_PyAsyncGen_ClearFreeLists(state, is_finalization);
1482-
_PyObjectStackChunk_ClearFreeList(state, is_finalization);
1483-
}
1484-
14851471
void
14861472
PyThreadState_Clear(PyThreadState *tstate)
14871473
{
@@ -1566,9 +1552,8 @@ PyThreadState_Clear(PyThreadState *tstate)
15661552
}
15671553
#ifdef Py_GIL_DISABLED
15681554
// Each thread should clear own freelists in free-threading builds.
1569-
_PyFreeListState *freelist_state = &((_PyThreadStateImpl*)tstate)->freelist_state;
1570-
_Py_ClearFreeLists(freelist_state, 1);
1571-
_PySlice_ClearCache(freelist_state);
1555+
_PyFreeListState *freelist_state = _PyFreeListState_GET();
1556+
_PyObject_ClearFreeLists(freelist_state, 1);
15721557

15731558
// Remove ourself from the biased reference counting table of threads.
15741559
_Py_brc_remove_thread(tstate);

0 commit comments

Comments
 (0)