summaryrefslogtreecommitdiffstats
path: root/Objects/listobject.c
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-07-22 16:08:27 (GMT)
committerGitHub <noreply@github.com>2024-07-22 16:08:27 (GMT)
commit5716cc352940a5f8557a8191e873837aa619498a (patch)
treea9b1526a46acfe002950b9ad0d046f03c7cab5e9 /Objects/listobject.c
parent2408a8a22bd13d8f15172a2ecf8bbbc4355dcb3b (diff)
downloadcpython-5716cc352940a5f8557a8191e873837aa619498a.zip
cpython-5716cc352940a5f8557a8191e873837aa619498a.tar.gz
cpython-5716cc352940a5f8557a8191e873837aa619498a.tar.bz2
gh-100240: Use a consistent implementation for freelists (#121934)
This combines and updates our freelist handling to use a consistent implementation. Objects in the freelist are linked together using the first word of memory block. If configured with freelists disabled, these operations are essentially no-ops.
Diffstat (limited to 'Objects/listobject.c')
-rw-r--r--Objects/listobject.c59
1 files changed, 9 insertions, 50 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c
index f29f58d..4d654c2 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -4,6 +4,7 @@
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
#include "pycore_dict.h" // _PyDictViewObject
+#include "pycore_freelist.h" // _Py_FREELIST_FREE(), _Py_FREELIST_POP()
#include "pycore_pyatomic_ft_wrappers.h"
#include "pycore_interp.h" // PyInterpreterState.list
#include "pycore_list.h" // struct _Py_list_freelist, _PyListIterObject
@@ -23,16 +24,6 @@ class list "PyListObject *" "&PyList_Type"
_Py_DECLARE_STR(list_err, "list index out of range");
-#ifdef WITH_FREELISTS
-static struct _Py_list_freelist *
-get_list_freelist(void)
-{
- struct _Py_object_freelists *freelists = _Py_object_freelists_GET();
- assert(freelists != NULL);
- return &freelists->lists;
-}
-#endif
-
#ifdef Py_GIL_DISABLED
typedef struct {
Py_ssize_t allocated;
@@ -205,55 +196,28 @@ list_preallocate_exact(PyListObject *self, Py_ssize_t size)
return 0;
}
-void
-_PyList_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization)
-{
-#ifdef WITH_FREELISTS
- struct _Py_list_freelist *state = &freelists->lists;
- while (state->numfree > 0) {
- PyListObject *op = state->items[--state->numfree];
- assert(PyList_CheckExact(op));
- PyObject_GC_Del(op);
- }
- if (is_finalization) {
- state->numfree = -1;
- }
-#endif
-}
-
/* Print summary info about the state of the optimized allocator */
void
_PyList_DebugMallocStats(FILE *out)
{
#ifdef WITH_FREELISTS
- struct _Py_list_freelist *list_freelist = get_list_freelist();
_PyDebugAllocatorStats(out,
"free PyListObject",
- list_freelist->numfree, sizeof(PyListObject));
+ _Py_FREELIST_SIZE(lists),
+ sizeof(PyListObject));
#endif
}
PyObject *
PyList_New(Py_ssize_t size)
{
- PyListObject *op;
-
if (size < 0) {
PyErr_BadInternalCall();
return NULL;
}
-#ifdef WITH_FREELISTS
- struct _Py_list_freelist *list_freelist = get_list_freelist();
- if (PyList_MAXFREELIST && list_freelist->numfree > 0) {
- list_freelist->numfree--;
- op = list_freelist->items[list_freelist->numfree];
- OBJECT_STAT_INC(from_freelist);
- _Py_NewReference((PyObject *)op);
- }
- else
-#endif
- {
+ PyListObject *op = _Py_FREELIST_POP(PyListObject, lists);
+ if (op == NULL) {
op = PyObject_GC_New(PyListObject, &PyList_Type);
if (op == NULL) {
return NULL;
@@ -548,16 +512,11 @@ list_dealloc(PyObject *self)
}
free_list_items(op->ob_item, false);
}
-#ifdef WITH_FREELISTS
- struct _Py_list_freelist *list_freelist = get_list_freelist();
- if (list_freelist->numfree < PyList_MAXFREELIST && list_freelist->numfree >= 0 && PyList_CheckExact(op)) {
- list_freelist->items[list_freelist->numfree++] = op;
- OBJECT_STAT_INC(to_freelist);
+ if (PyList_CheckExact(op)) {
+ _Py_FREELIST_FREE(lists, op, PyObject_GC_Del);
}
- else
-#endif
- {
- Py_TYPE(op)->tp_free((PyObject *)op);
+ else {
+ PyObject_GC_Del(op);
}
Py_TRASHCAN_END
}