Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-111968: Rename freelist related struct names to Eric's suggestion #115329

Merged
merged 9 commits into from
Feb 14, 2024
6 changes: 0 additions & 6 deletions Include/internal/pycore_dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,6 @@ typedef struct {
extern PyObject* _PyDictView_New(PyObject *, PyTypeObject *);
extern PyObject* _PyDictView_Intersect(PyObject* self, PyObject *other);


/* runtime lifecycle */

extern void _PyDict_Fini(PyInterpreterState *state);


/* other API */

typedef struct {
Expand Down
52 changes: 26 additions & 26 deletions Include/internal/pycore_freelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ extern "C" {
# define _PyObjectStackChunk_MAXFREELIST 0
#endif

struct _Py_list_state {
struct _Py_list_freelist {
#ifdef WITH_FREELISTS
PyListObject *free_list[PyList_MAXFREELIST];
int numfree;
#endif
};

struct _Py_tuple_state {
struct _Py_tuple_freelist {
#if WITH_FREELISTS
/* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE.
The empty tuple is handled separately.
Expand All @@ -57,7 +57,7 @@ struct _Py_tuple_state {
#endif
};

struct _Py_float_state {
struct _Py_float_freelist {
#ifdef WITH_FREELISTS
/* Special free list
free_list is a singly-linked list of available PyFloatObjects,
Expand All @@ -77,23 +77,23 @@ struct _Py_dict_freelist {
#endif
};

struct _Py_slice_state {
struct _Py_slice_freelist {
#ifdef WITH_FREELISTS
/* Using a cache is very effective since typically only a single slice is
created and then deleted again. */
PySliceObject *slice_cache;
#endif
};

struct _Py_context_state {
struct _Py_context_freelist {
#ifdef WITH_FREELISTS
// List of free PyContext objects
PyContext *freelist;
int numfree;
#endif
};

struct _Py_async_gen_state {
struct _Py_async_gen_freelist {
#ifdef WITH_FREELISTS
/* Freelists boost performance 6-10%; they also reduce memory
fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend
Expand All @@ -109,31 +109,31 @@ struct _Py_async_gen_state {

struct _PyObjectStackChunk;

struct _Py_object_stack_state {
struct _Py_object_stack_freelist {
struct _PyObjectStackChunk *free_list;
Py_ssize_t numfree;
};

typedef struct _Py_freelist_state {
struct _Py_float_state floats;
struct _Py_tuple_state tuples;
struct _Py_list_state lists;
struct _Py_object_freelists {
struct _Py_float_freelist floats;
struct _Py_tuple_freelist tuples;
struct _Py_list_freelist lists;
struct _Py_dict_freelist dicts;
struct _Py_slice_state slices;
struct _Py_context_state contexts;
struct _Py_async_gen_state async_gens;
struct _Py_object_stack_state object_stacks;
} _PyFreeListState;

extern void _PyObject_ClearFreeLists(_PyFreeListState *state, int is_finalization);
extern void _PyTuple_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _PyFloat_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _PyList_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _PySlice_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _PyDict_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _PyAsyncGen_ClearFreeLists(_PyFreeListState *state, int is_finalization);
extern void _PyContext_ClearFreeList(_PyFreeListState *state, int is_finalization);
extern void _PyObjectStackChunk_ClearFreeList(_PyFreeListState *state, int is_finalization);
struct _Py_slice_freelist slices;
struct _Py_context_freelist contexts;
struct _Py_async_gen_freelist async_gens;
struct _Py_object_stack_freelist object_stacks;
};

extern void _PyObject_ClearFreeLists(struct _Py_object_freelists *freelists, int is_finalization);
extern void _PyTuple_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization);
extern void _PyFloat_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization);
extern void _PyList_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization);
extern void _PySlice_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization);
extern void _PyDict_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization);
extern void _PyAsyncGen_ClearFreeLists(struct _Py_object_freelists *freelists, int is_finalization);
extern void _PyContext_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization);
extern void _PyObjectStackChunk_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization);

#ifdef __cplusplus
}
Expand Down
4 changes: 0 additions & 4 deletions Include/internal/pycore_interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ extern "C" {
#include "pycore_dtoa.h" // struct _dtoa_state
#include "pycore_exceptions.h" // struct _Py_exc_state
#include "pycore_floatobject.h" // struct _Py_float_state
#include "pycore_freelist.h" // struct _Py_freelist_state
#include "pycore_function.h" // FUNC_MAX_WATCHERS
#include "pycore_gc.h" // struct _gc_runtime_state
#include "pycore_genobject.h" // struct _Py_async_gen_state
Expand Down Expand Up @@ -222,9 +221,6 @@ struct _is {
// One bit is set for each non-NULL entry in code_watchers
uint8_t active_code_watchers;

#if !defined(Py_GIL_DISABLED)
struct _Py_freelist_state freelist_state;
#endif
struct _py_object_state object_state;
struct _Py_unicode_state unicode;
struct _Py_long_state long_state;
Expand Down
4 changes: 4 additions & 0 deletions Include/internal/pycore_object_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif

#include "pycore_freelist.h" // _PyObject_freelists
#include "pycore_hashtable.h" // _Py_hashtable_t

struct _py_object_runtime_state {
Expand All @@ -18,6 +19,9 @@ struct _py_object_runtime_state {
};

struct _py_object_state {
#if !defined(Py_GIL_DISABLED)
struct _Py_object_freelists freelists;
#endif
#ifdef Py_REF_DEBUG
Py_ssize_t reftotal;
#endif
Expand Down
6 changes: 3 additions & 3 deletions Include/internal/pycore_pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,17 +268,17 @@ PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);
// See also PyInterpreterState_Get() and _PyInterpreterState_GET().
extern PyInterpreterState* _PyGILState_GetInterpreterStateUnsafe(void);

static inline _PyFreeListState* _PyFreeListState_GET(void)
static inline struct _Py_object_freelists* _Py_object_freelists_GET(void)
{
PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG
_Py_EnsureTstateNotNULL(tstate);
#endif

#ifdef Py_GIL_DISABLED
return &((_PyThreadStateImpl*)tstate)->freelist_state;
return &((_PyThreadStateImpl*)tstate)->freelists;
#else
return &tstate->interp->freelist_state;
return &tstate->interp->object_state.freelists;
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_tstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ typedef struct _PyThreadStateImpl {

#ifdef Py_GIL_DISABLED
struct _mimalloc_thread_state mimalloc;
struct _Py_freelist_state freelist_state;
struct _Py_object_freelists freelists;
struct _brc_thread_state brc;
#endif

Expand Down
51 changes: 20 additions & 31 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,19 +271,19 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu

#ifdef WITH_FREELISTS
static struct _Py_dict_freelist *
get_dict_state(void)
get_dict_freelist(void)
{
_PyFreeListState *state = _PyFreeListState_GET();
return &state->dicts;
struct _Py_object_freelists *freelists = _Py_object_freelists_GET();
return &freelists->dicts;
}
#endif


void
_PyDict_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization)
_PyDict_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization)
{
#ifdef WITH_FREELISTS
struct _Py_dict_freelist *state = &freelist_state->dicts;
struct _Py_dict_freelist *state = &freelists->dicts;
while (state->numfree > 0) {
PyDictObject *op = state->free_list[--state->numfree];
assert(PyDict_CheckExact(op));
Expand All @@ -299,17 +299,6 @@ _PyDict_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization)
#endif
}

void
_PyDict_Fini(PyInterpreterState *Py_UNUSED(interp))
{
// With Py_GIL_DISABLED:
// the freelists for the current thread state have already been cleared.
#ifndef Py_GIL_DISABLED
_PyFreeListState *state = _PyFreeListState_GET();
_PyDict_ClearFreeList(state, 1);
#endif
}

static inline Py_hash_t
unicode_get_hash(PyObject *o)
{
Expand All @@ -322,9 +311,9 @@ void
_PyDict_DebugMallocStats(FILE *out)
{
#ifdef WITH_FREELISTS
struct _Py_dict_freelist *state = get_dict_state();
struct _Py_dict_freelist *dict_freelist = get_dict_freelist();
_PyDebugAllocatorStats(out, "free PyDictObject",
state->numfree, sizeof(PyDictObject));
dict_freelist->numfree, sizeof(PyDictObject));
#endif
}

Expand Down Expand Up @@ -674,9 +663,9 @@ new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode)
}

#ifdef WITH_FREELISTS
struct _Py_dict_freelist *state = get_dict_state();
if (log2_size == PyDict_LOG_MINSIZE && unicode && state->keys_numfree > 0) {
dk = state->keys_free_list[--state->keys_numfree];
struct _Py_dict_freelist *dict_freelist = get_dict_freelist();
if (log2_size == PyDict_LOG_MINSIZE && unicode && dict_freelist->keys_numfree > 0) {
dk = dict_freelist->keys_free_list[--dict_freelist->keys_numfree];
OBJECT_STAT_INC(from_freelist);
}
else
Expand Down Expand Up @@ -709,12 +698,12 @@ static void
free_keys_object(PyDictKeysObject *keys)
{
#ifdef WITH_FREELISTS
struct _Py_dict_freelist *state = get_dict_state();
struct _Py_dict_freelist *dict_freelist = get_dict_freelist();
if (DK_LOG_SIZE(keys) == PyDict_LOG_MINSIZE
&& state->keys_numfree < PyDict_MAXFREELIST
&& state->keys_numfree >= 0
&& dict_freelist->keys_numfree < PyDict_MAXFREELIST
&& dict_freelist->keys_numfree >= 0
&& DK_IS_UNICODE(keys)) {
state->keys_free_list[state->keys_numfree++] = keys;
dict_freelist->keys_free_list[dict_freelist->keys_numfree++] = keys;
OBJECT_STAT_INC(to_freelist);
return;
}
Expand Down Expand Up @@ -754,9 +743,9 @@ new_dict(PyInterpreterState *interp,
PyDictObject *mp;
assert(keys != NULL);
#ifdef WITH_FREELISTS
struct _Py_dict_freelist *state = get_dict_state();
if (state->numfree > 0) {
mp = state->free_list[--state->numfree];
struct _Py_dict_freelist *dict_freelist = get_dict_freelist();
if (dict_freelist->numfree > 0) {
mp = dict_freelist->free_list[--dict_freelist->numfree];
assert (mp != NULL);
assert (Py_IS_TYPE(mp, &PyDict_Type));
OBJECT_STAT_INC(from_freelist);
Expand Down Expand Up @@ -2604,10 +2593,10 @@ dict_dealloc(PyObject *self)
dictkeys_decref(interp, keys);
}
#ifdef WITH_FREELISTS
struct _Py_dict_freelist *state = get_dict_state();
if (state->numfree < PyDict_MAXFREELIST && state->numfree >=0 &&
struct _Py_dict_freelist *dict_freelist = get_dict_freelist();
if (dict_freelist->numfree < PyDict_MAXFREELIST && dict_freelist->numfree >=0 &&
Py_IS_TYPE(mp, &PyDict_Type)) {
state->free_list[state->numfree++] = mp;
dict_freelist->free_list[dict_freelist->numfree++] = mp;
OBJECT_STAT_INC(to_freelist);
}
else
Expand Down
38 changes: 19 additions & 19 deletions Objects/floatobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "pycore_dtoa.h" // _Py_dg_dtoa()
#include "pycore_floatobject.h" // _PyFloat_FormatAdvancedWriter()
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_interp.h" // _PyInterpreterState.float_state
#include "pycore_interp.h" // _Py_float_freelist
#include "pycore_long.h" // _PyLong_GetOne()
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_Init(), _PyDebugAllocatorStats()
Expand All @@ -27,12 +27,12 @@ class float "PyObject *" "&PyFloat_Type"
#include "clinic/floatobject.c.h"

#ifdef WITH_FREELISTS
static struct _Py_float_state *
get_float_state(void)
static struct _Py_float_freelist *
get_float_freelist(void)
{
_PyFreeListState *state = _PyFreeListState_GET();
assert(state != NULL);
return &state->floats;
struct _Py_object_freelists *freelists = _Py_object_freelists_GET();
assert(freelists != NULL);
return &freelists->floats;
}
#endif

Expand Down Expand Up @@ -129,11 +129,11 @@ PyFloat_FromDouble(double fval)
{
PyFloatObject *op;
#ifdef WITH_FREELISTS
struct _Py_float_state *state = get_float_state();
op = state->free_list;
struct _Py_float_freelist *float_freelist = get_float_freelist();
op = float_freelist->free_list;
if (op != NULL) {
state->free_list = (PyFloatObject *) Py_TYPE(op);
state->numfree--;
float_freelist->free_list = (PyFloatObject *) Py_TYPE(op);
float_freelist->numfree--;
OBJECT_STAT_INC(from_freelist);
}
else
Expand Down Expand Up @@ -245,14 +245,14 @@ _PyFloat_ExactDealloc(PyObject *obj)
assert(PyFloat_CheckExact(obj));
PyFloatObject *op = (PyFloatObject *)obj;
#ifdef WITH_FREELISTS
struct _Py_float_state *state = get_float_state();
if (state->numfree >= PyFloat_MAXFREELIST || state->numfree < 0) {
struct _Py_float_freelist *float_freelist = get_float_freelist();
if (float_freelist->numfree >= PyFloat_MAXFREELIST || float_freelist->numfree < 0) {
PyObject_Free(op);
return;
}
state->numfree++;
Py_SET_TYPE(op, (PyTypeObject *)state->free_list);
state->free_list = op;
float_freelist->numfree++;
Py_SET_TYPE(op, (PyTypeObject *)float_freelist->free_list);
float_freelist->free_list = op;
OBJECT_STAT_INC(to_freelist);
#else
PyObject_Free(op);
Expand Down Expand Up @@ -1990,10 +1990,10 @@ _PyFloat_InitTypes(PyInterpreterState *interp)
}

void
_PyFloat_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization)
_PyFloat_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization)
{
#ifdef WITH_FREELISTS
struct _Py_float_state *state = &freelist_state->floats;
struct _Py_float_freelist *state = &freelists->floats;
PyFloatObject *f = state->free_list;
while (f != NULL) {
PyFloatObject *next = (PyFloatObject*) Py_TYPE(f);
Expand Down Expand Up @@ -2021,10 +2021,10 @@ void
_PyFloat_DebugMallocStats(FILE *out)
{
#ifdef WITH_FREELISTS
struct _Py_float_state *state = get_float_state();
struct _Py_float_freelist *float_freelist = get_float_freelist();
_PyDebugAllocatorStats(out,
"free PyFloatObject",
state->numfree, sizeof(PyFloatObject));
float_freelist->numfree, sizeof(PyFloatObject));
#endif
}

Expand Down
Loading
Loading