Nuitka
The Python compiler
Loading...
Searching...
No Matches
freelists.h
1// Copyright 2026, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3#ifndef __NUITKA_FREELISTS_H__
4#define __NUITKA_FREELISTS_H__
5
6#ifndef __cplusplus
7#include <stdbool.h>
8#endif
9
10#ifdef _NUITKA_EXPERIMENTAL_DISABLE_FREELIST_ALL
11static const bool use_freelists = false;
12#else
13static const bool use_freelists = true;
14#endif
15
16#define allocateFromFreeList(free_list, object_type, type_type, size) \
17 if (free_list != NULL) { \
18 result = free_list; \
19 free_list = *((object_type **)free_list); \
20 free_list##_count -= 1; \
21 assert(free_list##_count >= 0); \
22 \
23 if (Py_SIZE(result) < size) { \
24 result = PyObject_GC_Resize(object_type, result, size); \
25 assert(result != NULL); \
26 } \
27 \
28 Nuitka_Py_NewReference((PyObject *)result); \
29 } else { \
30 result = (object_type *)Nuitka_GC_NewVar(&type_type, size); \
31 } \
32 CHECK_OBJECT(result);
33
34#define allocateFromFreeListFixed(free_list, object_type, type_type) \
35 if (free_list != NULL) { \
36 result = free_list; \
37 free_list = *((object_type **)free_list); \
38 free_list##_count -= 1; \
39 assert(free_list##_count >= 0); \
40 \
41 Nuitka_Py_NewReference((PyObject *)result); \
42 } else { \
43 result = (object_type *)Nuitka_GC_New(&type_type); \
44 } \
45 CHECK_OBJECT(result);
46
47#define releaseToFreeList(free_list, object, max_free_list_count) \
48 if (free_list != NULL || max_free_list_count == 0 || use_freelists == false) { \
49 if (free_list##_count >= max_free_list_count) { \
50 PyObject_GC_Del(object); \
51 } else { \
52 *((void **)object) = (void *)free_list; \
53 free_list = object; \
54 \
55 free_list##_count += 1; \
56 } \
57 } else { \
58 free_list = object; \
59 *((void **)object) = NULL; \
60 \
61 assert(free_list##_count == 0); \
62 \
63 free_list##_count += 1; \
64 }
65
66#if PYTHON_VERSION >= 0x3d0
67
68#if PYTHON_VERSION >= 0x3e0
69
70// CPython 3.14 changed the layout before post-QSBR interpreter fields in
71// 3.14.4 and again in 3.14.5.
72static inline struct _Py_freelists *Nuitka_Py_freelists_GET(PyThreadState *tstate) {
73#ifdef Py_GIL_DISABLED
74 return &((_PyThreadStateImpl *)tstate)->freelists;
75#else
76#if _NUITKA_MODULE_MODE && PYTHON_VERSION < 0x3f0
77 return (struct _Py_freelists *)Nuitka_PyInterpreterState_AdjustPostQsbrPointer(
78 &tstate->interp->object_state.freelists);
79#else
80 return &tstate->interp->object_state.freelists;
81#endif
82#endif
83}
84
85// Like _PyFreeList_Pop but doesn't set the reference, may also be totally
86// unnecessary to have.
87static inline PyObject *Nuitka_PyFreeList_Pop(struct _Py_freelist *freelist) {
88 return _PyFreeList_PopNoStats(freelist);
89}
90
91#else
92
93NUITKA_MAY_BE_UNUSED static inline struct _Py_object_freelists *_Nuitka_object_freelists_GET(PyThreadState *tstate) {
94
95#ifdef Py_GIL_DISABLED
96 return &((_PyThreadStateImpl *)tstate)->freelists;
97#else
98 return &tstate->interp->object_state.freelists;
99#endif
100}
101#endif
102
103#endif
104
105#endif
106
107// Part of "Nuitka", an optimizing Python compiler that is compatible and
108// integrates with CPython, but also works on its own.
109//
110// Licensed under the GNU Affero General Public License, Version 3 (the "License");
111// you may not use this file except in compliance with the License.
112// You may obtain a copy of the License at
113//
114// http://www.gnu.org/licenses/agpl.txt
115//
116// Unless required by applicable law or agreed to in writing, software
117// distributed under the License is distributed on an "AS IS" BASIS,
118// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119// See the License for the specific language governing permissions and
120// limitations under the License.