Skip to content

gh-126703: Add freelists for iterators and range, method and builtin_function_or_method objects #128368

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

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Prev Previous commit
Next Next commit
set types
  • Loading branch information
eendebakpt committed Dec 29, 2024
commit 17100c09debfa6aadc1ac5e747aa16a96688c74c
1 change: 1 addition & 0 deletions Include/internal/pycore_freelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ _Py_freelists_GET(void)
#define _Py_FREELIST_POP(TYPE, NAME) \
_Py_CAST(TYPE*, _PyFreeList_Pop(&_Py_freelists_GET()->NAME))


// Pops a non-PyObject data structure from the freelist, returns NULL if the
// freelist is empty.
#define _Py_FREELIST_POP_MEM(NAME) \
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_freelist_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extern "C" {
# define Py_ints_MAXFREELIST 100
# define Py_slices_MAXFREELIST 1
# define Py_ranges_MAXFREELIST 10
# define Py_rangeiters_MAXFREELIST 10
# define Py_shared_iters_MAXFREELIST 24
# define Py_contexts_MAXFREELIST 255
# define Py_async_gens_MAXFREELIST 80
# define Py_async_gen_asends_MAXFREELIST 80
Expand Down Expand Up @@ -45,7 +45,7 @@ struct _Py_freelists {
struct _Py_freelist dictkeys;
struct _Py_freelist slices;
struct _Py_freelist ranges;
struct _Py_freelist rangeiters;
struct _Py_freelist shared_iters;
struct _Py_freelist contexts;
struct _Py_freelist async_gens;
struct _Py_freelist async_gen_asends;
Expand Down
16 changes: 10 additions & 6 deletions Objects/listobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3910,15 +3910,19 @@ PyTypeObject PyListIter_Type = {
static PyObject *
list_iter(PyObject *seq)
{
_PyListIterObject *it;

if (!PyList_Check(seq)) {
PyErr_BadInternalCall();
return NULL;
}
it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type);
if (it == NULL)
return NULL;
_PyListIterObject *it = _Py_FREELIST_POP(_PyListIterObject, shared_iters);
if (it == NULL) {
it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type);
if (it == NULL) {
return NULL;
}
} else {
Py_SET_TYPE(it, &PyListIter_Type);
}
it->it_index = 0;
it->it_seq = (PyListObject *)Py_NewRef(seq);
_PyObject_GC_TRACK(it);
Expand All @@ -3931,7 +3935,7 @@ listiter_dealloc(PyObject *self)
_PyListIterObject *it = (_PyListIterObject *)self;
_PyObject_GC_UNTRACK(it);
Py_XDECREF(it->it_seq);
PyObject_GC_Del(it);
_Py_FREELIST_FREE(shared_iters, it, PyObject_GC_Del);
}

static int
Expand Down
7 changes: 5 additions & 2 deletions Objects/rangeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,7 @@ rangeiter_setstate(_PyRangeIterObject *r, PyObject *state)
static void
rangeiter_dealloc(_PyRangeIterObject *r)
{
_Py_FREELIST_FREE(rangeiters, r, PyObject_Free);
_Py_FREELIST_FREE(shared_iters, r, PyObject_Free);
}

PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
Expand Down Expand Up @@ -969,12 +969,15 @@ get_len_of_range(long lo, long hi, long step)
static PyObject *
fast_range_iter(long start, long stop, long step, long len)
{
_PyRangeIterObject *it = _Py_FREELIST_POP(_PyRangeIterObject, rangeiters);
_PyRangeIterObject *it = _Py_FREELIST_POP(_PyRangeIterObject, shared_iters);
if (it == NULL) {
it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type);
if (it == NULL)
return NULL;
}
else {
Py_SET_TYPE(it, &PyRangeIter_Type);
}
it->start = start;
it->step = step;
it->len = len;
Expand Down
15 changes: 11 additions & 4 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,8 @@ tupleiter_dealloc(_PyTupleIterObject *it)
{
_PyObject_GC_UNTRACK(it);
Py_XDECREF(it->it_seq);
PyObject_GC_Del(it);
assert(sizeof(_PyTupleIterObject)==sizeof(_PyListIterObject));
_Py_FREELIST_FREE(shared_iters, it, PyObject_GC_Del);
}

static int
Expand Down Expand Up @@ -1122,9 +1123,15 @@ tuple_iter(PyObject *seq)
PyErr_BadInternalCall();
return NULL;
}
it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type);
if (it == NULL)
return NULL;
it = _Py_FREELIST_POP(_PyTupleIterObject, shared_iters);

if (it == NULL) {
it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type);
if (it == NULL)
return NULL;
} else {
Py_SET_TYPE(it, &PyTupleIter_Type);
}
it->it_index = 0;
it->it_seq = (PyTupleObject *)Py_NewRef(seq);
_PyObject_GC_TRACK(it);
Expand Down
1 change: 1 addition & 0 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "pycore_code.h" // CO_FAST_FREE
#include "pycore_dict.h" // _PyDict_KeysSize()
#include "pycore_frame.h" // _PyInterpreterFrame
#include "pycore_freelist.h" // _Py_FREELIST_FREE(), _Py_FREELIST_POP()
#include "pycore_lock.h" // _PySeqLock_*
#include "pycore_long.h" // _PyLong_IsNegative(), _PyLong_GetOne()
#include "pycore_memoryobject.h" // _PyMemoryView_FromBufferProc()
Expand Down