[Python-checkins] bpo-40521: Cleanup code of free lists (GH-21082)

Victor Stinner webhook-mailer at python.org
Tue Jun 23 10:40:50 EDT 2020


https://github.com/python/cpython/commit/522691c46e2ae51faaad5bbbce7d959dd61770df
commit: 522691c46e2ae51faaad5bbbce7d959dd61770df
branch: master
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2020-06-23T16:40:40+02:00
summary:

bpo-40521: Cleanup code of free lists (GH-21082)

Add get_xxx_state() function to factorize duplicated code.

files:
M Objects/dictobject.c
M Objects/floatobject.c
M Objects/frameobject.c
M Objects/genobject.c
M Objects/listobject.c
M Objects/sliceobject.c
M Objects/tupleobject.c
M Python/context.c

diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index f3b1157177655..b1f11b3e695bb 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 7ffd7eebe5a45..0606f29ff5408 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 6e1cbcfaf6f51..7c2bce3615860 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 4207d5326cca1..6a68c9484a6ae 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 261a0fdfffae0..ab036154eacc2 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 f97a570a787f0..e8af623142b84 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 2ff4c48111fe0..f4f9aa259e8b2 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 dedbca99384c7..dc34071884750 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);



More information about the Python-checkins mailing list