Nuitka
The Python compiler
Loading...
Searching...
No Matches
CompiledFrameType.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3#ifdef __IDE_ONLY__
4#include "nuitka/freelists.h"
5#include "nuitka/prelude.h"
6#include <structmember.h>
7#endif
8
9// For reporting about reference counts per type.
10#if _DEBUG_REFCOUNTS
11int count_active_Nuitka_Frame_Type = 0;
12int count_allocated_Nuitka_Frame_Type = 0;
13int count_released_Nuitka_Frame_Type = 0;
14#endif
15
16// For reporting about frame cache usage
17#if _DEBUG_REFCOUNTS
18int count_active_frame_cache_instances = 0;
19int count_allocated_frame_cache_instances = 0;
20int count_released_frame_cache_instances = 0;
21int count_hit_frame_cache_instances = 0;
22#endif
23
24#if PYTHON_VERSION < 0x3b0
25static PyMemberDef Nuitka_Frame_members[] = {
26 {(char *)"f_back", T_OBJECT, offsetof(PyFrameObject, f_back), READONLY | RESTRICTED},
27 {(char *)"f_code", T_OBJECT, offsetof(PyFrameObject, f_code), READONLY | RESTRICTED},
28 {(char *)"f_builtins", T_OBJECT, offsetof(PyFrameObject, f_builtins), READONLY | RESTRICTED},
29 {(char *)"f_globals", T_OBJECT, offsetof(PyFrameObject, f_globals), READONLY | RESTRICTED},
30 {(char *)"f_lasti", T_INT, offsetof(PyFrameObject, f_lasti), READONLY | RESTRICTED},
31 {NULL}};
32
33#else
34#define Nuitka_Frame_members 0
35#endif
36
37#if PYTHON_VERSION < 0x300
38
39static PyObject *_Nuitka_Frame_get_exc_traceback(PyObject *self, void *data) {
40 assert(Nuitka_Frame_CheckExact(self));
41 CHECK_OBJECT(self);
42 assert(_PyObject_GC_IS_TRACKED(self));
43
44 struct Nuitka_FrameObject *frame = (struct Nuitka_FrameObject *)self;
45 PyObject *result = frame->m_frame.f_exc_traceback;
46
47 if (result == NULL) {
48 result = Py_None;
49 }
50
51 Py_INCREF(result);
52 return result;
53}
54
55static int _Nuitka_Frame_set_exc_traceback(PyObject *self, PyObject *traceback, void *data) {
56 assert(Nuitka_Frame_CheckExact(self));
57 CHECK_OBJECT(self);
58 assert(_PyObject_GC_IS_TRACKED(self));
59
60 struct Nuitka_FrameObject *frame = (struct Nuitka_FrameObject *)self;
61 Py_XDECREF(frame->m_frame.f_exc_traceback);
62
63 if (traceback == Py_None) {
64 traceback = NULL;
65 }
66
67 frame->m_frame.f_exc_traceback = traceback;
68 Py_XINCREF(traceback);
69
70 return 0;
71}
72
73static PyObject *_Nuitka_Frame_get_exc_type(PyObject *self, void *data) {
74 assert(Nuitka_Frame_CheckExact(self));
75 CHECK_OBJECT(self);
76 assert(_PyObject_GC_IS_TRACKED(self));
77
78 PyObject *result;
79 struct Nuitka_FrameObject *frame = (struct Nuitka_FrameObject *)self;
80
81 if (frame->m_frame.f_exc_type != NULL) {
82 result = frame->m_frame.f_exc_type;
83 } else {
84 result = Py_None;
85 }
86
87 Py_INCREF(result);
88 return result;
89}
90
91static int _Nuitka_Frame_set_exc_type(PyObject *self, PyObject *exception_type, void *data) {
92 assert(Nuitka_Frame_CheckExact(self));
93 CHECK_OBJECT(self);
94 assert(_PyObject_GC_IS_TRACKED(self));
95
96 struct Nuitka_FrameObject *frame = (struct Nuitka_FrameObject *)self;
97 PyObject *old = frame->m_frame.f_exc_type;
98
99 if (exception_type == Py_None) {
100 exception_type = NULL;
101 }
102
103 frame->m_frame.f_exc_type = exception_type;
104 Py_XINCREF(frame->m_frame.f_exc_type);
105
106 Py_XDECREF(old);
107
108 return 0;
109}
110
111static PyObject *_Nuitka_Frame_get_exc_value(PyObject *self, void *data) {
112 assert(Nuitka_Frame_CheckExact(self));
113 CHECK_OBJECT(self);
114 assert(_PyObject_GC_IS_TRACKED(self));
115
116 PyObject *result;
117 struct Nuitka_FrameObject *frame = (struct Nuitka_FrameObject *)self;
118
119 if (frame->m_frame.f_exc_value != NULL) {
120 result = frame->m_frame.f_exc_value;
121 } else {
122 result = Py_None;
123 }
124
125 Py_INCREF(result);
126 return result;
127}
128
129static int _Nuitka_Frame_set_exc_value(PyObject *self, PyObject *exception_value, void *data) {
130 assert(Nuitka_Frame_CheckExact(self));
131 CHECK_OBJECT(self);
132 assert(_PyObject_GC_IS_TRACKED(self));
133
134 struct Nuitka_FrameObject *frame = (struct Nuitka_FrameObject *)self;
135 PyObject *old = frame->m_frame.f_exc_value;
136
137 if (exception_value == Py_None) {
138 exception_value = NULL;
139 }
140
141 frame->m_frame.f_exc_value = exception_value;
142 Py_XINCREF(exception_value);
143 Py_XDECREF(old);
144
145 return 0;
146}
147
148static PyObject *_Nuitka_Frame_get_restricted(PyObject *self, void *data) {
149 assert(Nuitka_Frame_CheckExact(self));
150 CHECK_OBJECT(self);
151 assert(_PyObject_GC_IS_TRACKED(self));
152
153 Py_INCREF_IMMORTAL(Py_False);
154 return Py_False;
155}
156
157#endif
158
159static PyObject *_Nuitka_Frame_get_locals(PyObject *self, void *data) {
160 assert(Nuitka_Frame_CheckExact(self));
161 CHECK_OBJECT(self);
162 assert(_PyObject_GC_IS_TRACKED(self));
163
164 NUITKA_MAY_BE_UNUSED PyThreadState *tstate = PyThreadState_GET();
165
166 struct Nuitka_FrameObject *nuitka_frame = (struct Nuitka_FrameObject *)self;
167 if (nuitka_frame->m_type_description == NULL) {
168#if PYTHON_VERSION < 0x3b0
169 PyFrameObject *locals_owner = &nuitka_frame->m_frame;
170#else
171 _PyInterpreterFrame *locals_owner = &nuitka_frame->m_interpreter_frame;
172#endif
173
174 if (locals_owner->f_locals == NULL) {
175 locals_owner->f_locals = MAKE_DICT_EMPTY(tstate);
176 }
177
178 Py_INCREF(locals_owner->f_locals);
179 return locals_owner->f_locals;
180 } else {
181 PyObject *result = MAKE_DICT_EMPTY(tstate);
182 PyObject **var_names = Nuitka_GetCodeVarNames(Nuitka_GetFrameCodeObject(nuitka_frame));
183
184 char const *w = nuitka_frame->m_type_description;
185 char const *t = nuitka_frame->m_locals_storage;
186
187 while (*w != 0) {
188 switch (*w) {
189 case NUITKA_TYPE_DESCRIPTION_OBJECT:
190 case NUITKA_TYPE_DESCRIPTION_OBJECT_PTR: {
191 PyObject *value = *(PyObject **)t;
192 CHECK_OBJECT_X(value);
193
194 if (value != NULL) {
195 DICT_SET_ITEM(result, *var_names, value);
196 }
197
198 t += sizeof(PyObject *);
199
200 break;
201 }
202 case NUITKA_TYPE_DESCRIPTION_CELL: {
203 struct Nuitka_CellObject *value = *(struct Nuitka_CellObject **)t;
204 assert(Nuitka_Cell_Check((PyObject *)value));
205 CHECK_OBJECT(value);
206
207 if (value->ob_ref != NULL) {
208 DICT_SET_ITEM(result, *var_names, value->ob_ref);
209 }
210
211 t += sizeof(struct Nuitka_CellObject *);
212
213 break;
214 }
215 case NUITKA_TYPE_DESCRIPTION_NULL: {
216 break;
217 }
218 case NUITKA_TYPE_DESCRIPTION_BOOL: {
219 int value = *(int *)t;
220 t += sizeof(int);
221 switch ((nuitka_bool)value) {
222 case NUITKA_BOOL_TRUE: {
223 DICT_SET_ITEM(result, *var_names, Py_True);
224 break;
225 }
226 case NUITKA_BOOL_FALSE: {
227 DICT_SET_ITEM(result, *var_names, Py_False);
228 break;
229 }
230 default:
231 break;
232 }
233 break;
234 }
235 default:
236 assert(false);
237 }
238
239 w += 1;
240 var_names += 1;
241 }
242
243 return result;
244 }
245}
246
247static PyObject *_Nuitka_Frame_get_lineno(PyObject *self, void *data) {
248 assert(Nuitka_Frame_CheckExact(self));
249 CHECK_OBJECT(self);
250 assert(_PyObject_GC_IS_TRACKED(self));
251
252 struct Nuitka_FrameObject *frame = (struct Nuitka_FrameObject *)self;
253 return Nuitka_PyInt_FromLong(frame->m_frame.f_lineno);
254}
255
256static PyObject *_Nuitka_Frame_get_trace(PyObject *self, void *data) {
257 assert(Nuitka_Frame_CheckExact(self));
258 CHECK_OBJECT(self);
259 assert(_PyObject_GC_IS_TRACKED(self));
260
261 struct Nuitka_FrameObject *frame = (struct Nuitka_FrameObject *)self;
262 PyObject *result = frame->m_frame.f_trace;
263 Py_INCREF(result);
264 return result;
265}
266
267static int _Nuitka_Frame_set_trace(PyObject *self, PyObject *value, void *data) {
268 assert(Nuitka_Frame_CheckExact(self));
269 CHECK_OBJECT(self);
270 assert(_PyObject_GC_IS_TRACKED(self));
271#if !defined(_NUITKA_DEPLOYMENT_MODE) && !defined(_NUITKA_NO_DEPLOYMENT_FRAME_USELESS_SET_TRACE)
272 if (value == Py_None) {
273 return 0;
274 } else {
275 PyThreadState *tstate = PyThreadState_GET();
276
277 SET_CURRENT_EXCEPTION_TYPE0_STR(
278 tstate, PyExc_RuntimeError,
279 "f_trace is not writable in Nuitka, ignore with '--no-deployment-flag=frame-useless-set-trace'");
280 return -1;
281 }
282#else
283 return 0;
284#endif
285}
286
287#if PYTHON_VERSION >= 0x370
288static PyObject *_Nuitka_Frame_get_trace_lines(PyObject *self, void *data) {
289 assert(Nuitka_Frame_CheckExact(self));
290 CHECK_OBJECT(self);
291 assert(_PyObject_GC_IS_TRACKED(self));
292
293 PyObject *result = Py_False;
294 Py_INCREF_IMMORTAL(result);
295 return result;
296}
297
298static int _Nuitka_Frame_set_trace_lines(PyObject *self, PyObject *value, void *data) {
299 assert(Nuitka_Frame_CheckExact(self));
300 CHECK_OBJECT(self);
301 assert(_PyObject_GC_IS_TRACKED(self));
302
303 PyThreadState *tstate = PyThreadState_GET();
304
305 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_RuntimeError, "f_trace_lines is not writable in Nuitka");
306 return -1;
307}
308
309static PyObject *_Nuitka_Frame_get_trace_opcodes(PyObject *self, void *data) {
310 assert(Nuitka_Frame_CheckExact(self));
311 CHECK_OBJECT(self);
312 assert(_PyObject_GC_IS_TRACKED(self));
313
314 PyObject *result = Py_False;
315 Py_INCREF_IMMORTAL(result);
316 return result;
317}
318
319static int _Nuitka_Frame_set_trace_opcodes(PyObject *self, PyObject *value, void *data) {
320 assert(Nuitka_Frame_CheckExact(self));
321 CHECK_OBJECT(self);
322 assert(_PyObject_GC_IS_TRACKED(self));
323
324 PyThreadState *tstate = PyThreadState_GET();
325
326 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_RuntimeError, "f_trace_opcodes is not writable in Nuitka");
327 return -1;
328}
329#endif
330
331static PyGetSetDef Nuitka_Frame_tp_getset[] = {
332 {(char *)"f_locals", _Nuitka_Frame_get_locals, NULL, NULL},
333 {(char *)"f_lineno", _Nuitka_Frame_get_lineno, NULL, NULL},
334 {(char *)"f_trace", _Nuitka_Frame_get_trace, _Nuitka_Frame_set_trace, NULL},
335#if PYTHON_VERSION < 0x300
336 {(char *)"f_restricted", _Nuitka_Frame_get_restricted, NULL, NULL},
337 {(char *)"f_exc_traceback", _Nuitka_Frame_get_exc_traceback, _Nuitka_Frame_set_exc_traceback, NULL},
338 {(char *)"f_exc_type", _Nuitka_Frame_get_exc_type, _Nuitka_Frame_set_exc_type, NULL},
339 {(char *)"f_exc_value", _Nuitka_Frame_get_exc_value, _Nuitka_Frame_set_exc_value, NULL},
340#endif
341#if PYTHON_VERSION >= 0x370
342 {(char *)"f_trace_lines", _Nuitka_Frame_get_trace_lines, _Nuitka_Frame_set_trace_lines, NULL},
343 {(char *)"f_trace_opcodes", _Nuitka_Frame_get_trace_opcodes, _Nuitka_Frame_set_trace_opcodes, NULL},
344#endif
345 {NULL}};
346
347// tp_repr slot, decide how a function shall be output
348static PyObject *Nuitka_Frame_tp_repr(struct Nuitka_FrameObject *nuitka_frame) {
349 assert(Nuitka_Frame_CheckExact((PyObject *)nuitka_frame));
350 CHECK_OBJECT((PyObject *)nuitka_frame);
351 assert(_PyObject_GC_IS_TRACKED(nuitka_frame));
352
353#if PYTHON_VERSION >= 0x370
354 PyCodeObject *code_object = Nuitka_GetFrameCodeObject(nuitka_frame);
355 return Nuitka_String_FromFormat("<compiled_frame at %p, file %R, line %d, code %S>", nuitka_frame,
356 code_object->co_filename, Nuitka_GetFrameLineNumber(nuitka_frame),
357 code_object->co_name);
358#elif _DEBUG_FRAME || _DEBUG_REFRAME || _DEBUG_EXCEPTIONS
359 PyCodeObject *code_object = Nuitka_GetFrameCodeObject(nuitka_frame);
360 return Nuitka_String_FromFormat("<compiled_frame object for %s at %p>",
361 Nuitka_String_AsString(code_object->co_name), nuitka_frame);
362#else
363 return Nuitka_String_FromFormat("<compiled_frame object at %p>", nuitka_frame);
364#endif
365}
366
367static void Nuitka_Frame_tp_clear(struct Nuitka_FrameObject *frame) {
368 if (frame->m_type_description) {
369 char const *w = frame->m_type_description;
370 char const *t = frame->m_locals_storage;
371
372 while (*w != 0) {
373 switch (*w) {
374 case NUITKA_TYPE_DESCRIPTION_OBJECT:
375 case NUITKA_TYPE_DESCRIPTION_OBJECT_PTR:
376 case NUITKA_TYPE_DESCRIPTION_NILONG: {
377 PyObject *value = *(PyObject **)t;
378 CHECK_OBJECT_X(value);
379
380 Py_XDECREF(value);
381
382 t += sizeof(PyObject *);
383
384 break;
385 }
386 case NUITKA_TYPE_DESCRIPTION_CELL: {
387 struct Nuitka_CellObject *value = *(struct Nuitka_CellObject **)t;
388 assert(Nuitka_Cell_Check((PyObject *)value));
389 CHECK_OBJECT(value);
390
391 Py_DECREF(value);
392
393 t += sizeof(struct Nuitka_CellObject *);
394
395 break;
396 }
397 case NUITKA_TYPE_DESCRIPTION_NULL: {
398 break;
399 }
400 case NUITKA_TYPE_DESCRIPTION_BOOL: {
401 t += sizeof(int);
402
403 break;
404 }
405 default:
406 assert(false);
407 }
408
409 w += 1;
410 }
411
412 frame->m_type_description = NULL;
413 }
414}
415
416// Freelist setup
417#define MAX_FRAME_FREE_LIST_COUNT 100
418static struct Nuitka_FrameObject *free_list_frames = NULL;
419static int free_list_frames_count = 0;
420
421static void Nuitka_Frame_tp_dealloc(struct Nuitka_FrameObject *nuitka_frame) {
422#if _DEBUG_REFCOUNTS
423 count_active_Nuitka_Frame_Type -= 1;
424 count_released_Nuitka_Frame_Type += 1;
425#endif
426
427#ifndef __NUITKA_NO_ASSERT__
428 // Save the current exception, if any, we must to not corrupt it.
429 PyThreadState *tstate = PyThreadState_GET();
430
431 struct Nuitka_ExceptionPreservationItem saved_exception_state1;
432 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
433 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
434#endif
435
436 Nuitka_GC_UnTrack(nuitka_frame);
437
438 PyFrameObject *frame = &nuitka_frame->m_frame;
439#if PYTHON_VERSION < 0x3b0
440 PyFrameObject *locals_owner = frame;
441#else
442 _PyInterpreterFrame *locals_owner = &nuitka_frame->m_interpreter_frame;
443#endif
444
445 assert(Nuitka_GC_IS_TRACKED_X((PyObject *)frame->f_back));
446 Py_XDECREF(frame->f_back);
447 Py_DECREF(locals_owner->f_builtins);
448 Py_DECREF(locals_owner->f_globals);
449 Py_XDECREF(locals_owner->f_locals);
450
451#if PYTHON_VERSION < 0x370
452 Py_XDECREF(frame->f_exc_type);
453 Py_XDECREF(frame->f_exc_value);
454 Py_XDECREF(frame->f_exc_traceback);
455#endif
456
457 Nuitka_Frame_tp_clear(nuitka_frame);
458
459 if (Py_REFCNT(nuitka_frame) > 0) {
460 Py_SET_REFCNT(nuitka_frame, Py_REFCNT(nuitka_frame) - 1);
461 if (Py_REFCNT(nuitka_frame) >= 1) {
462 // TODO: Allow this in debug mode, for now we would like to reproduce it.
463 assert(false);
464 return;
465 }
466 }
467
468#if PYTHON_VERSION >= 0x3b0
469 // Restore from backup, see header comment for the field "m_ob_size" to get
470 // it.
471 Py_SET_SIZE(nuitka_frame, nuitka_frame->m_ob_size);
472#endif
473
474 releaseToFreeList(free_list_frames, nuitka_frame, MAX_FRAME_FREE_LIST_COUNT);
475
476#ifndef __NUITKA_NO_ASSERT__
477 struct Nuitka_ExceptionPreservationItem saved_exception_state2;
478 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
479 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
480
481 ASSERT_SAME_EXCEPTION_STATE(&saved_exception_state1, &saved_exception_state2);
482#endif
483}
484
485static int Nuitka_Frame_tp_traverse(struct Nuitka_FrameObject *frame, visitproc visit, void *arg) {
486 assert(Nuitka_Frame_CheckExact((PyObject *)frame));
487 CHECK_OBJECT((PyObject *)frame);
488 assert(_PyObject_GC_IS_TRACKED(frame));
489
490 Py_VISIT(frame->m_frame.f_back);
491
492#if PYTHON_VERSION < 0x3b0
493 PyFrameObject *locals_owner = &frame->m_frame;
494#else
495 _PyInterpreterFrame *locals_owner = &frame->m_interpreter_frame;
496#endif
497
498 Py_VISIT(locals_owner->f_builtins);
499 Py_VISIT(locals_owner->f_globals);
500 // Py_VISIT(locals_owner->f_locals);
501
502#if PYTHON_VERSION < 0x370
503 Py_VISIT(frame->m_frame.f_exc_type);
504 Py_VISIT(frame->m_frame.f_exc_value);
505 Py_VISIT(frame->m_frame.f_exc_traceback);
506#endif
507
508 // Traverse attached locals too.
509 char const *w = frame->m_type_description;
510 char const *t = frame->m_locals_storage;
511
512 while (w != NULL && *w != 0) {
513 switch (*w) {
514 case NUITKA_TYPE_DESCRIPTION_OBJECT:
515 case NUITKA_TYPE_DESCRIPTION_OBJECT_PTR: {
516 PyObject *value = *(PyObject **)t;
517 CHECK_OBJECT_X(value);
518
519 Py_VISIT(value);
520 t += sizeof(PyObject *);
521
522 break;
523 }
524 case NUITKA_TYPE_DESCRIPTION_CELL: {
525 struct Nuitka_CellObject *value = *(struct Nuitka_CellObject **)t;
526 assert(Nuitka_Cell_Check((PyObject *)value));
527 CHECK_OBJECT(value);
528
529 Py_VISIT(value);
530
531 t += sizeof(struct Nuitka_CellObject *);
532
533 break;
534 }
535 case NUITKA_TYPE_DESCRIPTION_NULL: {
536 break;
537 }
538 case NUITKA_TYPE_DESCRIPTION_BOOL: {
539 t += sizeof(int);
540
541 break;
542 }
543 default:
544 NUITKA_CANNOT_GET_HERE("invalid type description");
545 assert(false);
546 }
547
548 w += 1;
549 }
550
551 return 0;
552}
553
554#if PYTHON_VERSION >= 0x300
555
556static PyObject *Nuitka_GetFrameGenerator(struct Nuitka_FrameObject *nuitka_frame) {
557#if PYTHON_VERSION < 0x3b0
558 return nuitka_frame->m_frame.f_gen;
559#else
560 return nuitka_frame->m_generator;
561#endif
562}
563
564static PyObject *Nuitka_Frame_clear(struct Nuitka_FrameObject *frame, PyObject *unused) {
565 assert(Nuitka_Frame_CheckExact((PyObject *)frame));
566 CHECK_OBJECT((PyObject *)frame);
567 assert(_PyObject_GC_IS_TRACKED(frame));
568
569 PyThreadState *tstate = PyThreadState_GET();
570
571 if (Nuitka_Frame_IsExecuting(frame)) {
572 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_RuntimeError, "cannot clear an executing frame");
573
574 return NULL;
575 }
576
577#if PYTHON_VERSION >= 0x3b0
578 if (frame->m_frame_state == FRAME_COMPLETED) {
579 Nuitka_Frame_tp_clear(frame);
580
581 Py_RETURN_NONE;
582 }
583
584 if (frame->m_frame_state == FRAME_EXECUTING) {
585 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_RuntimeError, "cannot clear an executing frame");
586 return NULL;
587 }
588#endif
589
590#if PYTHON_VERSION >= 0x300
591 // For frames that are closed, we also need to close the generator.
592 PyObject *f_gen = Nuitka_GetFrameGenerator(frame);
593 if (f_gen != NULL) {
594 CHECK_OBJECT(f_gen);
595
596 Py_INCREF(frame);
597
598 bool close_exception;
599
600 if (Nuitka_Generator_Check(f_gen)) {
601 struct Nuitka_GeneratorObject *generator = (struct Nuitka_GeneratorObject *)f_gen;
602 Nuitka_SetFrameGenerator(frame, NULL);
603
604 close_exception = !_Nuitka_Generator_close(tstate, generator);
605 }
606#if PYTHON_VERSION >= 0x350
607 else if (Nuitka_Coroutine_Check(f_gen)) {
608 struct Nuitka_CoroutineObject *coroutine = (struct Nuitka_CoroutineObject *)f_gen;
609 Nuitka_SetFrameGenerator(frame, NULL);
610
611 close_exception = !_Nuitka_Coroutine_close(tstate, coroutine);
612 }
613#endif
614#if PYTHON_VERSION >= 0x360
615 else if (Nuitka_Asyncgen_Check(f_gen)) {
616 struct Nuitka_AsyncgenObject *asyncgen = (struct Nuitka_AsyncgenObject *)f_gen;
617 Nuitka_SetFrameGenerator(frame, NULL);
618
619 close_exception = !_Nuitka_Asyncgen_close(tstate, asyncgen);
620 }
621#endif
622 else {
623 // Compiled frames should only have our types, so this ought to not happen.
624 assert(false);
625
626 Nuitka_SetFrameGenerator(frame, NULL);
627
628 close_exception = false;
629 }
630
631 if (unlikely(close_exception)) {
632 PyErr_WriteUnraisable(f_gen);
633 }
634
635 Py_DECREF(frame);
636 }
637#endif
638
639 Nuitka_Frame_tp_clear(frame);
640
641 Py_RETURN_NONE;
642}
643
644#endif
645
646static inline Py_ssize_t Nuitka_Frame_GetSize(struct Nuitka_FrameObject *frame) {
647 assert(Nuitka_Frame_CheckExact((PyObject *)frame));
648 CHECK_OBJECT((PyObject *)frame);
649 assert(_PyObject_GC_IS_TRACKED(frame));
650
651#if PYTHON_VERSION < 0x3b0
652 return Py_SIZE(frame);
653#else
654 return frame->m_ob_size;
655#endif
656}
657
658static PyObject *Nuitka_Frame_sizeof(struct Nuitka_FrameObject *frame, PyObject *unused) {
659 assert(Nuitka_Frame_CheckExact((PyObject *)frame));
660 CHECK_OBJECT((PyObject *)frame);
661 assert(_PyObject_GC_IS_TRACKED(frame));
662
663 return PyInt_FromSsize_t(sizeof(struct Nuitka_FrameObject) + Py_SIZE(frame));
664}
665
666static PyMethodDef Nuitka_Frame_methods[] = {
667#if PYTHON_VERSION >= 0x300
668 {"clear", (PyCFunction)Nuitka_Frame_clear, METH_NOARGS, "F.clear(): clear most references held by the frame"},
669#endif
670 {"__sizeof__", (PyCFunction)Nuitka_Frame_sizeof, METH_NOARGS, "F.__sizeof__() -> size of F in memory, in bytes"},
671 {NULL, NULL}};
672
673PyTypeObject Nuitka_Frame_Type = {
674 PyVarObject_HEAD_INIT(NULL, 0) "compiled_frame",
675 sizeof(struct Nuitka_FrameObject),
676 1,
677 (destructor)Nuitka_Frame_tp_dealloc, // tp_dealloc
678 0, // tp_print
679 0, // tp_getattr
680 0, // tp_setattr
681 0, // tp_compare
682 (reprfunc)Nuitka_Frame_tp_repr, // tp_repr
683 0, // tp_as_number
684 0, // tp_as_sequence
685 0, // tp_as_mapping
686 0, // tp_hash
687 0, // tp_call
688 0, // tp_str
689 0, // tp_getattro (PyObject_GenericGetAttr)
690 0, // tp_setattro (PyObject_GenericSetAttr)
691 0, // tp_as_buffer
692 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
693 0, // tp_doc
694 (traverseproc)Nuitka_Frame_tp_traverse, // tp_traverse
695 (inquiry)Nuitka_Frame_tp_clear, // tp_clear
696 0, // tp_richcompare
697 0, // tp_weaklistoffset
698 0, // tp_iter
699 0, // tp_iternext
700 Nuitka_Frame_methods, // tp_methods
701 Nuitka_Frame_members, // tp_members
702 Nuitka_Frame_tp_getset, // tp_getset
703 0, // tp_base
704 0, // tp_dict
705};
706
707void _initCompiledFrameType(void) {
708 assert(Nuitka_Frame_Type.tp_doc != PyFrame_Type.tp_doc || PyFrame_Type.tp_doc == NULL);
709 assert(Nuitka_Frame_Type.tp_traverse != PyFrame_Type.tp_traverse);
710 assert(Nuitka_Frame_Type.tp_clear != PyFrame_Type.tp_clear || PyFrame_Type.tp_clear == NULL);
711 assert(Nuitka_Frame_Type.tp_richcompare != PyFrame_Type.tp_richcompare || PyFrame_Type.tp_richcompare == NULL);
712 assert(Nuitka_Frame_Type.tp_weaklistoffset != PyFrame_Type.tp_weaklistoffset ||
713 PyFrame_Type.tp_weaklistoffset == 0);
714 assert(Nuitka_Frame_Type.tp_iter != PyFrame_Type.tp_iter || PyFrame_Type.tp_iter == NULL);
715 assert(Nuitka_Frame_Type.tp_iternext != PyFrame_Type.tp_iternext || PyFrame_Type.tp_iternext == NULL);
716 assert(Nuitka_Frame_Type.tp_methods != PyFrame_Type.tp_methods);
717 assert(Nuitka_Frame_Type.tp_members != PyFrame_Type.tp_members);
718 assert(Nuitka_Frame_Type.tp_getset != PyFrame_Type.tp_getset);
719
720 assert(Nuitka_Frame_Type.tp_descr_get != PyFrame_Type.tp_descr_get || PyFrame_Type.tp_descr_get == NULL);
721
722 assert(Nuitka_Frame_Type.tp_descr_set != PyFrame_Type.tp_descr_set || PyFrame_Type.tp_descr_set == NULL);
723 assert(Nuitka_Frame_Type.tp_dictoffset != PyFrame_Type.tp_dictoffset || PyFrame_Type.tp_dictoffset == 0);
724 // TODO: These get changed and into the same thing, not sure what to compare against, project something
725 // assert(Nuitka_Frame_Type.tp_dict != PyFrame_Type.tp_dict);
726 // assert(Nuitka_Frame_Type.tp_init != PyFrame_Type.tp_init || PyFrame_Type.tp_init == NULL);
727 // assert(Nuitka_Frame_Type.tp_alloc != PyFrame_Type.tp_alloc || PyFrame_Type.tp_alloc == NULL);
728 // assert(Nuitka_Frame_Type.tp_new != PyFrame_Type.tp_new || PyFrame_Type.tp_new == NULL);
729 // assert(Nuitka_Frame_Type.tp_free != PyFrame_Type.tp_free || PyFrame_Type.tp_free == NULL);
730 // assert(Nuitka_Frame_Type.tp_weaklist != PyFrame_Type.tp_weaklist);
731 assert(Nuitka_Frame_Type.tp_bases != PyFrame_Type.tp_bases);
732 assert(Nuitka_Frame_Type.tp_mro != PyFrame_Type.tp_mro);
733 assert(Nuitka_Frame_Type.tp_cache != PyFrame_Type.tp_cache || PyFrame_Type.tp_cache == NULL);
734 assert(Nuitka_Frame_Type.tp_subclasses != PyFrame_Type.tp_subclasses || PyFrame_Type.tp_cache == NULL);
735 assert(Nuitka_Frame_Type.tp_del != PyFrame_Type.tp_del || PyFrame_Type.tp_del == NULL);
736#if PYTHON_VERSION >= 0x300
737 assert(Nuitka_Frame_Type.tp_finalize != PyFrame_Type.tp_finalize || PyFrame_Type.tp_finalize == NULL);
738#endif
739 Nuitka_PyType_Ready(&Nuitka_Frame_Type, &PyFrame_Type, true, true, false, false, false);
740
741 // These are to be used interchangeably. Make sure that's true.
742 assert(offsetof(struct Nuitka_FrameObject, m_frame) == 0);
743}
744
745static struct Nuitka_FrameObject *_MAKE_COMPILED_FRAME(PyCodeObject *code, PyObject *module, PyObject *f_locals,
746 Py_ssize_t locals_size) {
747 CHECK_CODE_OBJECT(code);
748 CHECK_OBJECT(module);
749
750#if _DEBUG_REFCOUNTS
751 count_active_Nuitka_Frame_Type += 1;
752 count_allocated_Nuitka_Frame_Type += 1;
753#endif
754
755 PyObject *globals = ((PyModuleObject *)module)->md_dict;
756 CHECK_OBJECT(globals);
757
758 assert(PyDict_Check(globals));
759
760 struct Nuitka_FrameObject *result;
761
762 // Macro to assign result memory from GC or free list.
763 allocateFromFreeList(free_list_frames, struct Nuitka_FrameObject, Nuitka_Frame_Type, locals_size);
764
765 result->m_type_description = NULL;
766
767 PyFrameObject *frame = &result->m_frame;
768 // Globals and locals are stored differently before Python 3.11
769#if PYTHON_VERSION < 0x3b0
770 PyFrameObject *locals_owner = frame;
771#else
772 _PyInterpreterFrame *locals_owner = &result->m_interpreter_frame;
773#endif
774
775#if PYTHON_VERSION < 0x3d0
776 locals_owner->f_code = code;
777#elif PYTHON_VERSION < 0x3e0
778 locals_owner->f_executable = (PyObject *)code;
779#else
780 // TODO: Why is our code object not immortal?
781 locals_owner->f_executable = _PyStackRef_FromPyObjectNew((PyObject *)code);
782#endif
783
784 frame->f_trace = Py_None;
785
786#if PYTHON_VERSION < 0x370
787 frame->f_exc_type = NULL;
788 frame->f_exc_value = NULL;
789 frame->f_exc_traceback = NULL;
790#else
791 frame->f_trace_lines = 0;
792 frame->f_trace_opcodes = 0;
793#endif
794
795#if PYTHON_VERSION >= 0x3b0
796 result->m_ob_size = Py_SIZE(result);
797#endif
798 frame->f_back = NULL;
799
800 Py_INCREF(dict_builtin);
801 locals_owner->f_builtins = (PyObject *)dict_builtin;
802
803 Py_INCREF(globals);
804 locals_owner->f_globals = globals;
805
806 // Note: Reference taking happens in calling function.
807 CHECK_OBJECT_X(f_locals);
808 locals_owner->f_locals = f_locals;
809
810#if PYTHON_VERSION < 0x300
811 frame->f_tstate = PyThreadState_GET();
812#endif
813
814#if PYTHON_VERSION < 0x3b0
815 frame->f_lasti = -1;
816 frame->f_iblock = 0; // spell-checker: ignore iblock
817#endif
818
819 frame->f_lineno = code->co_firstlineno;
820
821#if PYTHON_VERSION >= 0x300
822 Nuitka_SetFrameGenerator(result, NULL);
823
824 Nuitka_Frame_MarkAsNotExecuting(result);
825#endif
826
827#if PYTHON_VERSION >= 0x3b0
828 result->m_interpreter_frame.frame_obj = &result->m_frame;
829 result->m_interpreter_frame.owner = FRAME_OWNED_BY_GENERATOR;
830#if PYTHON_VERSION >= 0x3e0
831 result->m_interpreter_frame.f_funcobj = PyStackRef_NULL; // spell-checker: ignore funcobj
832#elif PYTHON_VERSION >= 0x3c0
833 result->m_interpreter_frame.f_funcobj = NULL; // spell-checker: ignore funcobj
834#else
835 result->m_interpreter_frame.f_func = NULL;
836#endif
837#if PYTHON_VERSION < 0x3d0
838 result->m_interpreter_frame.prev_instr = _PyCode_CODE(code);
839#else
840 result->m_interpreter_frame.instr_ptr = _PyCode_CODE(code);
841#endif
842 result->m_frame.f_frame = &result->m_interpreter_frame;
843
844 assert(!_PyFrame_IsIncomplete(&result->m_interpreter_frame));
845#endif
846
847 Nuitka_GC_Track(result);
848 return result;
849}
850
851struct Nuitka_FrameObject *MAKE_MODULE_FRAME(PyCodeObject *code, PyObject *module) {
852 PyObject *f_locals = ((PyModuleObject *)module)->md_dict;
853 Py_INCREF(f_locals);
854
855 return _MAKE_COMPILED_FRAME(code, module, f_locals, 0);
856}
857
858struct Nuitka_FrameObject *MAKE_FUNCTION_FRAME(PyThreadState *tstate, PyCodeObject *code, PyObject *module,
859 Py_ssize_t locals_size) {
860 PyObject *f_locals;
861
862 if (likely((code->co_flags & CO_OPTIMIZED) == CO_OPTIMIZED)) {
863 f_locals = NULL;
864 } else {
865 PyObject *kw_pairs[2] = {const_str_plain___module__, MODULE_NAME0(tstate, module)};
866 f_locals = MAKE_DICT(kw_pairs, 1);
867 }
868
869 return _MAKE_COMPILED_FRAME(code, module, f_locals, locals_size);
870}
871
872struct Nuitka_FrameObject *MAKE_CLASS_FRAME(PyThreadState *tstate, PyCodeObject *code, PyObject *module,
873 PyObject *f_locals, Py_ssize_t locals_size) {
874 // The frame template sets f_locals on usage itself, need not create it that way.
875 if (f_locals == NULL) {
876 PyObject *kw_pairs[2] = {const_str_plain___module__, MODULE_NAME0(tstate, module)};
877 f_locals = MAKE_DICT(kw_pairs, 1);
878 } else {
879 Py_INCREF(f_locals);
880 }
881
882 return _MAKE_COMPILED_FRAME(code, module, f_locals, locals_size);
883}
884
885// This is the backend of MAKE_CODE_OBJECT macro.
886PyCodeObject *makeCodeObject(PyObject *filename, int line, int flags, PyObject *function_name,
887#if PYTHON_VERSION >= 0x3b0
888 PyObject *function_qualname,
889#endif
890 PyObject *arg_names, PyObject *free_vars, int arg_count
891#if PYTHON_VERSION >= 0x300
892 ,
893 int kw_only_count
894#endif
895#if PYTHON_VERSION >= 0x380
896 ,
897 int pos_only_count
898#endif
899) {
900
901 if (filename == Py_None) {
902 filename = const_str_empty;
903 }
904
905 // TODO: We don't do that anymore once new-code-objects
906 // is the default, then we don't need to pass it, since
907 // we create them incomplete anyway.
908 CHECK_OBJECT(filename);
909 assert(Nuitka_StringOrUnicode_CheckExact(filename));
910
911 CHECK_OBJECT(function_name);
912 assert(Nuitka_String_CheckExact(function_name));
913
914#if PYTHON_VERSION < 0x300
915 PyObject *filename_str = NULL;
916
917 // TODO: Memory leak of filename, it might be intended transferred to the
918 // code object by using code.
919 if (PyUnicode_CheckExact(filename)) {
920 filename_str = PyUnicode_AsUTF8String(filename);
921 filename = filename_str;
922 } else {
923 filename_str = filename;
924 Py_INCREF(filename);
925 }
926#endif
927
928 if (arg_names == NULL || arg_names == Py_None) {
929 arg_names = const_tuple_empty;
930 }
931 CHECK_OBJECT(arg_names);
932 assert(PyTuple_Check(arg_names));
933
934 if (free_vars == NULL || free_vars == Py_None) {
935 free_vars = const_tuple_empty;
936 }
937 CHECK_OBJECT(free_vars);
938 assert(PyTuple_Check(free_vars));
939
940 // The PyCode_New has funny code that interns, mutating the tuple that owns
941 // it. Really serious non-immutable shit. We have triggered that changes
942 // behind our back in the past.
943#ifndef __NUITKA_NO_ASSERT__
944 // TODO: Reactivate once code object creation becomes un-streaming driven
945 // and we can pass the extra args with no worries.
946
947 // Py_hash_t hash = DEEP_HASH(arg_names);
948#endif
949
950 // spell-checker: ignore lnotab
951#if PYTHON_VERSION < 0x300
952 PyObject *code = const_str_empty;
953 PyObject *lnotab = const_str_empty;
954 PyObject *consts = const_tuple_empty;
955 PyObject *names = const_tuple_empty;
956 int stacksize = 0;
957#elif PYTHON_VERSION < 0x3b0
958 PyObject *code = const_bytes_empty;
959 PyObject *lnotab = const_bytes_empty;
960 PyObject *consts = const_tuple_empty;
961 PyObject *names = const_tuple_empty;
962 int stacksize = 0;
963#else
964 // Our code object needs to be recognizable, and Python doesn't store the
965 // length anymore, so we need a non-empty one.
966 static PyObject *empty_code = NULL;
967 static PyObject *lnotab = NULL;
968 static PyObject *consts = NULL;
969 static PyObject *names = NULL;
970 // TODO: Seems removable.
971 static PyObject *exception_table = NULL;
972 static int stacksize = 0;
973
974 if (empty_code == NULL) {
975 // Only needed once here.
976 PyThreadState *tstate = PyThreadState_GET();
977
978 PyObject *empty_code_module_object = Py_CompileString(
979 "def empty(): raise RuntimeError('Compiled function bytecode used')", "<exec>", Py_file_input);
980 NUITKA_MAY_BE_UNUSED PyObject *module =
981 PyImport_ExecCodeModule("nuitka_empty_function", empty_code_module_object);
982 CHECK_OBJECT(module);
983
984 PyObject *empty_function = PyObject_GetAttrString(module, "empty");
985 CHECK_OBJECT(empty_function);
986 PyObject *empty_code_object = PyObject_GetAttrString(empty_function, "__code__");
987 CHECK_OBJECT(empty_code_object);
988
989 NUITKA_MAY_BE_UNUSED bool bool_res = Nuitka_DelModuleString(tstate, "nuitka_empty_function");
990 assert(bool_res != false);
991
992 empty_code = PyObject_GetAttrString(empty_code_object, "co_code");
993 CHECK_OBJECT(empty_code);
994#if PYTHON_VERSION >= 0x3c0
995 lnotab = ((PyCodeObject *)empty_code_object)->co_linetable; // spell-checker: ignore linetable
996#else
997 lnotab = PyObject_GetAttrString(empty_code_object, "co_lnotab");
998 CHECK_OBJECT(lnotab);
999#endif
1000 consts = PyObject_GetAttrString(empty_code_object, "co_consts");
1001 CHECK_OBJECT(consts);
1002 names = PyObject_GetAttrString(empty_code_object, "co_names");
1003 CHECK_OBJECT(names);
1004 exception_table = PyObject_GetAttrString(empty_code_object, "co_exceptiontable");
1005 CHECK_OBJECT(exception_table);
1006
1007 stacksize = (int)PyLong_AsLong(PyObject_GetAttrString(empty_code_object, "co_stacksize"));
1008 }
1009
1010 PyObject *code = empty_code;
1011 CHECK_OBJECT(empty_code);
1012 CHECK_OBJECT(lnotab);
1013 CHECK_OBJECT(consts);
1014 CHECK_OBJECT(names);
1015 CHECK_OBJECT(exception_table);
1016#endif
1017
1018 // For Python 3.11 this value is checked, even if not used.
1019#if PYTHON_VERSION >= 0x3b0
1020 int nlocals = (int)PyTuple_GET_SIZE(arg_names);
1021#else
1022 int nlocals = 0;
1023#endif
1024
1025 // Not using PyCode_NewEmpty, it doesn't given us much beyond this
1026 // and is not available for Python2.
1027
1028#if PYTHON_VERSION >= 0x380
1029 PyCodeObject *result = PyCode_NewWithPosOnlyArgs(arg_count, // arg_count
1030#else
1031 PyCodeObject *result = PyCode_New(arg_count, // arg_count
1032#endif
1033
1034#if PYTHON_VERSION >= 0x300
1035#if PYTHON_VERSION >= 0x380
1036 pos_only_count, // pos-only count
1037#endif
1038 kw_only_count, // kw-only count
1039#endif
1040 nlocals, // nlocals
1041 stacksize, // stacksize
1042 flags, // flags
1043 code, // code (bytecode)
1044 consts, // consts (we are not going to be compatible)
1045 names, // names (we are not going to be compatible)
1046 arg_names, // var_names (we are not going to be compatible)
1047 free_vars, // free_vars
1048 const_tuple_empty, // cell_vars (we are not going to be compatible)
1049 filename, // filename
1050 function_name, // name
1051#if PYTHON_VERSION >= 0x3b0
1052 function_qualname, // qualname
1053#endif
1054 line, // first_lineno (offset of the code object)
1055 lnotab // lnotab (table to translate code object)
1056#if PYTHON_VERSION >= 0x3b0
1057 ,
1058 exception_table // exception_table
1059#endif
1060 );
1061
1062 // assert(DEEP_HASH(tstate, arg_names) == hash);
1063
1064#if PYTHON_VERSION < 0x300
1065 Py_DECREF(filename_str);
1066#endif
1067
1068 if (result == NULL) {
1069 PyErr_PrintEx(0);
1070 NUITKA_CANNOT_GET_HERE("Failed to create code object");
1071 }
1072
1073 return result;
1074}
1075
1076PyCodeObject *USE_CODE_OBJECT(PyThreadState *tstate, PyObject *code_object, PyObject *module_filename_obj) {
1077 assert(PyCode_Check(code_object));
1078 CHECK_OBJECT(module_filename_obj);
1079
1080 PyCodeObject *co = (PyCodeObject *)code_object;
1081 PyObject *old = co->co_filename;
1082
1083 if (old == const_str_empty) {
1084 // Set the filename, ignore the loss of a reference to empty string,
1085 // that's our singleton and immortal at least practically.
1086 co->co_filename = Py_NewRef(module_filename_obj);
1087
1088#if PYTHON_VERSION >= 0x3b0
1089 // Also, make sure the qualname is completed from the partial
1090 // name.
1091 if (co->co_qualname != co->co_name) {
1092 PyObject *w = UNICODE_CONCAT(tstate, co->co_qualname, const_str_dot);
1093 co->co_qualname = UNICODE_CONCAT(tstate, w, co->co_name);
1094 Py_DECREF(w);
1095 }
1096#endif
1097 }
1098
1099 return co;
1100}
1101
1102void Nuitka_Frame_AttachLocals(struct Nuitka_FrameObject *frame_object, char const *type_description, ...) {
1103 assert(Nuitka_Frame_CheckExact((PyObject *)frame_object));
1104 CHECK_OBJECT((PyObject *)frame_object);
1105 assert(_PyObject_GC_IS_TRACKED(frame_object));
1106 assertFrameObject(frame_object);
1107
1108#if _DEBUG_FRAME
1109 PRINT_FORMAT("Attaching to frame 0x%lx %s\n", frame_object,
1110 Nuitka_String_AsString(PyObject_Repr((PyObject *)Nuitka_Frame_GetCodeObject(&frame_object->m_frame))));
1111#endif
1112
1113 assert(frame_object->m_type_description == NULL);
1114
1115 // TODO: Do not call this if there is nothing to do. Instead make all the
1116 // places handle NULL pointer and recognize that there is nothing to do.
1117 // assert(type_description != NULL && assert(strlen(type_description)>0));
1118 if (type_description == NULL) {
1119 type_description = "";
1120 }
1121
1122 frame_object->m_type_description = type_description;
1123
1124 char const *w = type_description;
1125 char *t = frame_object->m_locals_storage;
1126
1127 va_list(ap);
1128 va_start(ap, type_description);
1129
1130 while (*w != 0) {
1131 switch (*w) {
1132 case NUITKA_TYPE_DESCRIPTION_OBJECT: {
1133 PyObject *value = va_arg(ap, PyObject *);
1134 memcpy(t, &value, sizeof(PyObject *));
1135 Py_XINCREF(value);
1136 t += sizeof(PyObject *);
1137
1138 break;
1139 }
1140 case NUITKA_TYPE_DESCRIPTION_OBJECT_PTR: {
1141 /* Note: We store the pointed object only, so this is only
1142 a shortcut for the calling side. */
1143 PyObject **value = va_arg(ap, PyObject **);
1144 CHECK_OBJECT_X(*value);
1145
1146 memcpy(t, value, sizeof(PyObject *));
1147
1148 Py_XINCREF(*value);
1149 t += sizeof(PyObject *);
1150
1151 break;
1152 }
1153 case NUITKA_TYPE_DESCRIPTION_CELL: {
1154 struct Nuitka_CellObject *value = va_arg(ap, struct Nuitka_CellObject *);
1155 assert(Nuitka_Cell_Check((PyObject *)value));
1156 CHECK_OBJECT(value);
1157 CHECK_OBJECT_X(value->ob_ref);
1158
1159 memcpy(t, &value, sizeof(struct Nuitka_CellObject *));
1160 // TODO: Reference count must become wrong here, should
1161 // be forced to one probably, or we should simply not
1162 // store cells, but their values. Take a ref off "value"
1163 // is probably not needed.
1164 // Py_SET_REFCNT((struct Nuitka_CellObject *)t, 1);
1165 Py_INCREF(value);
1166
1167 t += sizeof(struct Nuitka_CellObject *);
1168
1169 break;
1170 }
1171 case NUITKA_TYPE_DESCRIPTION_NULL: {
1172 NUITKA_MAY_BE_UNUSED void *value = va_arg(ap, struct Nuitka_CellObject *);
1173
1174 break;
1175 }
1176 case NUITKA_TYPE_DESCRIPTION_BOOL: {
1177 int value = va_arg(ap, int);
1178 memcpy(t, &value, sizeof(int));
1179
1180 t += sizeof(value);
1181
1182 break;
1183 }
1184 case NUITKA_TYPE_DESCRIPTION_NILONG: {
1185 nuitka_ilong value = va_arg(ap, nuitka_ilong);
1186 ENFORCE_NILONG_OBJECT_VALUE(&value);
1187
1188 CHECK_OBJECT(value.python_value);
1189 memcpy(t, &value.python_value, sizeof(PyObject *));
1190 Py_XINCREF(value.python_value);
1191 t += sizeof(PyObject *);
1192
1193 break;
1194 }
1195 default:
1196 NUITKA_CANNOT_GET_HERE("invalid type description");
1197 assert(false);
1198 }
1199
1200 w += 1;
1201 }
1202
1203 va_end(ap);
1204
1205 assert(t - frame_object->m_locals_storage <= Nuitka_Frame_GetSize(frame_object));
1206}
1207
1208// Make a dump of the active frame stack. For debugging purposes only.
1209#if _DEBUG_FRAME
1210void dumpFrameStack(void) {
1211 PyThreadState *tstate = PyThreadState_GET();
1212
1213 struct Nuitka_ExceptionPreservationItem saved_exception_state;
1214 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
1215
1216 int total = 0;
1217
1218#if PYTHON_VERSION < 0x3b0
1219 PyFrameObject *current = PyThreadState_GET()->frame;
1220 while (current != NULL) {
1221 total++;
1222 current = current->f_back;
1223 }
1224
1225 current = tstate->frame;
1226#else
1227 _PyCFrame *current = tstate->cframe;
1228 while (current != NULL) {
1229 total++;
1230 current = current->previous;
1231 }
1232
1233 current = tstate->cframe;
1234#endif
1235
1236 PRINT_STRING(">--------->\n");
1237
1238 while (current) {
1239#if PYTHON_VERSION < 0x3b0
1240 PyObject *current_repr = PyObject_Str((PyObject *)current);
1241 PyObject *code_repr = PyObject_Str((PyObject *)current->f_code);
1242#else
1243 PyObject *current_repr = NULL;
1244 if (current->current_frame->frame_obj != NULL) {
1245 current_repr = PyObject_Str((PyObject *)current->current_frame->frame_obj);
1246 } else {
1247 current_repr = const_str_empty;
1248 Py_INCREF(const_str_empty);
1249 }
1250 PyObject *code_repr = PyObject_Str((PyObject *)Nuitka_InterpreterFrame_GetCodeObject(current->current_frame));
1251#endif
1252
1253 PRINT_FORMAT("Frame stack %d: %s %d %s\n", total--, Nuitka_String_AsString(current_repr), Py_REFCNT(current),
1254 Nuitka_String_AsString(code_repr));
1255
1256 Py_DECREF(current_repr);
1257 Py_DECREF(code_repr);
1258
1259#if PYTHON_VERSION < 0x3b0
1260 current = current->f_back;
1261#else
1262 current = current->previous;
1263#endif
1264 }
1265
1266 PRINT_STRING(">---------<\n");
1267
1268 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
1269}
1270
1271static void PRINT_UNCOMPILED_FRAME(char const *prefix, PyFrameObject *frame) {
1272 PRINT_STRING(prefix);
1273 PRINT_STRING(" ");
1274
1275 if (frame) {
1276 PyObject *frame_str = PyObject_Str((PyObject *)frame);
1277 PRINT_ITEM(frame_str);
1278 Py_DECREF(frame_str);
1279
1280 PyObject *code_object_str = PyObject_Repr((PyObject *)Nuitka_Frame_GetCodeObject(frame));
1281 PRINT_ITEM(code_object_str);
1282 Py_DECREF(code_object_str);
1283
1284 PRINT_REFCOUNT((PyObject *)frame);
1285 } else {
1286 PRINT_STRING("<NULL> no frame");
1287 }
1288
1289 PRINT_NEW_LINE();
1290}
1291
1292void PRINT_COMPILED_FRAME(char const *prefix, struct Nuitka_FrameObject *frame) {
1293 return PRINT_UNCOMPILED_FRAME(prefix, &frame->m_frame);
1294}
1295
1296void PRINT_INTERPRETER_FRAME(char const *prefix, Nuitka_ThreadStateFrameType *frame) {
1297#if PYTHON_VERSION < 0x3b0
1298 PRINT_UNCOMPILED_FRAME(prefix, frame);
1299#else
1300 PRINT_STRING(prefix);
1301 PRINT_STRING(" ");
1302
1303 if (frame) {
1304 PRINT_FORMAT("0x%lx ", frame);
1305
1306 PyObject *code_object_str = PyObject_Repr((PyObject *)Nuitka_InterpreterFrame_GetCodeObject(frame));
1307 PRINT_ITEM(code_object_str);
1308 Py_DECREF(code_object_str);
1309 } else {
1310 PRINT_STRING("<NULL> no frame");
1311 }
1312
1313 PRINT_NEW_LINE();
1314#endif
1315}
1316
1317void PRINT_TOP_FRAME(char const *prefix) {
1318 PyThreadState *tstate = PyThreadState_GET();
1319
1320#if PYTHON_VERSION < 0x3b0
1321 PRINT_UNCOMPILED_FRAME(prefix, tstate->frame);
1322#else
1323 PRINT_INTERPRETER_FRAME(prefix, CURRENT_TSTATE_INTERPRETER_FRAME(tstate));
1324#endif
1325}
1326
1327#endif
1328// Part of "Nuitka", an optimizing Python compiler that is compatible and
1329// integrates with CPython, but also works on its own.
1330//
1331// Licensed under the Apache License, Version 2.0 (the "License");
1332// you may not use this file except in compliance with the License.
1333// You may obtain a copy of the License at
1334//
1335// http://www.apache.org/licenses/LICENSE-2.0
1336//
1337// Unless required by applicable law or agreed to in writing, software
1338// distributed under the License is distributed on an "AS IS" BASIS,
1339// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1340// See the License for the specific language governing permissions and
1341// limitations under the License.
Definition compiled_cell.h:14
Definition exceptions.h:712
Definition compiled_frame.h:117
Definition compiled_generator.h:41
Definition helpers.h:10
Definition ints.h:27