Nuitka
The Python compiler
Loading...
Searching...
No Matches
prelude.h
1// Copyright 2026, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3#ifndef __NUITKA_PRELUDE_H__
4#define __NUITKA_PRELUDE_H__
5
6#ifdef _MONOLITHPY
7// MonolithPy VFS support needs to be included as early as possible.
8#include "mp_embed.h"
9#endif
10
11#ifdef __NUITKA_NO_ASSERT__
12#undef NDEBUG
13#define NDEBUG
14#endif
15
16#include "nuitka/debug_settings.h"
17
18#if defined(_WIN32)
19// Note: Keep this separate line, must be included before other Windows headers.
20#include <windows.h>
21#endif
22
23/* Include the CPython version numbers, and define our own take of what version
24 * numbers should be.
25 */
26#include <patchlevel.h>
27
28/* Use a hex version of our own to compare for versions. We do not care about pre-releases */
29#if PY_MICRO_VERSION < 16
30#define PYTHON_VERSION (PY_MAJOR_VERSION * 256 + PY_MINOR_VERSION * 16 + PY_MICRO_VERSION)
31#else
32#define PYTHON_VERSION (PY_MAJOR_VERSION * 256 + PY_MINOR_VERSION * 16 + 15)
33#endif
34
35/* This is needed or else we can't create modules name "proc" or "func". For
36 * Python3, the name collision can't happen, so we can limit it to Python2.
37 spell-checker: ignore initproc,initfunc
38 */
39#define initproc python_init_proc
40#define initfunc python_init_func
41#define initstate python_initstate
42
43// Python 3.11 headers give these warnings
44#if defined(_MSC_VER)
45#pragma warning(push)
46#pragma warning(disable : 4200)
47#pragma warning(disable : 4244)
48#endif
49
50/* Include the relevant Python C-API header files. */
51#include <Python.h>
52#include <frameobject.h>
53#include <marshal.h>
54#include <methodobject.h>
55#include <osdefs.h>
56#include <structseq.h>
57
58#if PYTHON_VERSION < 0x3a0
59#include <pydebug.h>
60#endif
61
62/* A way to not give warnings about things that are declared, but might not
63 * be used like in-line helper functions in headers or static per module
64 * variables from headers.
65 */
66#if defined(__GNUC__) || defined(__clang__)
67#define NUITKA_MAY_BE_UNUSED __attribute__((__unused__))
68#else
69#define NUITKA_MAY_BE_UNUSED
70#endif
71
72// We are not following the 3.10 change to an inline function. At least
73// not immediately.
74#if PYTHON_VERSION >= 0x3a0 && PYTHON_VERSION < 0x3c0
75#undef Py_REFCNT
76#define Py_REFCNT(ob) (_PyObject_CAST(ob)->ob_refcnt)
77#endif
78
79// We are using this new macro on old code too.
80#ifndef Py_SET_REFCNT
81#define Py_SET_REFCNT(ob, refcnt) Py_REFCNT(ob) = refcnt
82#endif
83
84#if _NUITKA_MODULE_MODE
85NUITKA_MAY_BE_UNUSED static inline int Nuitka_GetRuntimeVersion(void) {
86 static int runtime_version = 0;
87
88 if (runtime_version == 0) {
89 const char *ver = Py_GetVersion();
90
91 while (*ver && *ver != '.') {
92 ver++;
93 }
94
95 if (*ver) {
96 ver++;
97 }
98
99 while (*ver && *ver != '.') {
100 ver++;
101 }
102
103 if (*ver) {
104 ver++;
105 }
106
107 int micro = 0;
108
109 while (*ver >= '0' && *ver <= '9') {
110 micro = micro * 10 + (*ver - '0');
111 ver++;
112 }
113
114 if (micro >= 16) {
115 micro = 15;
116 }
117
118 runtime_version = PY_MAJOR_VERSION * 256 + PY_MINOR_VERSION * 16 + micro;
119 }
120
121 return runtime_version;
122}
123#else
124#define Nuitka_GetRuntimeVersion() PYTHON_VERSION
125#endif
126
127#if _NUITKA_MODULE_MODE && PYTHON_VERSION >= 0x3e0 && PYTHON_VERSION < 0x3f0 && !defined(Py_GIL_DISABLED)
128// 'pycore_tuple.h' expands '_PyObject_GC_TRACK()' in inline helpers, so the
129// Nuitka runtime-aware replacements must be declared before that header is
130// included.
131NUITKA_MAY_BE_UNUSED static inline void Nuitka_GC_Track(void *raw_op);
132NUITKA_MAY_BE_UNUSED static inline void Nuitka_GC_UnTrack(void *raw_op);
133#endif
134
135#if defined(_WIN32)
136// Windows is too difficult for API redefines.
137#define MIN_PYCORE_PYTHON_VERSION 0x380
138#else
139#define MIN_PYCORE_PYTHON_VERSION 0x371
140#endif
141
142#if PYTHON_VERSION >= MIN_PYCORE_PYTHON_VERSION
143#define NUITKA_USE_PYCORE_THREAD_STATE
144#endif
145
146#ifdef NUITKA_USE_PYCORE_THREAD_STATE
147#undef Py_BUILD_CORE
148#define Py_BUILD_CORE
149#undef _PyGC_FINALIZED
150
151#if PYTHON_VERSION < 0x380
152#undef Py_ATOMIC_H
153#include <pyatomic.h>
154#undef Py_INTERNAL_PYSTATE_H
155#include <internal/pystate.h>
156#undef Py_STATE_H
157#include <pystate.h>
158
159extern _PyRuntimeState _PyRuntime;
160#else
161
162#if PYTHON_VERSION >= 0x3c0
163#include <internal/pycore_runtime.h>
164#include <internal/pycore_typeobject.h>
165#include <internal/pycore_typevarobject.h>
166
167// Changed internal type access for Python3.13
168#if PYTHON_VERSION < 0x3d0
169#define managed_static_type_state static_builtin_state
170#endif
171
172// 'pycore_object.h' uses '_PyStaticType_GetState()' in inline helpers, so the
173// Nuitka replacement must be visible before that header is included.
174NUITKA_MAY_BE_UNUSED static inline managed_static_type_state *Nuitka_PyStaticType_GetState(PyInterpreterState *interp,
175 PyTypeObject *self);
176
177#define _PyStaticType_GetState(interp, self) Nuitka_PyStaticType_GetState(interp, self)
178#endif
179
180#include <internal/pycore_pystate.h>
181#endif
182
183#if PYTHON_VERSION >= 0x390
184#include <internal/pycore_ceval.h>
185#include <internal/pycore_interp.h>
186#include <internal/pycore_runtime.h>
187#endif
188
189#if PYTHON_VERSION >= 0x380
190#include <cpython/initconfig.h>
191#include <internal/pycore_initconfig.h>
192#include <internal/pycore_pathconfig.h>
193#include <internal/pycore_pyerrors.h>
194#endif
195
196#if PYTHON_VERSION >= 0x3a0
197#include <internal/pycore_long.h>
198#include <internal/pycore_unionobject.h>
199#endif
200
201#if PYTHON_VERSION >= 0x3b0
202#include <internal/pycore_dict.h>
203#include <internal/pycore_frame.h>
204#include <internal/pycore_gc.h>
205#endif
206
207// Uncompiled generator integration requires these.
208#if PYTHON_VERSION >= 0x3b0
209#if PYTHON_VERSION >= 0x3d0
210#include <internal/pycore_opcode_utils.h>
211#include <opcode_ids.h>
212#else
213#include <internal/pycore_opcode.h>
214#endif
215// Clashes with our helper names.
216#undef CALL_FUNCTION
217#endif
218
219#if PYTHON_VERSION >= 0x3c0
220#include <cpython/code.h>
221#endif
222
223#if PYTHON_VERSION < 0x3c0
224// Make sure we go the really fast variant, spell-checker: ignore gilstate
225#undef PyThreadState_GET
226#define _PyThreadState_Current _PyRuntime.gilstate.tstate_current
227#define PyThreadState_GET() ((PyThreadState *)_Py_atomic_load_relaxed(&_PyThreadState_Current))
228#endif
229
230#if PYTHON_VERSION >= 0x380
231#undef _PyObject_LookupSpecial
232#include <internal/pycore_object.h>
233#else
234#include <objimpl.h>
235#endif
236
237#if PYTHON_VERSION >= 0x3c0
238#include <internal/pycore_global_objects.h>
239#endif
240
241#if PYTHON_VERSION >= 0x3d0
242#include <internal/pycore_critical_section.h>
243#include <internal/pycore_freelist.h>
244#include <internal/pycore_intrinsics.h>
245#include <internal/pycore_modsupport.h>
246#include <internal/pycore_parking_lot.h>
247#include <internal/pycore_pyatomic_ft_wrappers.h>
248#include <internal/pycore_pylifecycle.h>
249#include <internal/pycore_setobject.h>
250#include <internal/pycore_time.h>
251#endif
252
253#if PYTHON_VERSION >= 0x3e0
254#include "internal/pycore_object_alloc.h"
255#include <internal/pycore_interpframe.h>
256#include <internal/pycore_interpolation.h>
257#include <internal/pycore_list.h>
258#include <internal/pycore_template.h>
259#include <internal/pycore_tuple.h>
260#include <internal/pycore_typedefs.h>
261#include <internal/pycore_unicodeobject.h>
262#endif
263
264#undef Py_BUILD_CORE
265
266#endif
267
268#if PYTHON_VERSION >= 0x3e0 && PYTHON_VERSION < 0x3f0
269// CPython 3.14.5 grew "_gc_runtime_state" in GIL builds, shifting all later
270// interpreter fields by three pointer widths.
271static inline int Nuitka_PyInterpreterState_PostGcPointerDelta(void) {
272#if _NUITKA_MODULE_MODE && !defined(Py_GIL_DISABLED)
273 static int post_gc_pointer_delta = 99;
274
275 if (post_gc_pointer_delta == 99) {
276 int runtime_pointer_shift = 0;
277 int compile_time_pointer_shift = 0;
278 int runtime_version = Nuitka_GetRuntimeVersion();
279
280 if (runtime_version >= 0x3e5) {
281 runtime_pointer_shift += 3;
282 }
283
284#if PYTHON_VERSION >= 0x3e5
285 compile_time_pointer_shift += 3;
286#endif
287 post_gc_pointer_delta = runtime_pointer_shift - compile_time_pointer_shift;
288 }
289
290 return post_gc_pointer_delta;
291#else
292 return 0;
293#endif
294}
295
296static inline void *Nuitka_PyInterpreterState_AdjustPostGcPointer(void *field_ptr) {
297 return (char *)field_ptr + Nuitka_PyInterpreterState_PostGcPointerDelta() * sizeof(void *);
298}
299
300// CPython 3.14 changed the interpreter layout twice before fields after
301// "_qsbr_shared": 3.14.4 added "_qsbr_shared.array_raw" (+1 pointer) and
302// 3.14.5 grew "_gc_runtime_state" in GIL builds (+3 pointers).
303static inline int Nuitka_PyInterpreterState_PostQsbrPointerDelta(void) {
304#if _NUITKA_MODULE_MODE && !defined(Py_GIL_DISABLED)
305 static int post_qsbr_pointer_delta = 99;
306
307 if (post_qsbr_pointer_delta == 99) {
308 int post_gc_pointer_delta = Nuitka_PyInterpreterState_PostGcPointerDelta();
309 int runtime_version = Nuitka_GetRuntimeVersion();
310 int qsbr_pointer_delta = 0;
311
312 if (runtime_version >= 0x3e4) {
313 qsbr_pointer_delta += 1;
314 }
315
316#if PYTHON_VERSION >= 0x3e4
317 qsbr_pointer_delta -= 1;
318#endif
319 post_qsbr_pointer_delta = post_gc_pointer_delta + qsbr_pointer_delta;
320 }
321
322 return post_qsbr_pointer_delta;
323#else
324 return 0;
325#endif
326}
327
328static inline void *Nuitka_PyInterpreterState_AdjustPostQsbrPointer(void *field_ptr) {
329 return (char *)field_ptr + Nuitka_PyInterpreterState_PostQsbrPointerDelta() * sizeof(void *);
330}
331#endif
332
333#ifdef _NUITKA_ADAPTED_PYTHON_HEADERS
334/* Cross-compiler offset access and runtime abstraction layer */
335#include "nuitka/python_internals_access.h"
336#else
337#if PYTHON_VERSION >= 0x3c0
338#define Nuitka_PyRuntime__imports (&_PyRuntime.imports)
339#define Nuitka_PyRuntime__static_objects (&_PyRuntime.static_objects)
340#endif
341#endif
342
343#if PYTHON_VERSION >= 0x3c0
344static inline size_t Nuitka_static_builtin_index_get(PyTypeObject *self) { return (size_t)self->tp_subclasses - 1; }
345
346static inline struct _import_state *Nuitka_PyInterpreterState_GetImportsState(PyInterpreterState *interp) {
347#if PYTHON_VERSION >= 0x3e0 && PYTHON_VERSION < 0x3f0
348 return (struct _import_state *)Nuitka_PyInterpreterState_AdjustPostGcPointer(&interp->imports);
349#else
350 return &interp->imports;
351#endif
352}
353
354static inline struct types_state *Nuitka_PyInterpreterState_GetTypesState(PyInterpreterState *interp) {
355#if PYTHON_VERSION >= 0x3e0 && PYTHON_VERSION < 0x3f0
356 return (struct types_state *)Nuitka_PyInterpreterState_AdjustPostQsbrPointer(&interp->types);
357#else
358 return &interp->types;
359#endif
360}
361
362static inline struct _Py_dict_state *Nuitka_PyInterpreterState_GetDictState(PyInterpreterState *interp) {
363#if PYTHON_VERSION >= 0x3e0 && PYTHON_VERSION < 0x3f0
364 return (struct _Py_dict_state *)Nuitka_PyInterpreterState_AdjustPostQsbrPointer(&interp->dict_state);
365#else
366 return &interp->dict_state;
367#endif
368}
369
370#if PYTHON_VERSION >= 0x3d0
371NUITKA_MAY_BE_UNUSED static inline struct _Py_mem_interp_free_queue *
372Nuitka_PyInterpreterState_GetMemFreeQueue(PyInterpreterState *interp) {
373#if PYTHON_VERSION >= 0x3e0 && PYTHON_VERSION < 0x3f0
374 return (struct _Py_mem_interp_free_queue *)Nuitka_PyInterpreterState_AdjustPostQsbrPointer(&interp->mem_free_queue);
375#else
376 return &interp->mem_free_queue;
377#endif
378}
379#endif
380
381static inline managed_static_type_state *Nuitka_static_builtin_state_get(PyInterpreterState *interp,
382 PyTypeObject *self) {
383 struct types_state *types_state = Nuitka_PyInterpreterState_GetTypesState(interp);
384
385#if PYTHON_VERSION < 0x3d0
386 return &types_state->builtins[Nuitka_static_builtin_index_get(self)];
387#else
388 return &types_state->builtins.initialized[Nuitka_static_builtin_index_get(self)];
389#endif
390}
391
392NUITKA_MAY_BE_UNUSED static inline managed_static_type_state *Nuitka_PyStaticType_GetState(PyInterpreterState *interp,
393 PyTypeObject *self) {
394 assert(self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
395 return Nuitka_static_builtin_state_get(interp, self);
396}
397#endif
398
399#if defined(_MSC_VER)
400#pragma warning(pop)
401#endif
402
403/* See above. */
404#if PYTHON_VERSION < 0x300
405#undef initproc
406#undef initfunc
407#undef initstate
408#endif
409
410/* Type bool */
411#ifndef __cplusplus
412#include <stdbool.h>
413#endif
414
415/* Include the C header files most often used. */
416#include <stdio.h>
417
418#include "hedley.h"
419
420/* Use annotations for branch prediction. They still make sense as the L1
421 * cache space is saved.
422 */
423
424#define likely(x) HEDLEY_LIKELY(x)
425#define unlikely(x) HEDLEY_UNLIKELY(x)
426
427/* A way to indicate that a specific function won't return, so the C compiler
428 * can create better code.
429 */
430
431#define NUITKA_NO_RETURN HEDLEY_NO_RETURN
432
433/* This is used to indicate code control flows we know cannot happen. */
434#ifndef __NUITKA_NO_ASSERT__
435#define NUITKA_CANNOT_GET_HERE(NAME) \
436 PRINT_FORMAT("%s : %s\n", __FUNCTION__, #NAME); \
437 abort();
438#else
439#define NUITKA_CANNOT_GET_HERE(NAME) abort();
440#endif
441
442#define NUITKA_ERROR_EXIT(NAME) \
443 PRINT_FORMAT("%s : %s\n", __FUNCTION__, #NAME); \
444 abort();
445
446#if defined(_MSC_VER)
447/* Using "_alloca" extension due to MSVC restrictions for array variables
448 * on the local stack.
449 */
450#include <malloc.h>
451#define NUITKA_DYNAMIC_ARRAY_DECL(VARIABLE_NAME, ELEMENT_TYPE, COUNT) \
452 ELEMENT_TYPE *VARIABLE_NAME = (ELEMENT_TYPE *)_alloca(sizeof(ELEMENT_TYPE) * (COUNT));
453#elif defined(__ZIG__)
454#define NUITKA_DYNAMIC_ARRAY_DECL(VARIABLE_NAME, ELEMENT_TYPE, COUNT) \
455 ELEMENT_TYPE VARIABLE_NAME[((COUNT) == 0) ? 1 : (COUNT)];
456#else
457#define NUITKA_DYNAMIC_ARRAY_DECL(VARIABLE_NAME, ELEMENT_TYPE, COUNT) ELEMENT_TYPE VARIABLE_NAME[COUNT];
458#endif
459
460/* Python3 removed PyInt instead of renaming PyLong, and PyObject_Str instead
461 * of renaming PyObject_Unicode. Define this to be easily portable.
462 */
463#if PYTHON_VERSION >= 0x300
464#define PyInt_AsLong PyLong_AsLong
465#define PyInt_FromSsize_t PyLong_FromSsize_t
466
467#define PyNumber_Int PyNumber_Long
468
469#define PyObject_Unicode PyObject_Str
470
471#endif
472
473/* String handling that uses the proper version of strings for Python3 or not,
474 * which makes it easier to write portable code.
475 */
476#if PYTHON_VERSION < 0x300
477#define PyUnicode_GET_LENGTH(x) (PyUnicode_GET_SIZE(x))
478#define Nuitka_String_AsString PyString_AsString
479#define Nuitka_String_AsString_Unchecked PyString_AS_STRING
480#define Nuitka_String_Check PyString_Check
481#define Nuitka_String_CheckExact PyString_CheckExact
482NUITKA_MAY_BE_UNUSED static inline bool Nuitka_StringOrUnicode_CheckExact(PyObject *value) {
483 return PyString_CheckExact(value) || PyUnicode_CheckExact(value);
484}
485#define Nuitka_StringObject PyStringObject
486#define Nuitka_String_FromString PyString_FromString
487#define Nuitka_String_FromStringAndSize PyString_FromStringAndSize
488#define Nuitka_String_FromFormat PyString_FromFormat
489#define PyUnicode_CHECK_INTERNED (0)
490NUITKA_MAY_BE_UNUSED static Py_UNICODE *Nuitka_UnicodeAsWideString(PyObject *str, Py_ssize_t *size) {
491 PyObject *unicode;
492
493 if (!PyUnicode_Check(str)) {
494 // Leaking memory, but for usages its acceptable to
495 // achieve that the pointer remains valid.
496 unicode = PyObject_Unicode(str);
497 } else {
498 unicode = str;
499 }
500
501 if (size != NULL) {
502 *size = (Py_ssize_t)PyUnicode_GET_LENGTH(unicode);
503 }
504
505 return PyUnicode_AsUnicode(unicode);
506}
507#else
508#define Nuitka_String_AsString _PyUnicode_AsString
509
510// Note: This private stuff from file "Objects/unicodeobject.c"
511// spell-checker: ignore unicodeobject
512#define _PyUnicode_UTF8(op) (((PyCompactUnicodeObject *)(op))->utf8)
513#define PyUnicode_UTF8(op) \
514 (assert(PyUnicode_IS_READY(op)), \
515 PyUnicode_IS_COMPACT_ASCII(op) ? ((char *)((PyASCIIObject *)(op) + 1)) : _PyUnicode_UTF8(op))
516#ifdef __NUITKA_NO_ASSERT__
517#define Nuitka_String_AsString_Unchecked PyUnicode_UTF8
518#else
519NUITKA_MAY_BE_UNUSED static char const *Nuitka_String_AsString_Unchecked(PyObject *object) {
520 char const *result = PyUnicode_UTF8(object);
521 assert(result != NULL);
522 return result;
523}
524#endif
525#define Nuitka_String_Check PyUnicode_Check
526#define Nuitka_String_CheckExact PyUnicode_CheckExact
527#define Nuitka_StringOrUnicode_CheckExact PyUnicode_CheckExact
528#define Nuitka_StringObject PyUnicodeObject
529#define Nuitka_String_FromString PyUnicode_FromString
530#define Nuitka_String_FromStringAndSize PyUnicode_FromStringAndSize
531#define Nuitka_String_FromFormat PyUnicode_FromFormat
532#define Nuitka_UnicodeAsWideString PyUnicode_AsWideCharString
533#endif
534
535// Before 3.7, it's only available in debug Python, so we need to guard this.
536#if PYTHON_VERSION < 0x370
537#define Nuitka_PyUnicode_CheckConsistency(op, check) 1
538#else
539#define Nuitka_PyUnicode_CheckConsistency(op, check) (_PyUnicode_CheckConsistency(op, check))
540#endif
541
542// Wrap the type lookup for debug mode, to identify errors, and potentially
543// to make our own enhancement later on. For now only verify it is not being
544// called with an error set, which 3.9 asserts against in core code.
545#ifdef __NUITKA_NO_ASSERT__
546#define Nuitka_TypeLookup(x, y) _PyType_Lookup(x, y)
547#else
548NUITKA_MAY_BE_UNUSED static PyObject *Nuitka_TypeLookup(PyTypeObject *type, PyObject *name) {
549 return _PyType_Lookup(type, name);
550}
551
552#endif
553
554/* With the idea to reduce the amount of exported symbols in the DLLs, make it
555 * clear that the module "init" function should of course be exported, but not
556 * for executable, where we call it ourselves from the main code.
557 */
558
559#if PYTHON_VERSION < 0x300
560#define NUITKA_MODULE_ENTRY_FUNCTION void
561#else
562#define NUITKA_MODULE_ENTRY_FUNCTION PyObject *
563#endif
564
565#if PYTHON_VERSION < 0x300
566typedef long Py_hash_t;
567#endif
568
569/* These two express if a directly called function should be exported (C level)
570 * or if it can be local to the file.
571 */
572#define NUITKA_CROSS_MODULE
573#define NUITKA_LOCAL_MODULE static
574
575#if PYTHON_VERSION >= 0x3e0
576// TODO: Does this code have to be in the header really? spell-checker: ignore gcstate
577static inline void Nuitka_Py_ScheduleGC(PyThreadState *tstate) {
578 if (!_Py_eval_breaker_bit_is_set(tstate, _PY_GC_SCHEDULED_BIT)) {
579 _Py_set_eval_breaker_bit(tstate, _PY_GC_SCHEDULED_BIT);
580 }
581}
582
583static inline bool Nuitka_GC_UsesGeneration0List(void) {
584#if _NUITKA_MODULE_MODE && PYTHON_VERSION < 0x3f0 && !defined(Py_GIL_DISABLED)
585 static int uses_generation0_list = -1;
586
587 if (uses_generation0_list == -1) {
588 uses_generation0_list = Nuitka_GetRuntimeVersion() >= 0x3e5;
589 }
590
591 return uses_generation0_list != 0;
592#else
593 return PYTHON_VERSION >= 0x3e5;
594#endif
595}
596#endif
597
598/* Due to ABI issues, it seems that on Windows the symbols used by
599 * "_PyObject_GC_TRACK" were not exported before 3.8 and we need to use a
600 * function that does it instead.
601 *
602 * The Python 3.7.0 release on at Linux doesn't work this way either, was
603 * a bad CPython release apparently and between 3.7.3 and 3.7.4 these have
604 * become runtime incompatible.
605 *
606 */
607#if _NUITKA_MODULE_MODE && PYTHON_VERSION >= 0x3e0 && PYTHON_VERSION < 0x3f0 && !defined(Py_GIL_DISABLED)
608typedef struct {
609 PyObject *trash_delete_later;
610 int trash_delete_nesting;
611 int enabled;
612 int debug;
613 struct gc_generation young;
614 struct gc_generation old[2];
615 struct gc_generation permanent_generation;
616 struct gc_generation_stats generation_stats[NUM_GENERATIONS];
617 int collecting;
618 PyObject *garbage;
619 PyObject *callbacks;
620 Py_ssize_t heap_size;
621 Py_ssize_t work_to_do;
622 int visited_space;
623 int phase;
624} Nuitka_GCStateIncremental;
625
626typedef struct {
627 PyObject *trash_delete_later;
628 int trash_delete_nesting;
629 int enabled;
630 int debug;
631 struct gc_generation generations[NUM_GENERATIONS];
632 struct gc_generation permanent_generation;
633 struct gc_generation_stats generation_stats[NUM_GENERATIONS];
634 int collecting;
635 PyObject *garbage;
636 PyObject *callbacks;
637 Py_ssize_t heap_size;
638 Py_ssize_t dummy1;
639 int dummy2;
640 int dummy3;
641 Py_ssize_t long_lived_total;
642 Py_ssize_t long_lived_pending;
643 PyGC_Head *generation0;
644} Nuitka_GCStateGenerational;
645
646static inline Nuitka_GCStateIncremental *Nuitka_GC_GetIncrementalState(struct _gc_runtime_state *gcstate) {
647 return (Nuitka_GCStateIncremental *)gcstate;
648}
649
650static inline Nuitka_GCStateGenerational *Nuitka_GC_GetGenerationalState(struct _gc_runtime_state *gcstate) {
651 return (Nuitka_GCStateGenerational *)gcstate;
652}
653
654static inline PyGC_Head *Nuitka_GCHead_NEXT(PyGC_Head *gc) {
655 if (Nuitka_GC_UsesGeneration0List()) {
656 return (PyGC_Head *)gc->_gc_next;
657 } else {
658 uintptr_t next = gc->_gc_next & _PyGC_PREV_MASK;
659 return (PyGC_Head *)next;
660 }
661}
662
663static inline void Nuitka_GCHead_SET_NEXT(PyGC_Head *gc, PyGC_Head *next) {
664 if (Nuitka_GC_UsesGeneration0List()) {
665 gc->_gc_next = (uintptr_t)next;
666 } else {
667 uintptr_t unext = (uintptr_t)next;
668 assert((unext & ~_PyGC_PREV_MASK) == 0);
669 gc->_gc_next = (gc->_gc_next & ~_PyGC_PREV_MASK) | unext;
670 }
671}
672
673#define _PyGCHead_NEXT Nuitka_GCHead_NEXT
674#define _PyGCHead_SET_NEXT Nuitka_GCHead_SET_NEXT
675
676static inline bool Nuitka_GC_TrackOwnsAccounting(void) {
677 static int owns_accounting = -1;
678
679 if (owns_accounting == -1) {
680 int runtime_version = Nuitka_GetRuntimeVersion();
681 owns_accounting = runtime_version >= 0x3e1 && runtime_version < 0x3e5;
682 }
683
684 return owns_accounting != 0;
685}
686
687#undef Nuitka_GC_Track
688static inline void Nuitka_GC_Track(void *raw_op) {
689 PyObject *op = (PyObject *)raw_op;
690 PyGC_Head *gc = _Py_AS_GC(op);
691 struct _gc_runtime_state *gcstate = &_PyInterpreterState_GET()->gc;
692
693 if (Nuitka_GC_UsesGeneration0List()) {
694 Nuitka_GCStateGenerational *gcstate_generational = Nuitka_GC_GetGenerationalState(gcstate);
695 PyGC_Head *generation0 = gcstate_generational->generation0;
696 PyGC_Head *last = (PyGC_Head *)(generation0->_gc_prev);
697
698 _PyGCHead_SET_NEXT(last, gc);
699 _PyGCHead_SET_PREV(gc, last);
700 _PyGCHead_SET_NEXT(gc, generation0);
701 generation0->_gc_prev = (uintptr_t)gc;
702
703 gcstate_generational->heap_size++;
704 } else {
705 Nuitka_GCStateIncremental *gcstate_incremental = Nuitka_GC_GetIncrementalState(gcstate);
706 PyGC_Head *generation0 = &gcstate_incremental->young.head;
707 PyGC_Head *last = (PyGC_Head *)(generation0->_gc_prev);
708
709 _PyGCHead_SET_NEXT(last, gc);
710 _PyGCHead_SET_PREV(gc, last);
711
712 {
713 uintptr_t not_visited = 1 ^ gcstate_incremental->visited_space;
714 gc->_gc_next = ((uintptr_t)generation0) | not_visited;
715 }
716
717 generation0->_gc_prev = (uintptr_t)gc;
718
719 if (Nuitka_GC_TrackOwnsAccounting()) {
720 gcstate_incremental->young.count++;
721 gcstate_incremental->heap_size++;
722
723 if (gcstate_incremental->young.count > gcstate_incremental->young.threshold) {
724 if (gcstate_incremental->enabled && gcstate_incremental->young.threshold &&
725 !_Py_atomic_load_int_relaxed(&gcstate_incremental->collecting) &&
726 !_PyErr_Occurred(_PyThreadState_GET())) {
727 Nuitka_Py_ScheduleGC(_PyThreadState_GET());
728 }
729 }
730 }
731 }
732}
733
734// TODO: Does this code have to be in the header really? spell-checker: ignore gcstate
735#undef Nuitka_GC_UnTrack
736static inline void Nuitka_GC_UnTrack(void *raw_op) {
737 PyObject *op = (PyObject *)raw_op;
738 PyGC_Head *gc = _Py_AS_GC(op);
739 PyGC_Head *prev = _PyGCHead_PREV(gc);
740 PyGC_Head *next = _PyGCHead_NEXT(gc);
741
742 _PyGCHead_SET_NEXT(prev, next);
743 _PyGCHead_SET_PREV(next, prev);
744 gc->_gc_next = 0;
745 gc->_gc_prev &= _PyGC_PREV_MASK_FINALIZED;
746
747 if (Nuitka_GC_UsesGeneration0List()) {
748 struct _gc_runtime_state *gcstate = &_PyInterpreterState_GET()->gc;
749 gcstate->heap_size--;
750 } else if (Nuitka_GC_TrackOwnsAccounting()) {
751 Nuitka_GCStateIncremental *gcstate_incremental = Nuitka_GC_GetIncrementalState(&_PyInterpreterState_GET()->gc);
752
753 if (gcstate_incremental->young.count > 0) {
754 gcstate_incremental->young.count--;
755 }
756
757 gcstate_incremental->heap_size--;
758 }
759}
760
761#undef _PyObject_GC_TRACK
762#undef _PyObject_GC_UNTRACK
763#elif (PYTHON_VERSION >= 0x3e0 && !defined(Py_GIL_DISABLED)) && (PYTHON_VERSION < 0x3e5)
764
765static inline bool Nuitka_GC_TrackOwnsAccounting(void) {
766#if _NUITKA_MODULE_MODE
767 static int owns_accounting = -1;
768
769 if (owns_accounting == -1) {
770 owns_accounting = Nuitka_GetRuntimeVersion() >= 0x3e1;
771 }
772
773 return owns_accounting != 0;
774#else
775 return PYTHON_VERSION >= 0x3e1;
776#endif
777}
778
779#undef Nuitka_GC_Track
780static inline void Nuitka_GC_Track(void *raw_op) {
781 PyObject *op = (PyObject *)raw_op;
782 PyGC_Head *gc = _Py_AS_GC(op);
783
784 struct _gc_runtime_state *gcstate = &_PyInterpreterState_GET()->gc;
785 PyGC_Head *generation0 = &gcstate->young.head;
786 PyGC_Head *last = (PyGC_Head *)(generation0->_gc_prev);
787 _PyGCHead_SET_NEXT(last, gc);
788 _PyGCHead_SET_PREV(gc, last);
789 {
790 uintptr_t not_visited = 1 ^ gcstate->visited_space;
791 gc->_gc_next = ((uintptr_t)generation0) | not_visited;
792 }
793 generation0->_gc_prev = (uintptr_t)gc;
794
795 if (Nuitka_GC_TrackOwnsAccounting()) {
796 gcstate->young.count++;
797 gcstate->heap_size++;
798
799 if (gcstate->young.count > gcstate->young.threshold) {
800 if (gcstate->enabled && gcstate->young.threshold && !_Py_atomic_load_int_relaxed(&gcstate->collecting) &&
801 !_PyErr_Occurred(_PyThreadState_GET())) {
802 Nuitka_Py_ScheduleGC(_PyThreadState_GET());
803 }
804 }
805 }
806}
807
808// TODO: Does this code have to be in the header really? spell-checker: ignore gcstate
809#undef Nuitka_GC_UnTrack
810static inline void Nuitka_GC_UnTrack(void *raw_op) {
811 PyObject *op = (PyObject *)raw_op;
812 PyGC_Head *gc = _Py_AS_GC(op);
813 PyGC_Head *prev = _PyGCHead_PREV(gc);
814 PyGC_Head *next = _PyGCHead_NEXT(gc);
815 _PyGCHead_SET_NEXT(prev, next);
816 _PyGCHead_SET_PREV(next, prev);
817 gc->_gc_next = 0;
818 gc->_gc_prev &= _PyGC_PREV_MASK_FINALIZED;
819}
820
821#undef _PyObject_GC_TRACK
822#undef _PyObject_GC_UNTRACK
823#elif (defined(_WIN32) || defined(__MSYS__)) && PYTHON_VERSION < 0x380
824#define Nuitka_GC_Track PyObject_GC_Track
825#define Nuitka_GC_UnTrack PyObject_GC_UnTrack
826#undef _PyObject_GC_TRACK
827#undef _PyObject_GC_UNTRACK
828#elif PYTHON_VERSION == 0x370
829#define Nuitka_GC_Track PyObject_GC_Track
830#define Nuitka_GC_UnTrack PyObject_GC_UnTrack
831#undef _PyObject_GC_TRACK
832#undef _PyObject_GC_UNTRACK
833#elif _NUITKA_MODULE_MODE && PYTHON_VERSION >= 0x370 && PYTHON_VERSION < 0x380
834#define Nuitka_GC_Track PyObject_GC_Track
835#define Nuitka_GC_UnTrack PyObject_GC_UnTrack
836#undef _PyObject_GC_TRACK
837#undef _PyObject_GC_UNTRACK
838#undef PyThreadState_GET
839#define PyThreadState_GET PyThreadState_Get
840#else
841#define Nuitka_GC_Track _PyObject_GC_TRACK
842#define Nuitka_GC_UnTrack _PyObject_GC_UNTRACK
843#endif
844
845#if _NUITKA_EXPERIMENTAL_FAST_THREAD_GET && PYTHON_VERSION >= 0x300 && PYTHON_VERSION < 0x370
846// We are careful, access without locking under the assumption that we hold
847// the GIL over uses of this or the same thread continues to execute code of
848// ours.
849#undef PyThreadState_GET
850extern PyThreadState *_PyThreadState_Current;
851#define PyThreadState_GET() (_PyThreadState_Current)
852#endif
853
854#ifndef _NUITKA_FULL_COMPAT
855// Remove useless recursion control guards, except for testing mode, we do not
856// want them and we have no need for them as we are achieving deeper recursion
857// anyway.
858#undef Py_EnterRecursiveCall
859#define Py_EnterRecursiveCall(arg) (0)
860#undef Py_LeaveRecursiveCall
861#define Py_LeaveRecursiveCall()
862#endif
863
864#if PYTHON_VERSION < 0x300
865#define TP_RICHCOMPARE(t) (PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE) ? (t)->tp_richcompare : NULL)
866#else
867#define TP_RICHCOMPARE(t) ((t)->tp_richcompare)
868#endif
869
870// For older Python we need to define this ourselves.
871#ifndef Py_ABS
872#define Py_ABS(x) ((x) < 0 ? -(x) : (x))
873#endif
874
875#ifndef Py_MIN
876#define Py_MIN(x, y) (((x) > (y)) ? (y) : (x))
877#endif
878
879#ifndef Py_MAX
880#define Py_MAX(x, y) (((x) > (y)) ? (x) : (y))
881#endif
882
883#ifndef Py_SET_SIZE
884#define Py_SET_SIZE(op, size) ((PyVarObject *)(op))->ob_size = size
885#endif
886
887#ifndef PyFloat_SET_DOUBLE
888#define PyFloat_SET_DOUBLE(op, value) ((PyFloatObject *)(op))->ob_fval = value
889#endif
890
891#ifndef Py_NewRef
892static inline PyObject *_Py_NewRef(PyObject *obj) {
893 Py_INCREF(obj);
894 return obj;
895}
896
897static inline PyObject *_Py_XNewRef(PyObject *obj) {
898 Py_XINCREF(obj);
899 return obj;
900}
901
902#define Py_NewRef(obj) _Py_NewRef((PyObject *)(obj))
903#define Py_XNewRef(obj) _Py_XNewRef((PyObject *)(obj))
904#endif
905
906// For older Python, we don't have a feature "CLASS" anymore, that's implied now.
907#if PYTHON_VERSION < 0x300
908#define NuitkaType_HasFeatureClass(descr) (PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS))
909#else
910#define NuitkaType_HasFeatureClass(descr) (1)
911#endif
912
913// For pre-3.13, lets allow ourselves to use them as well, these do play
914// nice with no-GIL Python.
915#if PYTHON_VERSION < 0x3d0
916#define FT_ATOMIC_LOAD_PTR(value) value
917#define FT_ATOMIC_STORE_PTR(value, new_value) value = new_value
918#define FT_ATOMIC_LOAD_SSIZE(value) value
919#define FT_ATOMIC_LOAD_SSIZE_ACQUIRE(value) value
920#define FT_ATOMIC_LOAD_SSIZE_RELAXED(value) value
921#define FT_ATOMIC_STORE_PTR(value, new_value) value = new_value
922#define FT_ATOMIC_LOAD_PTR_ACQUIRE(value) value
923#define FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(value) value
924#define FT_ATOMIC_LOAD_PTR_RELAXED(value) value
925#define FT_ATOMIC_LOAD_UINT8(value) value
926#define FT_ATOMIC_STORE_UINT8(value, new_value) value = new_value
927#define FT_ATOMIC_LOAD_UINT8_RELAXED(value) value
928#define FT_ATOMIC_LOAD_UINT16_RELAXED(value) value
929#define FT_ATOMIC_LOAD_UINT32_RELAXED(value) value
930#define FT_ATOMIC_LOAD_ULONG_RELAXED(value) value
931#define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) value = new_value
932#define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) value = new_value
933#define FT_ATOMIC_STORE_UINTPTR_RELEASE(value, new_value) value = new_value
934#define FT_ATOMIC_STORE_SSIZE_RELAXED(value, new_value) value = new_value
935#define FT_ATOMIC_STORE_UINT8_RELAXED(value, new_value) value = new_value
936#define FT_ATOMIC_STORE_UINT16_RELAXED(value, new_value) value = new_value
937#define FT_ATOMIC_STORE_UINT32_RELAXED(value, new_value) value = new_value
938
939#define Py_BEGIN_CRITICAL_SECTION(mut) {
940#define Py_BEGIN_CRITICAL_SECTION2(m1, m2) {
941#define Py_BEGIN_CRITICAL_SECTION_MUT(mut) {
942#define Py_BEGIN_CRITICAL_SECTION2_MUT(m1, m2) {
943#define Py_END_CRITICAL_SECTION() }
944
945#define Py_BEGIN_CRITICAL_SECTION_SEQUENCE_FAST(original) {
946#define Py_END_CRITICAL_SECTION_SEQUENCE_FAST() }
947#define _Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(mutex)
948#define _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op)
949
950#endif
951
952#ifdef Py_GIL_DISABLED
953#define LOCK_KEYS(keys) PyMutex_Lock(&keys->dk_mutex)
954#define UNLOCK_KEYS(keys) PyMutex_Unlock(&keys->dk_mutex)
955#else
956#define LOCK_KEYS(keys)
957#define UNLOCK_KEYS(keys)
958#endif
959
960// Our replacement for "PyType_IsSubtype"
961extern bool Nuitka_Type_IsSubtype(PyTypeObject *a, PyTypeObject *b);
962
963#include "nuitka/allocator.h"
964#include "nuitka/exceptions.h"
965
966// The digit types
967#if PYTHON_VERSION < 0x300
968#include <longintrepr.h>
969
970#if PYTHON_VERSION < 0x270
971// Not present in Python2.6 yet, spell-checker: ignore sdigit
972typedef signed int sdigit;
973#endif
974#endif
975
976// Standard way to cast PyCFunctionWithKeywords to PyCFunction without
977// triggering compiler warnings about mismatched function types. To preserve
978// type safety, we assert that the passed function actually matches
979// PyCFunctionWithKeywords using a ternary operator conditional that forces the
980// compiler to check the input type.
981#define CAST_METHOD_KW(func) (PyCFunction)(void (*)(void))(1 ? (func) : (PyCFunctionWithKeywords)(func))
982
983// A long value that represents a signed digit on the helper interface.
984typedef long nuitka_digit;
985
986#include "nuitka/helpers.h"
987
988#include "nuitka/compiled_frame.h"
989
990#include "nuitka/compiled_cell.h"
991
992#include "nuitka/compiled_function.h"
993
994/* Sentinel PyObject to be used for all our call iterator endings. */
995extern PyObject *Nuitka_sentinel_value;
996
997/* Value to use for __compiled__ value of all modules. */
998extern PyObject *Nuitka_dunder_compiled_value;
999
1000#include "nuitka/compiled_generator.h"
1001
1002#include "nuitka/compiled_method.h"
1003
1004#if PYTHON_VERSION >= 0x350
1005#include "nuitka/compiled_coroutine.h"
1006#endif
1007
1008#if PYTHON_VERSION >= 0x360
1009#include "nuitka/compiled_asyncgen.h"
1010#endif
1011
1012#include "nuitka/filesystem_paths.h"
1013#include "nuitka/safe_string_ops.h"
1014
1015#include "nuitka/jit_sources.h"
1016
1017#if !_NUITKA_EXPERIMENTAL_WRITEABLE_CONSTANTS
1018#define DECODE(x) assert(x)
1019#define UN_TRANSLATE(x) (x)
1020#endif
1021
1022#ifndef MAKE_NAME
1023#define MAKE_NAME(name, index) (name)
1024#endif
1025
1026#ifndef UN_TRANSLATE_NAME
1027#define UN_TRANSLATE_NAME(x) (x)
1028#endif
1029
1030#if _NUITKA_EXPERIMENTAL_FILE_TRACING
1031#include "nuitka_file_tracer.h"
1032#else
1033#if PYTHON_VERSION < 0x300
1034#define TRACE_FILE_OPEN(tstate, x, y, z, r) (false)
1035#else
1036#define TRACE_FILE_OPEN(tstate, x, y, z, a, b, c, d, e, r) (false)
1037#endif
1038#define TRACE_FILE_READ(tstate, x, y) (false)
1039
1040#define TRACE_FILE_EXISTS(tstate, x, y) (false)
1041#define TRACE_FILE_ISFILE(tstate, x, y) (false)
1042#define TRACE_FILE_ISDIR(tstate, x, y) (false)
1043
1044#define TRACE_FILE_LISTDIR(tstate, x, y) (false)
1045
1046#define TRACE_FILE_STAT(tstate, x, y, z, r) (false)
1047
1048#endif
1049
1050// Only Python3.9+ has a more precise check, while making the old one slow.
1051#ifndef PyCFunction_CheckExact
1052#define PyCFunction_CheckExact PyCFunction_Check
1053#endif
1054
1055#ifdef _NUITKA_EXPERIMENTAL_DUMP_C_TRACEBACKS
1056extern void INIT_C_BACKTRACES(void);
1057extern void DUMP_C_BACKTRACE(void);
1058
1059// For signal handlers, we can do this.
1060#include <ucontext.h>
1061extern void DUMP_C_BACKTRACE_FROM_CONTEXT(void *ucontext);
1062#endif
1063
1064#if _NUITKA_EXPERIMENTAL_EXTRA_INCLUDES
1065#include "extra_python_includes.h"
1066#endif
1067
1068#endif
1069
1070// Part of "Nuitka", an optimizing Python compiler that is compatible and
1071// integrates with CPython, but also works on its own.
1072//
1073// Licensed under the GNU Affero General Public License, Version 3 (the "License");
1074// you may not use this file except in compliance with the License.
1075// You may obtain a copy of the License at
1076//
1077// http://www.gnu.org/licenses/agpl.txt
1078//
1079// Unless required by applicable law or agreed to in writing, software
1080// distributed under the License is distributed on an "AS IS" BASIS,
1081// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1082// See the License for the specific language governing permissions and
1083// limitations under the License.