diff --git a/Include/internal/pycore_floatobject.h b/Include/internal/pycore_floatobject.h index 4e5474841bc..038578e1f96 100644 --- a/Include/internal/pycore_floatobject.h +++ b/Include/internal/pycore_floatobject.h @@ -8,14 +8,14 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif - +#include "pycore_freelist.h" // _PyFreeListState #include "pycore_unicodeobject.h" // _PyUnicodeWriter /* runtime lifecycle */ extern void _PyFloat_InitState(PyInterpreterState *); extern PyStatus _PyFloat_InitTypes(PyInterpreterState *); -extern void _PyFloat_Fini(PyInterpreterState *); +extern void _PyFloat_Fini(_PyFreeListState *); extern void _PyFloat_FiniType(PyInterpreterState *); @@ -33,24 +33,7 @@ struct _Py_float_runtime_state { }; -#ifndef WITH_FREELISTS -// without freelists -# define PyFloat_MAXFREELIST 0 -#endif -#ifndef PyFloat_MAXFREELIST -# define PyFloat_MAXFREELIST 100 -#endif - -struct _Py_float_state { -#if PyFloat_MAXFREELIST > 0 - /* Special free list - free_list is a singly-linked list of available PyFloatObjects, - linked via abuse of their ob_type members. */ - int numfree; - PyFloatObject *free_list; -#endif -}; void _PyFloat_ExactDealloc(PyObject *op); diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index b725986528d..d9619218b8d 100644 --- a/Include/internal/pycore_freelist.h +++ b/Include/internal/pycore_freelist.h @@ -8,24 +8,34 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#ifndef WITH_FREELISTS -// without freelists -# define PyList_MAXFREELIST 0 -#endif - -/* Empty list reuse scheme to save calls to malloc and free */ -#ifndef PyList_MAXFREELIST +#ifdef WITH_FREELISTS +// with freelists # define PyList_MAXFREELIST 80 +# define PyFloat_MAXFREELIST 100 +#else +# define PyList_MAXFREELIST 0 +# define PyFloat_MAXFREELIST 0 #endif struct _Py_list_state { -#if PyList_MAXFREELIST > 0 +#ifdef WITH_FREELISTS PyListObject *free_list[PyList_MAXFREELIST]; int numfree; #endif }; +struct _Py_float_state { +#ifdef WITH_FREELISTS + /* Special free list + free_list is a singly-linked list of available PyFloatObjects, + linked via abuse of their ob_type members. */ + int numfree; + PyFloatObject *free_list; +#endif +}; + typedef struct _Py_freelist_state { + struct _Py_float_state float_state; struct _Py_list_state list; } _PyFreeListState; diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index 5d90d3a7f86..2a0730eebb8 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -243,7 +243,7 @@ extern PyObject *_PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs); extern void _PyGC_ClearAllFreeLists(PyInterpreterState *interp); extern void _Py_ClearFreeLists(_PyFreeListState *state, int is_finalization); extern void _PyTuple_ClearFreeList(PyInterpreterState *interp); -extern void _PyFloat_ClearFreeList(PyInterpreterState *interp); +extern void _PyFloat_ClearFreeList(_PyFreeListState *state, int is_finalization); extern void _PyList_ClearFreeList(_PyFreeListState *state, int is_finalization); extern void _PyDict_ClearFreeList(PyInterpreterState *interp); extern void _PyAsyncGen_ClearFreeLists(PyInterpreterState *interp); diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 4d49fa2a51b..dadc8e3b91a 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -184,7 +184,6 @@ struct _is { #endif struct _py_object_state object_state; struct _Py_unicode_state unicode; - struct _Py_float_state float_state; struct _Py_long_state long_state; struct _dtoa_state dtoa; struct _py_func_state func_state; diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 364cf1553bb..f1a09c0a94f 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -26,17 +26,13 @@ class float "PyObject *" "&PyFloat_Type" #include "clinic/floatobject.c.h" -#ifndef PyFloat_MAXFREELIST -# define PyFloat_MAXFREELIST 100 -#endif - - -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS static struct _Py_float_state * get_float_state(void) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - return &interp->float_state; + _PyFreeListState *state = _PyFreeListState_GET(); + assert(state != NULL); + return &state->float_state; } #endif @@ -132,7 +128,7 @@ PyObject * PyFloat_FromDouble(double fval) { PyFloatObject *op; -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS struct _Py_float_state *state = get_float_state(); op = state->free_list; if (op != NULL) { @@ -252,13 +248,9 @@ _PyFloat_ExactDealloc(PyObject *obj) { assert(PyFloat_CheckExact(obj)); PyFloatObject *op = (PyFloatObject *)obj; -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS struct _Py_float_state *state = get_float_state(); -#ifdef Py_DEBUG - // float_dealloc() must not be called after _PyFloat_Fini() - assert(state->numfree != -1); -#endif - if (state->numfree >= PyFloat_MAXFREELIST) { + if (state->numfree >= PyFloat_MAXFREELIST || state->numfree < 0) { PyObject_Free(op); return; } @@ -275,7 +267,7 @@ static void float_dealloc(PyObject *op) { assert(PyFloat_Check(op)); -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS if (PyFloat_CheckExact(op)) { _PyFloat_ExactDealloc(op); } @@ -2002,10 +1994,10 @@ _PyFloat_InitTypes(PyInterpreterState *interp) } void -_PyFloat_ClearFreeList(PyInterpreterState *interp) +_PyFloat_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization) { -#if PyFloat_MAXFREELIST > 0 - struct _Py_float_state *state = &interp->float_state; +#ifdef WITH_FREELISTS + struct _Py_float_state *state = &freelist_state->float_state; PyFloatObject *f = state->free_list; while (f != NULL) { PyFloatObject *next = (PyFloatObject*) Py_TYPE(f); @@ -2013,18 +2005,19 @@ _PyFloat_ClearFreeList(PyInterpreterState *interp) f = next; } state->free_list = NULL; - state->numfree = 0; + if (is_finalization) { + state->numfree = -1; + } + else { + state->numfree = 0; + } #endif } void -_PyFloat_Fini(PyInterpreterState *interp) +_PyFloat_Fini(_PyFreeListState *state) { - _PyFloat_ClearFreeList(interp); -#if defined(Py_DEBUG) && PyFloat_MAXFREELIST > 0 - struct _Py_float_state *state = &interp->float_state; - state->numfree = -1; -#endif + _PyFloat_ClearFreeList(state, 1); } void @@ -2037,7 +2030,7 @@ _PyFloat_FiniType(PyInterpreterState *interp) void _PyFloat_DebugMallocStats(FILE *out) { -#if PyFloat_MAXFREELIST > 0 +#ifdef WITH_FREELISTS struct _Py_float_state *state = get_float_state(); _PyDebugAllocatorStats(out, "free PyFloatObject", diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index aea272840f9..c19893a39c1 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -15,7 +15,6 @@ void _PyGC_ClearAllFreeLists(PyInterpreterState *interp) { _PyTuple_ClearFreeList(interp); - _PyFloat_ClearFreeList(interp); _PyDict_ClearFreeList(interp); _PyAsyncGen_ClearFreeLists(interp); _PyContext_ClearFreeList(interp); diff --git a/Python/gc_gil.c b/Python/gc_gil.c index b0961cdbee9..c8ca397be7a 100644 --- a/Python/gc_gil.c +++ b/Python/gc_gil.c @@ -12,7 +12,6 @@ void _PyGC_ClearAllFreeLists(PyInterpreterState *interp) { _PyTuple_ClearFreeList(interp); - _PyFloat_ClearFreeList(interp); _PyDict_ClearFreeList(interp); _PyAsyncGen_ClearFreeLists(interp); _PyContext_ClearFreeList(interp); diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index bd6475f99e4..6468e72eaad 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1757,10 +1757,10 @@ finalize_interp_types(PyInterpreterState *interp) _PySlice_Fini(interp); _PyUnicode_Fini(interp); - _PyFloat_Fini(interp); _PyFreeListState *state = _PyFreeListState_GET(); _PyList_Fini(state); + _PyFloat_Fini(state); #ifdef Py_DEBUG _PyStaticObjects_CheckRefcnt(interp); diff --git a/Python/pystate.c b/Python/pystate.c index ddd57f75f3f..683e29277b4 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1458,6 +1458,7 @@ clear_datastack(PyThreadState *tstate) void _Py_ClearFreeLists(_PyFreeListState *state, int is_finalization) { + _PyFloat_ClearFreeList(state, is_finalization); _PyList_ClearFreeList(state, is_finalization); }