3#ifndef __NUITKA_COMPILED_FRAME_H__
4#define __NUITKA_COMPILED_FRAME_H__
8#include "nuitka/prelude.h"
14#if PYTHON_VERSION >= 0x3b0
21#if PYTHON_VERSION < 0x3b0
22typedef PyFrameObject Nuitka_ThreadStateFrameType;
24typedef _PyInterpreterFrame Nuitka_ThreadStateFrameType;
29extern void PRINT_TOP_FRAME(
char const *prefix);
30extern void PRINT_PYTHON_FRAME(
char const *prefix, PyFrameObject *frame);
32extern void PRINT_INTERPRETER_FRAME(
char const *prefix, Nuitka_ThreadStateFrameType *frame);
34#define PRINT_TOP_FRAME(prefix)
35#define PRINT_PYTHON_FRAME(prefix, frame)
36#define PRINT_COMPILED_FRAME(prefix, frame)
37#define PRINT_INTERPRETER_FRAME(prefix, frame)
41extern struct Nuitka_FrameObject *MAKE_MODULE_FRAME(PyCodeObject *code, PyObject *module);
42extern struct Nuitka_FrameObject *MAKE_FUNCTION_FRAME(PyThreadState *tstate, PyCodeObject *code, PyObject *module,
43 Py_ssize_t locals_size);
44extern struct Nuitka_FrameObject *MAKE_CLASS_FRAME(PyThreadState *tstate, PyCodeObject *code, PyObject *module,
45 PyObject *f_locals, Py_ssize_t locals_size);
49#if PYTHON_VERSION < 0x300
50#define MAKE_CODE_OBJECT(filename, line, flags, function_name, function_qualname, arg_names, free_vars, arg_count, \
51 kw_only_count, pos_only_count) \
52 makeCodeObject(filename, line, flags, function_name, arg_names, free_vars, arg_count)
53extern PyCodeObject *makeCodeObject(PyObject *filename,
int line,
int flags, PyObject *function_name,
54 PyObject *arg_names, PyObject *free_vars,
int arg_count);
55#elif PYTHON_VERSION < 0x380
56#define MAKE_CODE_OBJECT(filename, line, flags, function_name, function_qualname, arg_names, free_vars, arg_count, \
57 kw_only_count, pos_only_count) \
58 makeCodeObject(filename, line, flags, function_name, arg_names, free_vars, arg_count, kw_only_count)
59extern PyCodeObject *makeCodeObject(PyObject *filename,
int line,
int flags, PyObject *function_name,
60 PyObject *arg_names, PyObject *free_vars,
int arg_count,
int kw_only_count);
61#elif PYTHON_VERSION < 0x3b0
62#define MAKE_CODE_OBJECT(filename, line, flags, function_name, function_qualname, arg_names, free_vars, arg_count, \
63 kw_only_count, pos_only_count) \
64 makeCodeObject(filename, line, flags, function_name, arg_names, free_vars, arg_count, kw_only_count, pos_only_count)
65extern PyCodeObject *makeCodeObject(PyObject *filename,
int line,
int flags, PyObject *function_name,
66 PyObject *arg_names, PyObject *free_vars,
int arg_count,
int kw_only_count,
69#define MAKE_CODE_OBJECT(filename, line, flags, function_name, function_qualname, arg_names, free_vars, arg_count, \
70 kw_only_count, pos_only_count) \
71 makeCodeObject(filename, line, flags, function_name, function_qualname, arg_names, free_vars, arg_count, \
72 kw_only_count, pos_only_count)
73extern PyCodeObject *makeCodeObject(PyObject *filename,
int line,
int flags, PyObject *function_name,
74 PyObject *function_qualname, PyObject *arg_names, PyObject *free_vars,
75 int arg_count,
int kw_only_count,
int pos_only_count);
78NUITKA_MAY_BE_UNUSED
static inline bool isFakeCodeObject(PyCodeObject *code) {
79#if PYTHON_VERSION < 0x300
80 return code->co_code == const_str_empty;
81#elif PYTHON_VERSION < 0x3b0
82 return code->co_code == const_bytes_empty;
92extern PyCodeObject *USE_CODE_OBJECT(PyThreadState *tstate, PyObject *code_object, PyObject *module_filename_obj);
94extern PyTypeObject Nuitka_Frame_Type;
96static inline bool Nuitka_Frame_CheckExact(PyObject *
object) {
98 return Py_TYPE(
object) == &Nuitka_Frame_Type;
101static inline bool Nuitka_Frame_Check(PyObject *
object) {
104 if (!_PyObject_GC_IS_TRACKED(
object)) {
108 CHECK_OBJECT(
object);
110 if (Nuitka_Frame_CheckExact(
object)) {
114 return strcmp(Py_TYPE(
object)->tp_name,
"compiled_frame") == 0;
118 PyFrameObject m_frame;
120#if PYTHON_VERSION >= 0x3b0
121 PyObject *m_generator;
122 PyFrameState m_frame_state;
123 _PyInterpreterFrame m_interpreter_frame;
130 Py_ssize_t m_ob_size;
135 char const *m_type_description;
136 char m_locals_storage[1];
139inline static void CHECK_CODE_OBJECT(PyCodeObject *code_object) { CHECK_OBJECT(code_object); }
141NUITKA_MAY_BE_UNUSED
static inline bool isFrameUnusable(
struct Nuitka_FrameObject *frame_object) {
142 CHECK_OBJECT_X(frame_object);
146 frame_object == NULL ||
148 Py_REFCNT(frame_object) > 1 ||
149#if PYTHON_VERSION < 0x300
151 frame_object->m_frame.f_tstate != PyThreadState_GET() ||
154 frame_object->m_frame.f_back != NULL;
157 if (result && frame_object != NULL) {
158 PRINT_COMPILED_FRAME(
"NOT REUSING FRAME:", frame_object);
166extern int count_active_frame_cache_instances;
167extern int count_allocated_frame_cache_instances;
168extern int count_released_frame_cache_instances;
169extern int count_hit_frame_cache_instances;
173extern void dumpFrameStack(
void);
176#if PYTHON_VERSION >= 0x3b0
177inline static PyCodeObject *Nuitka_InterpreterFrame_GetCodeObject(_PyInterpreterFrame *frame) {
178#if PYTHON_VERSION < 0x3d0
179 return frame->f_code;
181 return (PyCodeObject *)frame->f_executable;
186inline static PyCodeObject *Nuitka_Frame_GetCodeObject(PyFrameObject *frame) {
187#if PYTHON_VERSION >= 0x3b0
188 assert(frame->f_frame);
189 return Nuitka_InterpreterFrame_GetCodeObject(frame->f_frame);
191 return frame->f_code;
195inline static void assertPythonFrameObject(PyFrameObject *frame_object) {
200 CHECK_OBJECT(frame_object);
202 CHECK_CODE_OBJECT(Nuitka_Frame_GetCodeObject(frame_object));
206 CHECK_OBJECT(frame_object);
212 assertPythonFrameObject(&frame_object->m_frame);
215inline static void assertThreadFrameObject(Nuitka_ThreadStateFrameType *frame) {
216#if PYTHON_VERSION < 0x3b0
217 assertPythonFrameObject(frame);
221 if (frame->frame_obj) {
222 assertPythonFrameObject(frame->frame_obj);
231#if PYTHON_VERSION >= 0x300
233#if PYTHON_VERSION < 0x3b0
235static inline void Nuitka_PythonFrame_MarkAsExecuting(PyFrameObject *frame) {
236#if PYTHON_VERSION >= 0x3a0
237 frame->f_state = FRAME_EXECUTING;
239 frame->f_executing = 1;
247#if PYTHON_VERSION >= 0x3b0
248 frame->m_frame_state = FRAME_EXECUTING;
249#elif PYTHON_VERSION >= 0x3a0
250 frame->m_frame.f_state = FRAME_EXECUTING;
252 frame->m_frame.f_executing = 1;
256#define Nuitka_Frame_MarkAsExecuting(frame) ;
259#if PYTHON_VERSION >= 0x300
262#if PYTHON_VERSION >= 0x3b0
263 frame->m_frame_state = FRAME_SUSPENDED;
264#elif PYTHON_VERSION >= 0x3a0
265 frame->m_frame.f_state = FRAME_SUSPENDED;
267 frame->m_frame.f_executing = 0;
271#define Nuitka_Frame_MarkAsNotExecuting(frame) ;
272#define Nuitka_PythonFrame_MarkAsExecuting(frame) ;
275#if PYTHON_VERSION >= 0x300
278#if PYTHON_VERSION >= 0x3b0
279 return frame->m_frame_state == FRAME_EXECUTING;
280#elif PYTHON_VERSION >= 0x3a0
281 return frame->m_frame.f_state == FRAME_EXECUTING;
283 return frame->m_frame.f_executing == 1;
288#if PYTHON_VERSION >= 0x3b0
290#if PYTHON_VERSION < 0x3d0
291#define CURRENT_TSTATE_INTERPRETER_FRAME(tstate) tstate->cframe->current_frame
293#define CURRENT_TSTATE_INTERPRETER_FRAME(tstate) tstate->current_frame
296NUITKA_MAY_BE_UNUSED
inline static void pushFrameStackInterpreterFrame(PyThreadState *tstate,
297 _PyInterpreterFrame *interpreter_frame) {
298 _PyInterpreterFrame *old = CURRENT_TSTATE_INTERPRETER_FRAME(tstate);
299 interpreter_frame->previous = old;
300 CURRENT_TSTATE_INTERPRETER_FRAME(tstate) = interpreter_frame;
302 if (old != NULL && !_PyFrame_IsIncomplete(old) && interpreter_frame->frame_obj) {
303 interpreter_frame->frame_obj->f_back = old->frame_obj;
304 CHECK_OBJECT_X(old->frame_obj);
306 Py_XINCREF(old->frame_obj);
311NUITKA_MAY_BE_UNUSED
inline static void pushFrameStackPythonFrame(PyThreadState *tstate, PyFrameObject *frame_object) {
312 PRINT_TOP_FRAME(
"Normal push entry top frame:");
313 PRINT_COMPILED_FRAME(
"Pushing:", frame_object);
316 assertPythonFrameObject(frame_object);
318 PyFrameObject *old = tstate->frame;
322 assertPythonFrameObject(old);
323 CHECK_CODE_OBJECT(Nuitka_Frame_GetCodeObject(old));
327 assert(old != frame_object);
330 tstate->frame = frame_object;
334 frame_object->f_back = old;
337 Nuitka_PythonFrame_MarkAsExecuting(frame_object);
338 Py_INCREF(frame_object);
340 PRINT_TOP_FRAME(
"Normal push exit top frame:");
344NUITKA_MAY_BE_UNUSED
inline static void pushFrameStackCompiledFrame(PyThreadState *tstate,
346#if PYTHON_VERSION < 0x3b0
347 pushFrameStackPythonFrame(tstate, &frame_object->m_frame);
349 pushFrameStackInterpreterFrame(tstate, &frame_object->m_interpreter_frame);
351 Nuitka_Frame_MarkAsExecuting(frame_object);
352 Py_INCREF(frame_object);
356NUITKA_MAY_BE_UNUSED
inline static void popFrameStack(PyThreadState *tstate) {
358 PRINT_TOP_FRAME(
"Normal pop entry top frame:");
361#if PYTHON_VERSION < 0x3b0
363 CHECK_OBJECT(frame_object);
366 printf(
"Taking off frame %s %s\n", Nuitka_String_AsString(PyObject_Str((PyObject *)frame_object)),
367 Nuitka_String_AsString(PyObject_Repr((PyObject *)Nuitka_Frame_GetCodeObject(&frame_object->m_frame))));
371 tstate->frame = frame_object->m_frame.f_back;
372 frame_object->m_frame.f_back = NULL;
374 Nuitka_Frame_MarkAsNotExecuting(frame_object);
375 Py_DECREF(frame_object);
377 assert(CURRENT_TSTATE_INTERPRETER_FRAME(tstate));
381 CHECK_OBJECT(frame_object);
383 CURRENT_TSTATE_INTERPRETER_FRAME(tstate) = CURRENT_TSTATE_INTERPRETER_FRAME(tstate)->previous;
385 Nuitka_Frame_MarkAsNotExecuting(frame_object);
387 CHECK_OBJECT_X(frame_object->m_frame.f_back);
388 Py_CLEAR(frame_object->m_frame.f_back);
390 Py_DECREF(frame_object);
392 frame_object->m_interpreter_frame.previous = NULL;
396 PRINT_TOP_FRAME(
"Normal pop exit top frame:");
400#if PYTHON_VERSION >= 0x300
401NUITKA_MAY_BE_UNUSED
static void Nuitka_SetFrameGenerator(
struct Nuitka_FrameObject *nuitka_frame,
402 PyObject *generator) {
403#if PYTHON_VERSION < 0x3b0
404 nuitka_frame->m_frame.f_gen = generator;
406 nuitka_frame->m_generator = generator;
411 Nuitka_Frame_MarkAsExecuting(nuitka_frame);
416NUITKA_MAY_BE_UNUSED
static PyCodeObject *Nuitka_GetFrameCodeObject(
struct Nuitka_FrameObject *nuitka_frame) {
417#if PYTHON_VERSION < 0x3b0
418 return nuitka_frame->m_frame.f_code;
420 return Nuitka_InterpreterFrame_GetCodeObject(&nuitka_frame->m_interpreter_frame);
424NUITKA_MAY_BE_UNUSED
static int Nuitka_GetFrameLineNumber(
struct Nuitka_FrameObject *nuitka_frame) {
425 return nuitka_frame->m_frame.f_lineno;
428NUITKA_MAY_BE_UNUSED
static PyObject **Nuitka_GetCodeVarNames(PyCodeObject *code_object) {
429#if PYTHON_VERSION < 0x3b0
430 return &PyTuple_GET_ITEM(code_object->co_varnames, 0);
435 return &PyTuple_GET_ITEM(code_object->co_localsplusnames, 0);
440extern void Nuitka_Frame_AttachLocals(
struct Nuitka_FrameObject *frame,
char const *type_description, ...);
442NUITKA_MAY_BE_UNUSED
static Nuitka_ThreadStateFrameType *_Nuitka_GetThreadStateFrame(PyThreadState *tstate) {
443#if PYTHON_VERSION < 0x3b0
444 return tstate->frame;
446 return CURRENT_TSTATE_INTERPRETER_FRAME(tstate);
450NUITKA_MAY_BE_UNUSED
inline static void pushFrameStackGenerator(PyThreadState *tstate,
451 Nuitka_ThreadStateFrameType *frame_object) {
452#if PYTHON_VERSION < 0x3b0
453 Nuitka_ThreadStateFrameType *return_frame = _Nuitka_GetThreadStateFrame(tstate);
455 Py_XINCREF(return_frame);
457 pushFrameStackPythonFrame(tstate, frame_object);
458 Py_DECREF(frame_object);
460 pushFrameStackInterpreterFrame(tstate, frame_object);
464NUITKA_MAY_BE_UNUSED
inline static void pushFrameStackGeneratorCompiledFrame(PyThreadState *tstate,
466#if PYTHON_VERSION < 0x3b0
467 pushFrameStackGenerator(tstate, &frame_object->m_frame);
469 pushFrameStackGenerator(tstate, &frame_object->m_interpreter_frame);
474#define NUITKA_TYPE_DESCRIPTION_NULL 'N'
475#define NUITKA_TYPE_DESCRIPTION_CELL 'c'
476#define NUITKA_TYPE_DESCRIPTION_OBJECT 'o'
477#define NUITKA_TYPE_DESCRIPTION_OBJECT_PTR 'O'
478#define NUITKA_TYPE_DESCRIPTION_BOOL 'b'
479#define NUITKA_TYPE_DESCRIPTION_NILONG 'L'
482extern int count_active_Nuitka_Frame_Type;
483extern int count_allocated_Nuitka_Frame_Type;
484extern int count_released_Nuitka_Frame_Type;
Definition compiled_frame.h:117