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