@@ -8,144 +8,109 @@ extern "C" {
88# error "this header requires Py_BUILD_CORE define"
99#endif
1010
11- // PyTuple_MAXSAVESIZE - largest tuple to save on free list
12- // PyTuple_MAXFREELIST - maximum number of tuples of each size to save
13-
14- #ifdef WITH_FREELISTS
15- // with freelists
16- # define PyTuple_MAXSAVESIZE 20
17- # define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE
18- # define PyTuple_MAXFREELIST 2000
19- # define PyList_MAXFREELIST 80
20- # define PyDict_MAXFREELIST 80
21- # define PyFloat_MAXFREELIST 100
22- # define PyContext_MAXFREELIST 255
23- # define _PyAsyncGen_MAXFREELIST 80
24- # define _PyObjectStackChunk_MAXFREELIST 4
25- #else
26- # define PyTuple_NFREELISTS 0
27- # define PyTuple_MAXFREELIST 0
28- # define PyList_MAXFREELIST 0
29- # define PyDict_MAXFREELIST 0
30- # define PyFloat_MAXFREELIST 0
31- # define PyContext_MAXFREELIST 0
32- # define _PyAsyncGen_MAXFREELIST 0
33- # define _PyObjectStackChunk_MAXFREELIST 0
34- #endif
35-
36- struct _Py_list_freelist {
37- #ifdef WITH_FREELISTS
38- PyListObject * items [PyList_MAXFREELIST ];
39- int numfree ;
11+ #include "pycore_freelist_state.h" // struct _Py_freelists
12+ #include "pycore_object.h" // _PyObject_IS_GC
13+ #include "pycore_pystate.h" // _PyThreadState_GET
14+ #include "pycore_code.h" // OBJECT_STAT_INC
15+
16+ static inline struct _Py_freelists *
17+ _Py_freelists_GET (void )
18+ {
19+ PyThreadState * tstate = _PyThreadState_GET ();
20+ #ifdef Py_DEBUG
21+ _Py_EnsureTstateNotNULL (tstate );
4022#endif
41- };
42-
43- struct _Py_tuple_freelist {
44- #if WITH_FREELISTS
45- /* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE.
46- The empty tuple is handled separately.
4723
48- Each tuple stored in the array is the head of the linked list
49- (and the next available tuple) for that size. The actual tuple
50- object is used as the linked list node, with its first item
51- (ob_item[0]) pointing to the next node (i.e. the previous head).
52- Each linked list is initially NULL. */
53- PyTupleObject * items [PyTuple_NFREELISTS ];
54- int numfree [PyTuple_NFREELISTS ];
24+ #ifdef Py_GIL_DISABLED
25+ return & ((_PyThreadStateImpl * )tstate )-> freelists ;
5526#else
56- char _unused ; // Empty structs are not allowed.
57- #endif
58- };
59-
60- struct _Py_float_freelist {
61- #ifdef WITH_FREELISTS
62- /* Special free list
63- free_list is a singly-linked list of available PyFloatObjects,
64- linked via abuse of their ob_type members. */
65- int numfree ;
66- PyFloatObject * items ;
67- #endif
68- };
69-
70- struct _Py_dict_freelist {
71- #ifdef WITH_FREELISTS
72- /* Dictionary reuse scheme to save calls to malloc and free */
73- PyDictObject * items [PyDict_MAXFREELIST ];
74- int numfree ;
27+ return & tstate -> interp -> object_state .freelists ;
7528#endif
76- };
29+ }
7730
78- struct _Py_dictkeys_freelist {
79- #ifdef WITH_FREELISTS
80- /* Dictionary keys reuse scheme to save calls to malloc and free */
81- PyDictKeysObject * items [PyDict_MAXFREELIST ];
82- int numfree ;
83- #endif
84- };
31+ #ifndef WITH_FREELISTS
32+ #define _Py_FREELIST_FREE (NAME , op , freefunc ) freefunc(op)
33+ #define _Py_FREELIST_PUSH (NAME , op , limit ) (0)
34+ #define _Py_FREELIST_POP (TYPE , NAME ) (NULL)
35+ #define _Py_FREELIST_POP_MEM (NAME ) (NULL)
36+ #define _Py_FREELIST_SIZE (NAME ) (0)
37+ #else
38+ // Pushes `op` to the freelist, calls `freefunc` if the freelist is full
39+ #define _Py_FREELIST_FREE (NAME , op , freefunc ) \
40+ _PyFreeList_Free(&_Py_freelists_GET()->NAME, _PyObject_CAST(op), \
41+ Py_ ## NAME ## _MAXFREELIST, freefunc)
42+ // Pushes `op` to the freelist, returns 1 if successful, 0 if the freelist is full
43+ #define _Py_FREELIST_PUSH (NAME , op , limit ) \
44+ _PyFreeList_Push(&_Py_freelists_GET()->NAME, _PyObject_CAST(op), limit)
45+
46+ // Pops a PyObject from the freelist, returns NULL if the freelist is empty.
47+ #define _Py_FREELIST_POP (TYPE , NAME ) \
48+ _Py_CAST(TYPE*, _PyFreeList_Pop(&_Py_freelists_GET()->NAME))
49+
50+ // Pops a non-PyObject data structure from the freelist, returns NULL if the
51+ // freelist is empty.
52+ #define _Py_FREELIST_POP_MEM (NAME ) \
53+ _PyFreeList_PopMem(&_Py_freelists_GET()->NAME)
54+
55+ #define _Py_FREELIST_SIZE (NAME ) (int)((_Py_freelists_GET()->NAME).size)
56+
57+ static inline int
58+ _PyFreeList_Push (struct _Py_freelist * fl , void * obj , Py_ssize_t maxsize )
59+ {
60+ if (fl -> size < maxsize && fl -> size >= 0 ) {
61+ * (void * * )obj = fl -> freelist ;
62+ fl -> freelist = obj ;
63+ fl -> size ++ ;
64+ OBJECT_STAT_INC (to_freelist );
65+ return 1 ;
66+ }
67+ return 0 ;
68+ }
8569
86- struct _Py_slice_freelist {
87- #ifdef WITH_FREELISTS
88- /* Using a cache is very effective since typically only a single slice is
89- created and then deleted again. */
90- PySliceObject * slice_cache ;
91- #endif
92- };
70+ static inline void
71+ _PyFreeList_Free (struct _Py_freelist * fl , void * obj , Py_ssize_t maxsize ,
72+ freefunc dofree )
73+ {
74+ if (!_PyFreeList_Push (fl , obj , maxsize )) {
75+ dofree (obj );
76+ }
77+ }
9378
94- struct _Py_context_freelist {
95- #ifdef WITH_FREELISTS
96- // List of free PyContext objects
97- PyContext * items ;
98- int numfree ;
99- #endif
100- };
79+ static inline void *
80+ _PyFreeList_PopNoStats (struct _Py_freelist * fl )
81+ {
82+ void * obj = fl -> freelist ;
83+ if (obj != NULL ) {
84+ assert (fl -> size > 0 );
85+ fl -> freelist = * (void * * )obj ;
86+ fl -> size -- ;
87+ }
88+ return obj ;
89+ }
10190
102- struct _Py_async_gen_freelist {
103- #ifdef WITH_FREELISTS
104- /* Freelists boost performance 6-10%; they also reduce memory
105- fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend
106- are short-living objects that are instantiated for every
107- __anext__() call. */
108- struct _PyAsyncGenWrappedValue * items [ _PyAsyncGen_MAXFREELIST ] ;
109- int numfree ;
110- #endif
111- };
91+ static inline PyObject *
92+ _PyFreeList_Pop ( struct _Py_freelist * fl )
93+ {
94+ PyObject * op = _PyFreeList_PopNoStats ( fl );
95+ if ( op != NULL ) {
96+ OBJECT_STAT_INC ( from_freelist );
97+ _Py_NewReference ( op ) ;
98+ }
99+ return op ;
100+ }
112101
113- struct _Py_async_gen_asend_freelist {
114- #ifdef WITH_FREELISTS
115- struct PyAsyncGenASend * items [_PyAsyncGen_MAXFREELIST ];
116- int numfree ;
102+ static inline void *
103+ _PyFreeList_PopMem (struct _Py_freelist * fl )
104+ {
105+ void * op = _PyFreeList_PopNoStats (fl );
106+ if (op != NULL ) {
107+ OBJECT_STAT_INC (from_freelist );
108+ }
109+ return op ;
110+ }
117111#endif
118- };
119-
120- struct _PyObjectStackChunk ;
121-
122- struct _Py_object_stack_freelist {
123- struct _PyObjectStackChunk * items ;
124- Py_ssize_t numfree ;
125- };
126-
127- struct _Py_object_freelists {
128- struct _Py_float_freelist floats ;
129- struct _Py_tuple_freelist tuples ;
130- struct _Py_list_freelist lists ;
131- struct _Py_dict_freelist dicts ;
132- struct _Py_dictkeys_freelist dictkeys ;
133- struct _Py_slice_freelist slices ;
134- struct _Py_context_freelist contexts ;
135- struct _Py_async_gen_freelist async_gens ;
136- struct _Py_async_gen_asend_freelist async_gen_asends ;
137- struct _Py_object_stack_freelist object_stacks ;
138- };
139112
140- extern void _PyObject_ClearFreeLists (struct _Py_object_freelists * freelists , int is_finalization );
141- extern void _PyTuple_ClearFreeList (struct _Py_object_freelists * freelists , int is_finalization );
142- extern void _PyFloat_ClearFreeList (struct _Py_object_freelists * freelists , int is_finalization );
143- extern void _PyList_ClearFreeList (struct _Py_object_freelists * freelists , int is_finalization );
144- extern void _PySlice_ClearFreeList (struct _Py_object_freelists * freelists , int is_finalization );
145- extern void _PyDict_ClearFreeList (struct _Py_object_freelists * freelists , int is_finalization );
146- extern void _PyAsyncGen_ClearFreeLists (struct _Py_object_freelists * freelists , int is_finalization );
147- extern void _PyContext_ClearFreeList (struct _Py_object_freelists * freelists , int is_finalization );
148- extern void _PyObjectStackChunk_ClearFreeList (struct _Py_object_freelists * freelists , int is_finalization );
113+ extern void _PyObject_ClearFreeLists (struct _Py_freelists * freelists , int is_finalization );
149114
150115#ifdef __cplusplus
151116}
0 commit comments