From 522691c46e2ae51faaad5bbbce7d959dd61770df Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 23 Jun 2020 16:40:40 +0200 Subject: bpo-40521: Cleanup code of free lists (GH-21082) Add get_xxx_state() function to factorize duplicated code. --- Objects/dictobject.c | 30 ++++++++++++++++-------------- Objects/floatobject.c | 21 ++++++++++++++------- Objects/frameobject.c | 18 ++++++++++++------ Objects/genobject.c | 20 ++++++++++++-------- Objects/listobject.c | 18 ++++++++++++------ Objects/sliceobject.c | 24 ++++++++++++++++-------- Objects/tupleobject.c | 34 ++++++++++++++++++---------------- Python/context.c | 14 ++++++++++---- 8 files changed, 110 insertions(+), 69 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index f3b1157..b1f11b3 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -249,6 +249,15 @@ static uint64_t pydict_global_version = 0; #include "clinic/dictobject.c.h" + +static struct _Py_dict_state * +get_dict_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->dict_state; +} + + void _PyDict_ClearFreeList(PyThreadState *tstate) { @@ -269,8 +278,7 @@ _PyDict_Fini(PyThreadState *tstate) { _PyDict_ClearFreeList(tstate); #ifdef Py_DEBUG - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_dict_state *state = &interp->dict_state; + struct _Py_dict_state *state = get_dict_state(); state->numfree = -1; state->keys_numfree = -1; #endif @@ -281,8 +289,7 @@ _PyDict_Fini(PyThreadState *tstate) void _PyDict_DebugMallocStats(FILE *out) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_dict_state *state = &interp->dict_state; + struct _Py_dict_state *state = get_dict_state(); _PyDebugAllocatorStats(out, "free PyDictObject", state->numfree, sizeof(PyDictObject)); } @@ -557,8 +564,7 @@ new_keys_object(Py_ssize_t size) es = sizeof(Py_ssize_t); } - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_dict_state *state = &interp->dict_state; + struct _Py_dict_state *state = get_dict_state(); #ifdef Py_DEBUG // new_keys_object() must not be called after _PyDict_Fini() assert(state->keys_numfree != -1); @@ -598,8 +604,7 @@ free_keys_object(PyDictKeysObject *keys) Py_XDECREF(entries[i].me_key); Py_XDECREF(entries[i].me_value); } - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_dict_state *state = &interp->dict_state; + struct _Py_dict_state *state = get_dict_state(); #ifdef Py_DEBUG // free_keys_object() must not be called after _PyDict_Fini() assert(state->keys_numfree != -1); @@ -620,8 +625,7 @@ new_dict(PyDictKeysObject *keys, PyObject **values) { PyDictObject *mp; assert(keys != NULL); - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_dict_state *state = &interp->dict_state; + struct _Py_dict_state *state = get_dict_state(); #ifdef Py_DEBUG // new_dict() must not be called after _PyDict_Fini() assert(state->numfree != -1); @@ -1281,8 +1285,7 @@ dictresize(PyDictObject *mp, Py_ssize_t minsize) #ifdef Py_REF_DEBUG _Py_RefTotal--; #endif - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_dict_state *state = &interp->dict_state; + struct _Py_dict_state *state = get_dict_state(); #ifdef Py_DEBUG // dictresize() must not be called after _PyDict_Fini() assert(state->keys_numfree != -1); @@ -2032,8 +2035,7 @@ dict_dealloc(PyDictObject *mp) assert(keys->dk_refcnt == 1); dictkeys_decref(keys); } - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_dict_state *state = &interp->dict_state; + struct _Py_dict_state *state = get_dict_state(); #ifdef Py_DEBUG // new_dict() must not be called after _PyDict_Fini() assert(state->numfree != -1); diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 7ffd7ee..0606f29 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -23,6 +23,15 @@ class float "PyObject *" "&PyFloat_Type" # define PyFloat_MAXFREELIST 100 #endif + +static struct _Py_float_state * +get_float_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->float_state; +} + + double PyFloat_GetMax(void) { @@ -113,8 +122,7 @@ PyFloat_GetInfo(void) PyObject * PyFloat_FromDouble(double fval) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_float_state *state = &interp->float_state; + struct _Py_float_state *state = get_float_state(); PyFloatObject *op = state->free_list; if (op != NULL) { #ifdef Py_DEBUG @@ -222,8 +230,7 @@ static void float_dealloc(PyFloatObject *op) { if (PyFloat_CheckExact(op)) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_float_state *state = &interp->float_state; + struct _Py_float_state *state = get_float_state(); #ifdef Py_DEBUG // float_dealloc() must not be called after _PyFloat_Fini() assert(state->numfree != -1); @@ -236,8 +243,9 @@ float_dealloc(PyFloatObject *op) Py_SET_TYPE(op, (PyTypeObject *)state->free_list); state->free_list = op; } - else + else { Py_TYPE(op)->tp_free((PyObject *)op); + } } double @@ -2017,8 +2025,7 @@ _PyFloat_Fini(PyThreadState *tstate) void _PyFloat_DebugMallocStats(FILE *out) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_float_state *state = &interp->float_state; + struct _Py_float_state *state = get_float_state(); _PyDebugAllocatorStats(out, "free PyFloatObject", state->numfree, sizeof(PyFloatObject)); diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 6e1cbcf..7c2bce3 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -22,6 +22,15 @@ static PyMemberDef frame_memberlist[] = { {NULL} /* Sentinel */ }; + +static struct _Py_frame_state * +get_frame_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->frame; +} + + static PyObject * frame_getlocals(PyFrameObject *f, void *closure) { @@ -593,8 +602,7 @@ frame_dealloc(PyFrameObject *f) co->co_zombieframe = f; } else { - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_frame_state *state = &interp->frame; + struct _Py_frame_state *state = get_frame_state(); #ifdef Py_DEBUG // frame_dealloc() must not be called after _PyFrame_Fini() assert(state->numfree != -1); @@ -784,8 +792,7 @@ frame_alloc(PyCodeObject *code) Py_ssize_t ncells = PyTuple_GET_SIZE(code->co_cellvars); Py_ssize_t nfrees = PyTuple_GET_SIZE(code->co_freevars); Py_ssize_t extras = code->co_stacksize + code->co_nlocals + ncells + nfrees; - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_frame_state *state = &interp->frame; + struct _Py_frame_state *state = get_frame_state(); if (state->free_list == NULL) { f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, extras); @@ -1206,8 +1213,7 @@ _PyFrame_Fini(PyThreadState *tstate) void _PyFrame_DebugMallocStats(FILE *out) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_frame_state *state = &interp->frame; + struct _Py_frame_state *state = get_frame_state(); _PyDebugAllocatorStats(out, "free PyFrameObject", state->numfree, sizeof(PyFrameObject)); diff --git a/Objects/genobject.c b/Objects/genobject.c index 4207d532..6a68c94 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -1389,6 +1389,14 @@ PyTypeObject PyAsyncGen_Type = { }; +static struct _Py_async_gen_state * +get_async_gen_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->async_gen; +} + + PyObject * PyAsyncGen_New(PyFrameObject *f, PyObject *name, PyObject *qualname) { @@ -1477,8 +1485,7 @@ async_gen_asend_dealloc(PyAsyncGenASend *o) _PyObject_GC_UNTRACK((PyObject *)o); Py_CLEAR(o->ags_gen); Py_CLEAR(o->ags_sendval); - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_async_gen_state *state = &interp->async_gen; + struct _Py_async_gen_state *state = get_async_gen_state(); #ifdef Py_DEBUG // async_gen_asend_dealloc() must not be called after _PyAsyncGen_Fini() assert(state->asend_numfree != -1); @@ -1639,8 +1646,7 @@ static PyObject * async_gen_asend_new(PyAsyncGenObject *gen, PyObject *sendval) { PyAsyncGenASend *o; - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_async_gen_state *state = &interp->async_gen; + struct _Py_async_gen_state *state = get_async_gen_state(); #ifdef Py_DEBUG // async_gen_asend_new() must not be called after _PyAsyncGen_Fini() assert(state->asend_numfree != -1); @@ -1678,8 +1684,7 @@ async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o) { _PyObject_GC_UNTRACK((PyObject *)o); Py_CLEAR(o->agw_val); - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_async_gen_state *state = &interp->async_gen; + struct _Py_async_gen_state *state = get_async_gen_state(); #ifdef Py_DEBUG // async_gen_wrapped_val_dealloc() must not be called after _PyAsyncGen_Fini() assert(state->value_numfree != -1); @@ -1752,8 +1757,7 @@ _PyAsyncGenValueWrapperNew(PyObject *val) _PyAsyncGenWrappedValue *o; assert(val); - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_async_gen_state *state = &interp->async_gen; + struct _Py_async_gen_state *state = get_async_gen_state(); #ifdef Py_DEBUG // _PyAsyncGenValueWrapperNew() must not be called after _PyAsyncGen_Fini() assert(state->value_numfree != -1); diff --git a/Objects/listobject.c b/Objects/listobject.c index 261a0fd..ab03615 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -19,6 +19,15 @@ class list "PyListObject *" "&PyList_Type" #include "clinic/listobject.c.h" + +static struct _Py_list_state * +get_list_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->list; +} + + /* Ensure ob_item has room for at least newsize elements, and set * ob_size to newsize. If newsize > ob_size on entry, the content * of the new slots at exit is undefined heap trash; it's the caller's @@ -121,8 +130,7 @@ _PyList_Fini(PyThreadState *tstate) void _PyList_DebugMallocStats(FILE *out) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_list_state *state = &interp->list; + struct _Py_list_state *state = get_list_state(); _PyDebugAllocatorStats(out, "free PyListObject", state->numfree, sizeof(PyListObject)); @@ -136,8 +144,7 @@ PyList_New(Py_ssize_t size) return NULL; } - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_list_state *state = &interp->list; + struct _Py_list_state *state = get_list_state(); PyListObject *op; #ifdef Py_DEBUG // PyList_New() must not be called after _PyList_Fini() @@ -336,8 +343,7 @@ list_dealloc(PyListObject *op) } PyMem_FREE(op->ob_item); } - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_list_state *state = &interp->list; + struct _Py_list_state *state = get_list_state(); #ifdef Py_DEBUG // list_dealloc() must not be called after _PyList_Fini() assert(state->numfree != -1); diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index f97a570..e8af623 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -113,27 +113,35 @@ void _PySlice_Fini(PyThreadState *tstate) PyObject * PySlice_New(PyObject *start, PyObject *stop, PyObject *step) { + if (step == NULL) { + step = Py_None; + } + if (start == NULL) { + start = Py_None; + } + if (stop == NULL) { + stop = Py_None; + } + PyInterpreterState *interp = _PyInterpreterState_GET(); PySliceObject *obj; if (interp->slice_cache != NULL) { obj = interp->slice_cache; interp->slice_cache = NULL; _Py_NewReference((PyObject *)obj); - } else { + } + else { obj = PyObject_GC_New(PySliceObject, &PySlice_Type); - if (obj == NULL) + if (obj == NULL) { return NULL; + } } - if (step == NULL) step = Py_None; Py_INCREF(step); - if (start == NULL) start = Py_None; - Py_INCREF(start); - if (stop == NULL) stop = Py_None; - Py_INCREF(stop); - obj->step = step; + Py_INCREF(start); obj->start = start; + Py_INCREF(stop); obj->stop = stop; _PyObject_GC_TRACK(obj); diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 2ff4c48..f4f9aa2 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -14,19 +14,28 @@ class tuple "PyTupleObject *" "&PyTuple_Type" #include "clinic/tupleobject.c.h" + +static struct _Py_tuple_state * +get_tuple_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->tuple; +} + + static inline void tuple_gc_track(PyTupleObject *op) { _PyObject_GC_TRACK(op); } + /* Print summary info about the state of the optimized allocator */ void _PyTuple_DebugMallocStats(FILE *out) { #if PyTuple_MAXSAVESIZE > 0 - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_tuple_state *state = &interp->tuple; + struct _Py_tuple_state *state = get_tuple_state(); for (int i = 1; i < PyTuple_MAXSAVESIZE; i++) { char buf[128]; PyOS_snprintf(buf, sizeof(buf), @@ -89,8 +98,7 @@ PyTuple_New(Py_ssize_t size) { PyTupleObject *op; #if PyTuple_MAXSAVESIZE > 0 - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_tuple_state *state = &interp->tuple; + struct _Py_tuple_state *state = get_tuple_state(); if (size == 0 && state->free_list[0]) { op = state->free_list[0]; Py_INCREF(op); @@ -198,8 +206,7 @@ PyTuple_Pack(Py_ssize_t n, ...) return PyTuple_New(0); } - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_tuple_state *state = &interp->tuple; + struct _Py_tuple_state *state = get_tuple_state(); va_start(vargs, n); PyTupleObject *result = tuple_alloc(state, n); @@ -233,8 +240,7 @@ tupledealloc(PyTupleObject *op) Py_XDECREF(op->ob_item[i]); } #if PyTuple_MAXSAVESIZE > 0 - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_tuple_state *state = &interp->tuple; + struct _Py_tuple_state *state = get_tuple_state(); #ifdef Py_DEBUG // tupledealloc() must not be called after _PyTuple_Fini() assert(state->numfree[0] != -1); @@ -420,8 +426,7 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) return PyTuple_New(0); } - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_tuple_state *state = &interp->tuple; + struct _Py_tuple_state *state = get_tuple_state(); PyTupleObject *tuple = tuple_alloc(state, n); if (tuple == NULL) { return NULL; @@ -492,8 +497,7 @@ tupleconcat(PyTupleObject *a, PyObject *bb) return PyTuple_New(0); } - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_tuple_state *state = &interp->tuple; + struct _Py_tuple_state *state = get_tuple_state(); np = tuple_alloc(state, size); if (np == NULL) { return NULL; @@ -537,8 +541,7 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) if (n > PY_SSIZE_T_MAX / Py_SIZE(a)) return PyErr_NoMemory(); size = Py_SIZE(a) * n; - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_tuple_state *state = &interp->tuple; + struct _Py_tuple_state *state = get_tuple_state(); np = tuple_alloc(state, size); if (np == NULL) return NULL; @@ -804,8 +807,7 @@ tuplesubscript(PyTupleObject* self, PyObject* item) return (PyObject *)self; } else { - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_tuple_state *state = &interp->tuple; + struct _Py_tuple_state *state = get_tuple_state(); PyTupleObject* result = tuple_alloc(state, slicelength); if (!result) return NULL; diff --git a/Python/context.c b/Python/context.c index dedbca9..dc34071 100644 --- a/Python/context.c +++ b/Python/context.c @@ -66,6 +66,14 @@ static int contextvar_del(PyContextVar *var); +static struct _Py_context_state * +get_context_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->context; +} + + PyObject * _PyContext_NewHamtForTests(void) { @@ -332,8 +340,7 @@ class _contextvars.Context "PyContext *" "&PyContext_Type" static inline PyContext * _context_alloc(void) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_context_state *state = &interp->context; + struct _Py_context_state *state = get_context_state(); PyContext *ctx; #ifdef Py_DEBUG // _context_alloc() must not be called after _PyContext_Fini() @@ -462,8 +469,7 @@ context_tp_dealloc(PyContext *self) } (void)context_tp_clear(self); - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_context_state *state = &interp->context; + struct _Py_context_state *state = get_context_state(); #ifdef Py_DEBUG // _context_alloc() must not be called after _PyContext_Fini() assert(state->numfree != -1); -- cgit v0.12