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#else
778 // TODO: Why is our code object not just immortal.
779 locals_owner->f_executable = (PyObject *)code;
780#endif
781
782 frame->f_trace = Py_None;
783
784#if PYTHON_VERSION < 0x370
785 frame->f_exc_type = NULL;
786 frame->f_exc_value = NULL;
787 frame->f_exc_traceback = NULL;
788#else
789 frame->f_trace_lines = 0;
790 frame->f_trace_opcodes = 0;
791#endif
792
793#if PYTHON_VERSION >= 0x3b0
794 result->m_ob_size = Py_SIZE(result);
795#endif
796 frame->f_back = NULL;
797
798 Py_INCREF(dict_builtin);
799 locals_owner->f_builtins = (PyObject *)dict_builtin;
800
801 Py_INCREF(globals);
802 locals_owner->f_globals = globals;
803
804 // Note: Reference taking happens in calling function.
805 CHECK_OBJECT_X(f_locals);
806 locals_owner->f_locals = f_locals;
807
808#if PYTHON_VERSION < 0x300
809 frame->f_tstate = PyThreadState_GET();
810#endif
811
812#if PYTHON_VERSION < 0x3b0
813 frame->f_lasti = -1;
814 frame->f_iblock = 0; // spell-checker: ignore iblock
815#endif
816
817 frame->f_lineno = code->co_firstlineno;
818
819#if PYTHON_VERSION >= 0x300
820 Nuitka_SetFrameGenerator(result, NULL);
821
822 Nuitka_Frame_MarkAsNotExecuting(result);
823#endif
824
825#if PYTHON_VERSION >= 0x3b0
826 result->m_interpreter_frame.frame_obj = &result->m_frame;
827 result->m_interpreter_frame.owner = FRAME_OWNED_BY_GENERATOR;
828#if PYTHON_VERSION >= 0x3c0
829 result->m_interpreter_frame.f_funcobj = NULL; // spell-checker: ignore funcobj
830#else
831 result->m_interpreter_frame.f_func = NULL;
832#endif
833#if PYTHON_VERSION < 0x3d0
834 result->m_interpreter_frame.prev_instr = _PyCode_CODE(code);
835#else
836 result->m_interpreter_frame.instr_ptr = _PyCode_CODE(code);
837#endif
838 result->m_frame.f_frame = &result->m_interpreter_frame;
839
840 assert(!_PyFrame_IsIncomplete(&result->m_interpreter_frame));
841#endif
842
843 Nuitka_GC_Track(result);
844 return result;
845}
846
847struct Nuitka_FrameObject *MAKE_MODULE_FRAME(PyCodeObject *code, PyObject *module) {
848 PyObject *f_locals = ((PyModuleObject *)module)->md_dict;
849 Py_INCREF(f_locals);
850
851 return _MAKE_COMPILED_FRAME(code, module, f_locals, 0);
852}
853
854struct Nuitka_FrameObject *MAKE_FUNCTION_FRAME(PyThreadState *tstate, PyCodeObject *code, PyObject *module,
855 Py_ssize_t locals_size) {
856 PyObject *f_locals;
857
858 if (likely((code->co_flags & CO_OPTIMIZED) == CO_OPTIMIZED)) {
859 f_locals = NULL;
860 } else {
861 PyObject *kw_pairs[2] = {const_str_plain___module__, MODULE_NAME0(tstate, module)};
862 f_locals = MAKE_DICT(kw_pairs, 1);
863 }
864
865 return _MAKE_COMPILED_FRAME(code, module, f_locals, locals_size);
866}
867
868struct Nuitka_FrameObject *MAKE_CLASS_FRAME(PyThreadState *tstate, PyCodeObject *code, PyObject *module,
869 PyObject *f_locals, Py_ssize_t locals_size) {
870 // The frame template sets f_locals on usage itself, need not create it that way.
871 if (f_locals == NULL) {
872 PyObject *kw_pairs[2] = {const_str_plain___module__, MODULE_NAME0(tstate, module)};
873 f_locals = MAKE_DICT(kw_pairs, 1);
874 } else {
875 Py_INCREF(f_locals);
876 }
877
878 return _MAKE_COMPILED_FRAME(code, module, f_locals, locals_size);
879}
880
881// This is the backend of MAKE_CODE_OBJECT macro.
882PyCodeObject *makeCodeObject(PyObject *filename, int line, int flags, PyObject *function_name,
883#if PYTHON_VERSION >= 0x3b0
884 PyObject *function_qualname,
885#endif
886 PyObject *arg_names, PyObject *free_vars, int arg_count
887#if PYTHON_VERSION >= 0x300
888 ,
889 int kw_only_count
890#endif
891#if PYTHON_VERSION >= 0x380
892 ,
893 int pos_only_count
894#endif
895) {
896
897 if (filename == Py_None) {
898 filename = const_str_empty;
899 }
900
901 // TODO: We don't do that anymore once new-code-objects
902 // is the default, then we don't need to pass it, since
903 // we create them incomplete anyway.
904 CHECK_OBJECT(filename);
905 assert(Nuitka_StringOrUnicode_CheckExact(filename));
906
907 CHECK_OBJECT(function_name);
908 assert(Nuitka_String_CheckExact(function_name));
909
910#if PYTHON_VERSION < 0x300
911 PyObject *filename_str = NULL;
912
913 // TODO: Memory leak of filename, it might be intended transferred to the
914 // code object by using code.
915 if (PyUnicode_CheckExact(filename)) {
916 filename_str = PyUnicode_AsUTF8String(filename);
917 filename = filename_str;
918 } else {
919 filename_str = filename;
920 Py_INCREF(filename);
921 }
922#endif
923
924 if (arg_names == NULL || arg_names == Py_None) {
925 arg_names = const_tuple_empty;
926 }
927 CHECK_OBJECT(arg_names);
928 assert(PyTuple_Check(arg_names));
929
930 if (free_vars == NULL || free_vars == Py_None) {
931 free_vars = const_tuple_empty;
932 }
933 CHECK_OBJECT(free_vars);
934 assert(PyTuple_Check(free_vars));
935
936 // The PyCode_New has funny code that interns, mutating the tuple that owns
937 // it. Really serious non-immutable shit. We have triggered that changes
938 // behind our back in the past.
939#ifndef __NUITKA_NO_ASSERT__
940 // TODO: Reactivate once code object creation becomes un-streaming driven
941 // and we can pass the extra args with no worries.
942
943 // Py_hash_t hash = DEEP_HASH(arg_names);
944#endif
945
946 // spell-checker: ignore lnotab
947#if PYTHON_VERSION < 0x300
948 PyObject *code = const_str_empty;
949 PyObject *lnotab = const_str_empty;
950 PyObject *consts = const_tuple_empty;
951 PyObject *names = const_tuple_empty;
952 int stacksize = 0;
953#elif PYTHON_VERSION < 0x3b0
954 PyObject *code = const_bytes_empty;
955 PyObject *lnotab = const_bytes_empty;
956 PyObject *consts = const_tuple_empty;
957 PyObject *names = const_tuple_empty;
958 int stacksize = 0;
959#else
960 // Our code object needs to be recognizable, and Python doesn't store the
961 // length anymore, so we need a non-empty one.
962 static PyObject *empty_code = NULL;
963 static PyObject *lnotab = NULL;
964 static PyObject *consts = NULL;
965 static PyObject *names = NULL;
966 // TODO: Seems removable.
967 static PyObject *exception_table = NULL;
968 static int stacksize = 0;
969
970 if (empty_code == NULL) {
971 // Only needed once here.
972 PyThreadState *tstate = PyThreadState_GET();
973
974 PyObject *empty_code_module_object = Py_CompileString(
975 "def empty(): raise RuntimeError('Compiled function bytecode used')", "<exec>", Py_file_input);
976 NUITKA_MAY_BE_UNUSED PyObject *module =
977 PyImport_ExecCodeModule("nuitka_empty_function", empty_code_module_object);
978 CHECK_OBJECT(module);
979
980 PyObject *empty_function = PyObject_GetAttrString(module, "empty");
981 CHECK_OBJECT(empty_function);
982 PyObject *empty_code_object = PyObject_GetAttrString(empty_function, "__code__");
983 CHECK_OBJECT(empty_code_object);
984
985 NUITKA_MAY_BE_UNUSED bool bool_res = Nuitka_DelModuleString(tstate, "nuitka_empty_function");
986 assert(bool_res != false);
987
988 empty_code = PyObject_GetAttrString(empty_code_object, "co_code");
989 CHECK_OBJECT(empty_code);
990#if PYTHON_VERSION >= 0x3c0
991 lnotab = ((PyCodeObject *)empty_code_object)->co_linetable; // spell-checker: ignore linetable
992#else
993 lnotab = PyObject_GetAttrString(empty_code_object, "co_lnotab");
994 CHECK_OBJECT(lnotab);
995#endif
996 consts = PyObject_GetAttrString(empty_code_object, "co_consts");
997 CHECK_OBJECT(consts);
998 names = PyObject_GetAttrString(empty_code_object, "co_names");
999 CHECK_OBJECT(names);
1000 exception_table = PyObject_GetAttrString(empty_code_object, "co_exceptiontable");
1001 CHECK_OBJECT(exception_table);
1002
1003 stacksize = (int)PyLong_AsLong(PyObject_GetAttrString(empty_code_object, "co_stacksize"));
1004 }
1005
1006 PyObject *code = empty_code;
1007 CHECK_OBJECT(empty_code);
1008 CHECK_OBJECT(lnotab);
1009 CHECK_OBJECT(consts);
1010 CHECK_OBJECT(names);
1011 CHECK_OBJECT(exception_table);
1012#endif
1013
1014 // For Python 3.11 this value is checked, even if not used.
1015#if PYTHON_VERSION >= 0x3b0
1016 int nlocals = (int)PyTuple_GET_SIZE(arg_names);
1017#else
1018 int nlocals = 0;
1019#endif
1020
1021 // Not using PyCode_NewEmpty, it doesn't given us much beyond this
1022 // and is not available for Python2.
1023
1024#if PYTHON_VERSION >= 0x380
1025 PyCodeObject *result = PyCode_NewWithPosOnlyArgs(arg_count, // arg_count
1026#else
1027 PyCodeObject *result = PyCode_New(arg_count, // arg_count
1028#endif
1029
1030#if PYTHON_VERSION >= 0x300
1031#if PYTHON_VERSION >= 0x380
1032 pos_only_count, // pos-only count
1033#endif
1034 kw_only_count, // kw-only count
1035#endif
1036 nlocals, // nlocals
1037 stacksize, // stacksize
1038 flags, // flags
1039 code, // code (bytecode)
1040 consts, // consts (we are not going to be compatible)
1041 names, // names (we are not going to be compatible)
1042 arg_names, // var_names (we are not going to be compatible)
1043 free_vars, // free_vars
1044 const_tuple_empty, // cell_vars (we are not going to be compatible)
1045 filename, // filename
1046 function_name, // name
1047#if PYTHON_VERSION >= 0x3b0
1048 function_qualname, // qualname
1049#endif
1050 line, // first_lineno (offset of the code object)
1051 lnotab // lnotab (table to translate code object)
1052#if PYTHON_VERSION >= 0x3b0
1053 ,
1054 exception_table // exception_table
1055#endif
1056 );
1057
1058 // assert(DEEP_HASH(tstate, arg_names) == hash);
1059
1060#if PYTHON_VERSION < 0x300
1061 Py_DECREF(filename_str);
1062#endif
1063
1064 if (result == NULL) {
1065 PyErr_PrintEx(0);
1066 NUITKA_CANNOT_GET_HERE("Failed to create code object");
1067 }
1068
1069 return result;
1070}
1071
1072PyCodeObject *USE_CODE_OBJECT(PyThreadState *tstate, PyObject *code_object, PyObject *module_filename_obj) {
1073 assert(PyCode_Check(code_object));
1074 CHECK_OBJECT(module_filename_obj);
1075
1076 PyCodeObject *co = (PyCodeObject *)code_object;
1077 PyObject *old = co->co_filename;
1078
1079 if (old == const_str_empty) {
1080 // Set the filename, ignore the loss of a reference to empty string,
1081 // that's our singleton and immortal at least practically.
1082 co->co_filename = Py_NewRef(module_filename_obj);
1083
1084#if PYTHON_VERSION >= 0x3b0
1085 // Also, make sure the qualname is completed from the partial
1086 // name.
1087 if (co->co_qualname != co->co_name) {
1088 PyObject *w = UNICODE_CONCAT(tstate, co->co_qualname, const_str_dot);
1089 co->co_qualname = UNICODE_CONCAT(tstate, w, co->co_name);
1090 Py_DECREF(w);
1091 }
1092#endif
1093 }
1094
1095 return co;
1096}
1097
1098void Nuitka_Frame_AttachLocals(struct Nuitka_FrameObject *frame_object, char const *type_description, ...) {
1099 assert(Nuitka_Frame_CheckExact((PyObject *)frame_object));
1100 CHECK_OBJECT((PyObject *)frame_object);
1101 assert(_PyObject_GC_IS_TRACKED(frame_object));
1102 assertFrameObject(frame_object);
1103
1104#if _DEBUG_FRAME
1105 PRINT_FORMAT("Attaching to frame 0x%lx %s\n", frame_object,
1106 Nuitka_String_AsString(PyObject_Repr((PyObject *)Nuitka_Frame_GetCodeObject(&frame_object->m_frame))));
1107#endif
1108
1109 assert(frame_object->m_type_description == NULL);
1110
1111 // TODO: Do not call this if there is nothing to do. Instead make all the
1112 // places handle NULL pointer and recognize that there is nothing to do.
1113 // assert(type_description != NULL && assert(strlen(type_description)>0));
1114 if (type_description == NULL) {
1115 type_description = "";
1116 }
1117
1118 frame_object->m_type_description = type_description;
1119
1120 char const *w = type_description;
1121 char *t = frame_object->m_locals_storage;
1122
1123 va_list(ap);
1124 va_start(ap, type_description);
1125
1126 while (*w != 0) {
1127 switch (*w) {
1128 case NUITKA_TYPE_DESCRIPTION_OBJECT: {
1129 PyObject *value = va_arg(ap, PyObject *);
1130 memcpy(t, &value, sizeof(PyObject *));
1131 Py_XINCREF(value);
1132 t += sizeof(PyObject *);
1133
1134 break;
1135 }
1136 case NUITKA_TYPE_DESCRIPTION_OBJECT_PTR: {
1137 /* Note: We store the pointed object only, so this is only
1138 a shortcut for the calling side. */
1139 PyObject **value = va_arg(ap, PyObject **);
1140 CHECK_OBJECT_X(*value);
1141
1142 memcpy(t, value, sizeof(PyObject *));
1143
1144 Py_XINCREF(*value);
1145 t += sizeof(PyObject *);
1146
1147 break;
1148 }
1149 case NUITKA_TYPE_DESCRIPTION_CELL: {
1150 struct Nuitka_CellObject *value = va_arg(ap, struct Nuitka_CellObject *);
1151 assert(Nuitka_Cell_Check((PyObject *)value));
1152 CHECK_OBJECT(value);
1153 CHECK_OBJECT_X(value->ob_ref);
1154
1155 memcpy(t, &value, sizeof(struct Nuitka_CellObject *));
1156 // TODO: Reference count must become wrong here, should
1157 // be forced to one probably, or we should simply not
1158 // store cells, but their values. Take a ref off "value"
1159 // is probably not needed.
1160 // Py_SET_REFCNT((struct Nuitka_CellObject *)t, 1);
1161 Py_INCREF(value);
1162
1163 t += sizeof(struct Nuitka_CellObject *);
1164
1165 break;
1166 }
1167 case NUITKA_TYPE_DESCRIPTION_NULL: {
1168 NUITKA_MAY_BE_UNUSED void *value = va_arg(ap, struct Nuitka_CellObject *);
1169
1170 break;
1171 }
1172 case NUITKA_TYPE_DESCRIPTION_BOOL: {
1173 int value = va_arg(ap, int);
1174 memcpy(t, &value, sizeof(int));
1175
1176 t += sizeof(value);
1177
1178 break;
1179 }
1180 case NUITKA_TYPE_DESCRIPTION_NILONG: {
1181 nuitka_ilong value = va_arg(ap, nuitka_ilong);
1182 ENFORCE_NILONG_OBJECT_VALUE(&value);
1183
1184 CHECK_OBJECT(value.python_value);
1185 memcpy(t, &value.python_value, sizeof(PyObject *));
1186 Py_XINCREF(value.python_value);
1187 t += sizeof(PyObject *);
1188
1189 break;
1190 }
1191 default:
1192 NUITKA_CANNOT_GET_HERE("invalid type description");
1193 assert(false);
1194 }
1195
1196 w += 1;
1197 }
1198
1199 va_end(ap);
1200
1201 assert(t - frame_object->m_locals_storage <= Nuitka_Frame_GetSize(frame_object));
1202}
1203
1204// Make a dump of the active frame stack. For debugging purposes only.
1205#if _DEBUG_FRAME
1206void dumpFrameStack(void) {
1207 PyThreadState *tstate = PyThreadState_GET();
1208
1209 struct Nuitka_ExceptionPreservationItem saved_exception_state;
1210 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
1211
1212 int total = 0;
1213
1214#if PYTHON_VERSION < 0x3b0
1215 PyFrameObject *current = PyThreadState_GET()->frame;
1216 while (current != NULL) {
1217 total++;
1218 current = current->f_back;
1219 }
1220
1221 current = tstate->frame;
1222#else
1223 _PyCFrame *current = tstate->cframe;
1224 while (current != NULL) {
1225 total++;
1226 current = current->previous;
1227 }
1228
1229 current = tstate->cframe;
1230#endif
1231
1232 PRINT_STRING(">--------->\n");
1233
1234 while (current) {
1235#if PYTHON_VERSION < 0x3b0
1236 PyObject *current_repr = PyObject_Str((PyObject *)current);
1237 PyObject *code_repr = PyObject_Str((PyObject *)current->f_code);
1238#else
1239 PyObject *current_repr = NULL;
1240 if (current->current_frame->frame_obj != NULL) {
1241 current_repr = PyObject_Str((PyObject *)current->current_frame->frame_obj);
1242 } else {
1243 current_repr = const_str_empty;
1244 Py_INCREF(const_str_empty);
1245 }
1246 PyObject *code_repr = PyObject_Str((PyObject *)Nuitka_InterpreterFrame_GetCodeObject(current->current_frame));
1247#endif
1248
1249 PRINT_FORMAT("Frame stack %d: %s %d %s\n", total--, Nuitka_String_AsString(current_repr), Py_REFCNT(current),
1250 Nuitka_String_AsString(code_repr));
1251
1252 Py_DECREF(current_repr);
1253 Py_DECREF(code_repr);
1254
1255#if PYTHON_VERSION < 0x3b0
1256 current = current->f_back;
1257#else
1258 current = current->previous;
1259#endif
1260 }
1261
1262 PRINT_STRING(">---------<\n");
1263
1264 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state);
1265}
1266
1267static void PRINT_UNCOMPILED_FRAME(char const *prefix, PyFrameObject *frame) {
1268 PRINT_STRING(prefix);
1269 PRINT_STRING(" ");
1270
1271 if (frame) {
1272 PyObject *frame_str = PyObject_Str((PyObject *)frame);
1273 PRINT_ITEM(frame_str);
1274 Py_DECREF(frame_str);
1275
1276 PyObject *code_object_str = PyObject_Repr((PyObject *)Nuitka_Frame_GetCodeObject(frame));
1277 PRINT_ITEM(code_object_str);
1278 Py_DECREF(code_object_str);
1279
1280 PRINT_REFCOUNT((PyObject *)frame);
1281 } else {
1282 PRINT_STRING("<NULL> no frame");
1283 }
1284
1285 PRINT_NEW_LINE();
1286}
1287
1288void PRINT_COMPILED_FRAME(char const *prefix, struct Nuitka_FrameObject *frame) {
1289 return PRINT_UNCOMPILED_FRAME(prefix, &frame->m_frame);
1290}
1291
1292void PRINT_INTERPRETER_FRAME(char const *prefix, Nuitka_ThreadStateFrameType *frame) {
1293#if PYTHON_VERSION < 0x3b0
1294 PRINT_UNCOMPILED_FRAME(prefix, frame);
1295#else
1296 PRINT_STRING(prefix);
1297 PRINT_STRING(" ");
1298
1299 if (frame) {
1300 PRINT_FORMAT("0x%lx ", frame);
1301
1302 PyObject *code_object_str = PyObject_Repr((PyObject *)Nuitka_InterpreterFrame_GetCodeObject(frame));
1303 PRINT_ITEM(code_object_str);
1304 Py_DECREF(code_object_str);
1305 } else {
1306 PRINT_STRING("<NULL> no frame");
1307 }
1308
1309 PRINT_NEW_LINE();
1310#endif
1311}
1312
1313void PRINT_TOP_FRAME(char const *prefix) {
1314 PyThreadState *tstate = PyThreadState_GET();
1315
1316#if PYTHON_VERSION < 0x3b0
1317 PRINT_UNCOMPILED_FRAME(prefix, tstate->frame);
1318#else
1319 PRINT_INTERPRETER_FRAME(prefix, CURRENT_TSTATE_INTERPRETER_FRAME(tstate));
1320#endif
1321}
1322
1323#endif
1324// Part of "Nuitka", an optimizing Python compiler that is compatible and
1325// integrates with CPython, but also works on its own.
1326//
1327// Licensed under the Apache License, Version 2.0 (the "License");
1328// you may not use this file except in compliance with the License.
1329// You may obtain a copy of the License at
1330//
1331// http://www.apache.org/licenses/LICENSE-2.0
1332//
1333// Unless required by applicable law or agreed to in writing, software
1334// distributed under the License is distributed on an "AS IS" BASIS,
1335// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1336// See the License for the specific language governing permissions and
1337// 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