mirror of
https://github.com/python/cpython.git
synced 2025-08-22 17:55:18 +00:00
bpo-45522: Allow to disable freelists on build time (GH-29056)
Freelists for object structs can now be disabled. A new ``configure`` option ``--without-freelists`` can be used to disable all freelists except empty tuple singleton. Internal Py*_MAXFREELIST macros can now be defined as 0 without causing compiler warnings and segfaults. Signed-off-by: Christian Heimes <christian@python.org>
This commit is contained in:
parent
5a14f71fe8
commit
9942f42a93
15 changed files with 218 additions and 35 deletions
|
@ -19,12 +19,14 @@ static PyMemberDef frame_memberlist[] = {
|
|||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
#if PyFrame_MAXFREELIST > 0
|
||||
static struct _Py_frame_state *
|
||||
get_frame_state(void)
|
||||
{
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
return &interp->frame;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static PyObject *
|
||||
|
@ -607,9 +609,6 @@ static PyGetSetDef frame_getsetlist[] = {
|
|||
f_back next item on free list, or NULL
|
||||
*/
|
||||
|
||||
/* max value for numfree */
|
||||
#define PyFrame_MAXFREELIST 200
|
||||
|
||||
static void _Py_HOT_FUNCTION
|
||||
frame_dealloc(PyFrameObject *f)
|
||||
{
|
||||
|
@ -638,6 +637,7 @@ frame_dealloc(PyFrameObject *f)
|
|||
}
|
||||
Py_CLEAR(f->f_back);
|
||||
Py_CLEAR(f->f_trace);
|
||||
#if PyFrame_MAXFREELIST > 0
|
||||
struct _Py_frame_state *state = get_frame_state();
|
||||
#ifdef Py_DEBUG
|
||||
// frame_dealloc() must not be called after _PyFrame_Fini()
|
||||
|
@ -648,7 +648,9 @@ frame_dealloc(PyFrameObject *f)
|
|||
f->f_back = state->free_list;
|
||||
state->free_list = f;
|
||||
}
|
||||
else {
|
||||
else
|
||||
#endif
|
||||
{
|
||||
PyObject_GC_Del(f);
|
||||
}
|
||||
|
||||
|
@ -801,8 +803,10 @@ static inline PyFrameObject*
|
|||
frame_alloc(InterpreterFrame *frame, int owns)
|
||||
{
|
||||
PyFrameObject *f;
|
||||
#if PyFrame_MAXFREELIST > 0
|
||||
struct _Py_frame_state *state = get_frame_state();
|
||||
if (state->free_list == NULL)
|
||||
#endif
|
||||
{
|
||||
f = PyObject_GC_New(PyFrameObject, &PyFrame_Type);
|
||||
if (f == NULL) {
|
||||
|
@ -816,7 +820,9 @@ frame_alloc(InterpreterFrame *frame, int owns)
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if PyFrame_MAXFREELIST > 0
|
||||
else
|
||||
{
|
||||
#ifdef Py_DEBUG
|
||||
// frame_alloc() must not be called after _PyFrame_Fini()
|
||||
assert(state->numfree != -1);
|
||||
|
@ -827,6 +833,7 @@ frame_alloc(InterpreterFrame *frame, int owns)
|
|||
state->free_list = state->free_list->f_back;
|
||||
_Py_NewReference((PyObject *)f);
|
||||
}
|
||||
#endif
|
||||
f->f_frame = frame;
|
||||
f->f_own_locals_memory = owns;
|
||||
return f;
|
||||
|
@ -1069,6 +1076,7 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
|
|||
void
|
||||
_PyFrame_ClearFreeList(PyInterpreterState *interp)
|
||||
{
|
||||
#if PyFrame_MAXFREELIST > 0
|
||||
struct _Py_frame_state *state = &interp->frame;
|
||||
while (state->free_list != NULL) {
|
||||
PyFrameObject *f = state->free_list;
|
||||
|
@ -1077,13 +1085,14 @@ _PyFrame_ClearFreeList(PyInterpreterState *interp)
|
|||
--state->numfree;
|
||||
}
|
||||
assert(state->numfree == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_PyFrame_Fini(PyInterpreterState *interp)
|
||||
{
|
||||
_PyFrame_ClearFreeList(interp);
|
||||
#ifdef Py_DEBUG
|
||||
#if defined(Py_DEBUG) && PyFrame_MAXFREELIST > 0
|
||||
struct _Py_frame_state *state = &interp->frame;
|
||||
state->numfree = -1;
|
||||
#endif
|
||||
|
@ -1093,10 +1102,12 @@ _PyFrame_Fini(PyInterpreterState *interp)
|
|||
void
|
||||
_PyFrame_DebugMallocStats(FILE *out)
|
||||
{
|
||||
#if PyFrame_MAXFREELIST > 0
|
||||
struct _Py_frame_state *state = get_frame_state();
|
||||
_PyDebugAllocatorStats(out,
|
||||
"free PyFrameObject",
|
||||
state->numfree, sizeof(PyFrameObject));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue