3#ifndef __NUITKA_ALLOCATOR_H__
4#define __NUITKA_ALLOCATOR_H__
8#include "nuitka/prelude.h"
12#if PYTHON_VERSION < 0x270 && !defined(_PyObject_GC_IS_TRACKED)
13#define _PyObject_GC_IS_TRACKED(obj) (1)
17#if PYTHON_VERSION >= 0x350 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_ALLOCATORS)
18extern void *(*python_obj_malloc)(
void *ctx,
size_t size);
19extern void *(*python_mem_malloc)(
void *ctx,
size_t size);
20extern void *(*python_mem_calloc)(
void *ctx,
size_t nelem,
size_t elsize);
21#ifndef Py_GIL_DISABLED
22extern void *(*python_mem_realloc)(
void *ctx,
void *ptr,
size_t new_size);
24extern void (*python_mem_free)(
void *ctx,
void *ptr);
28extern void *python_obj_ctx;
29extern void *python_mem_ctx;
31#define python_obj_ctx (NULL)
32#define python_mem_ctx (NULL)
35extern void initNuitkaAllocators(
void);
38NUITKA_MAY_BE_UNUSED
static void *NuitkaObject_Malloc(
size_t size) {
return python_obj_malloc(python_obj_ctx, size); }
41NUITKA_MAY_BE_UNUSED
static void *NuitkaMem_Malloc(
size_t size) {
return python_mem_malloc(python_mem_ctx, size); }
44NUITKA_MAY_BE_UNUSED
static void *NuitkaMem_Calloc(
size_t nelem,
size_t elsize) {
45 return python_mem_calloc(python_mem_ctx, nelem, elsize);
48#ifndef Py_GIL_DISABLED
50NUITKA_MAY_BE_UNUSED
static void *NuitkaMem_Realloc(
void *ptr,
size_t new_size) {
51 return python_mem_realloc(python_mem_ctx, ptr, new_size);
54NUITKA_MAY_BE_UNUSED
static void NuitkaMem_Free(
void *ptr) { python_mem_free(python_mem_ctx, ptr); }
58#define NuitkaObject_Malloc(size) PyObject_MALLOC(size)
59#define NuitkaMem_Malloc(size) PyMem_MALLOC(size)
60#define NuitkaMem_Calloc(elem, elsize) PyMem_Calloc(elem, elsize)
61#ifndef Py_GIL_DISABLED
66#define NuitkaMem_Realloc(ptr, new_size) PyMem_Realloc(ptr, new_size)
68#define NuitkaMem_Realloc(ptr, new_size) PyMem_REALLOC(ptr, new_size)
71#define NuitkaMem_Free(ptr) PyMem_Free(ptr)
75#if PYTHON_VERSION >= 0x380 && PYTHON_VERSION < 0x3c0
77static inline void _Nuitka_Py_DECREF(PyObject *ob) {
78 assert(ob != NULL && ob->ob_refcnt >= 0);
85 if (--ob->ob_refcnt == 0) {
86 destructor dealloc = Py_TYPE(ob)->tp_dealloc;
88 _Py_ForgetReference(ob);
95#define Py_DECREF(ob) _Nuitka_Py_DECREF((PyObject *)(ob))
98static inline void _Nuitka_Py_XDECREF(PyObject *ob) {
100 assert(ob->ob_refcnt >= 0);
107 if (--ob->ob_refcnt == 0) {
108 destructor dealloc = Py_TYPE(ob)->tp_dealloc;
110 _Py_ForgetReference(ob);
118#define Py_XDECREF(ob) _Nuitka_Py_XDECREF((PyObject *)(ob))
122#define Py_CLEAR(op) \
124 PyObject *_py_tmp = (PyObject *)(op); \
125 if (_py_tmp != NULL) { \
127 Py_DECREF(_py_tmp); \
131#elif PYTHON_VERSION >= 0x3c0 && defined(_WIN32) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && \
132 !defined(Py_GIL_DISABLED) && !defined(_NUITKA_EXPERIMENTAL_DISABLE_PY_DECREF_OVERRIDE)
135#define Py_DECREF(arg) \
137 PyObject *op = _PyObject_CAST(arg); \
138 if (_Py_IsImmortal(op)) { \
141 _Py_DECREF_STAT_INC(); \
142 if (--op->ob_refcnt == 0) { \
143 destructor dealloc = Py_TYPE(op)->tp_dealloc; \
149#define Py_XDECREF(arg) \
151 PyObject *xop = _PyObject_CAST(arg); \
158#define Py_IS_TYPE(ob, type) (_PyObject_CAST(ob)->ob_type == (type))
160#undef _Py_DECREF_SPECIALIZED
161#define _Py_DECREF_SPECIALIZED(arg, dealloc) \
163 PyObject *op = _PyObject_CAST(arg); \
164 if (_Py_IsImmortal(op)) { \
167 _Py_DECREF_STAT_INC(); \
168 if (--op->ob_refcnt == 0) { \
169 destructor d = (destructor)(dealloc); \
176#if PYTHON_VERSION < 0x3c0
177#define Py_INCREF_IMMORTAL(value) Py_INCREF(value)
178#define Py_DECREF_IMMORTAL(value) Py_DECREF(value)
179#elif defined(_NUITKA_DEBUG_DEBUG_IMMORTAL)
180#define Py_INCREF_IMMORTAL(value) assert(Py_REFCNT(value) == _Py_IMMORTAL_REFCNT)
181#define Py_DECREF_IMMORTAL(value) assert(Py_REFCNT(value) == _Py_IMMORTAL_REFCNT)
183#define Py_INCREF_IMMORTAL(value)
184#define Py_DECREF_IMMORTAL(value)
189static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) { ob->ob_type = type; }
190#define Py_SET_TYPE(ob, type) _Py_SET_TYPE((PyObject *)(ob), type)
195#if PYTHON_VERSION >= 0x390
196static inline void Nuitka_Py_NewReferenceNoTotal(PyObject *op) { Py_SET_REFCNT(op, 1); }
197static inline void Nuitka_Py_NewReference(PyObject *op) {
199#if PYTHON_VERSION < 0x3c0
203 _PyInterpreterState_GET()->object_state.reftotal++;
206#if !defined(Py_GIL_DISABLED)
209 op->ob_tid = _Py_ThreadId();
211 op->ob_mutex = (PyMutex){0};
213 op->ob_ref_local = 1;
214 op->ob_ref_shared = 0;
218#define Nuitka_Py_NewReference(op) _Py_NewReference(op)
221static inline int Nuitka_PyType_HasFeature(PyTypeObject *type,
unsigned long feature) {
222 return ((type->tp_flags & feature) != 0);
225#if PYTHON_VERSION >= 0x3b0
227static inline size_t Nuitka_PyType_PreHeaderSize(PyTypeObject *tp) {
228 return _PyType_IS_GC(tp) *
sizeof(PyGC_Head) +
229 Nuitka_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT) * 2 *
sizeof(PyObject *);
232extern void Nuitka_PyObject_GC_Link(PyObject *op);
234static PyObject *Nuitka_PyType_AllocNoTrackVar(PyTypeObject *type, Py_ssize_t nitems) {
236 const size_t size = _PyObject_VAR_SIZE(type, nitems + 1);
239 const size_t pre_size = Nuitka_PyType_PreHeaderSize(type);
240 assert(pre_size ==
sizeof(PyGC_Head));
242 char *alloc = (
char *)NuitkaObject_Malloc(size + pre_size);
244 PyObject *obj = (PyObject *)(alloc + pre_size);
248 ((PyObject **)alloc)[0] = NULL;
249 ((PyObject **)alloc)[1] = NULL;
251 Nuitka_PyObject_GC_Link(obj);
256 memset(obj, 0, size);
259 assert(type->tp_itemsize != 0);
260 Py_SET_SIZE((PyVarObject *)obj, nitems);
263 Py_SET_TYPE(obj, type);
264 if (Nuitka_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
268 Nuitka_Py_NewReference(obj);
273static PyObject *Nuitka_PyType_AllocNoTrack(PyTypeObject *type) {
275 const size_t pre_size = Nuitka_PyType_PreHeaderSize(type);
277 char *alloc = (
char *)NuitkaObject_Malloc(_PyObject_SIZE(type) + pre_size);
279 PyObject *obj = (PyObject *)(alloc + pre_size);
282 ((PyObject **)alloc)[0] = NULL;
283 ((PyObject **)alloc)[1] = NULL;
285 Nuitka_PyObject_GC_Link(obj);
288 Py_SET_TYPE(obj, type);
290 if (Nuitka_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
294 Nuitka_Py_NewReference(obj);
300NUITKA_MAY_BE_UNUSED
static void *Nuitka_GC_NewVar(PyTypeObject *type, Py_ssize_t nitems) {
303#if PYTHON_VERSION < 0x3b0
304 size_t size = _PyObject_VAR_SIZE(type, nitems);
305 PyVarObject *op = (PyVarObject *)_PyObject_GC_Malloc(size);
308 Py_SIZE(op) = nitems;
309 Py_SET_TYPE(op, type);
311#if PYTHON_VERSION >= 0x380
314 if (Nuitka_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
319 Nuitka_Py_NewReference((PyObject *)op);
324 PyObject *op = Nuitka_PyType_AllocNoTrackVar(type, nitems);
326 assert(Py_SIZE(op) == nitems);
330NUITKA_MAY_BE_UNUSED
static void *Nuitka_GC_New(PyTypeObject *type) {
331#if PYTHON_VERSION < 0x3b0
332 size_t size = _PyObject_SIZE(type);
334 PyVarObject *op = (PyVarObject *)_PyObject_GC_Malloc(size);
337 Py_SET_TYPE(op, type);
339#if PYTHON_VERSION >= 0x380
342 if (Nuitka_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
347 Nuitka_Py_NewReference((PyObject *)op);
350 PyObject *op = Nuitka_PyType_AllocNoTrack(type);
355static bool inline Nuitka_GC_IS_TRACKED_X(PyObject *
object) {
356 return object == NULL || _PyObject_GC_IS_TRACKED(
object);
360#if PYTHON_VERSION >= 0x3c0
361static void inline Py_SET_REFCNT_IMMORTAL(PyObject *
object) {
362 assert(
object != NULL);
365 if (_PyObject_IS_GC(
object) && _PyObject_GC_IS_TRACKED(
object)) {
366 Nuitka_GC_UnTrack(
object);
369#ifdef Py_GIL_DISABLED
370 object->ob_tid = _Py_UNOWNED_TID;
371 object->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL;
372 object->ob_ref_shared = 0;
374 object->ob_refcnt = _Py_IMMORTAL_REFCNT;
378#define Py_SET_REFCNT_IMMORTAL(object)
383#define _Py_CAST(type, expr) ((type)(expr))
386#ifndef _PyObject_CAST
387#define _PyObject_CAST(op) _Py_CAST(PyObject *, (op))
392#define Py_SETREF(dst, src) \
394 _Py_TYPEOF(dst) *_tmp_dst_ptr = &(dst); \
395 _Py_TYPEOF(dst) _tmp_old_dst = (*_tmp_dst_ptr); \
396 *_tmp_dst_ptr = (src); \
397 Py_DECREF(_tmp_old_dst); \
400#define Py_SETREF(dst, src) \
402 PyObject **_tmp_dst_ptr = _Py_CAST(PyObject **, &(dst)); \
403 PyObject *_tmp_old_dst = (*_tmp_dst_ptr); \
404 PyObject *_tmp_src = _PyObject_CAST(src); \
405 memcpy(_tmp_dst_ptr, &_tmp_src, sizeof(PyObject *)); \
406 Py_DECREF(_tmp_old_dst); \
416#define Py_XSETREF(dst, src) \
418 _Py_TYPEOF(dst) *_tmp_dst_ptr = &(dst); \
419 _Py_TYPEOF(dst) _tmp_old_dst = (*_tmp_dst_ptr); \
420 *_tmp_dst_ptr = (src); \
421 Py_XDECREF(_tmp_old_dst); \
424#define Py_XSETREF(dst, src) \
426 PyObject **_tmp_dst_ptr = _Py_CAST(PyObject **, &(dst)); \
427 PyObject *_tmp_old_dst = (*_tmp_dst_ptr); \
428 PyObject *_tmp_src = _PyObject_CAST(src); \
429 memcpy(_tmp_dst_ptr, &_tmp_src, sizeof(PyObject *)); \
430 Py_XDECREF(_tmp_old_dst); \