From b8367e7cf3d740fdc401902b502c0ef2ccc6197c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 19 Mar 2025 15:23:32 +0100 Subject: gh-130931: Add pycore_typedefs.h internal header (#131396) Declare _PyInterpreterFrame and _PyRuntimeState types before declaring their structure members. Break reference cycles between header files. --- Include/internal/pycore_ceval.h | 7 ++++--- Include/internal/pycore_frame.h | 7 ++++--- Include/internal/pycore_gc.h | 5 +++-- Include/internal/pycore_genobject.h | 4 +++- Include/internal/pycore_initconfig.h | 5 ++--- Include/internal/pycore_instruments.h | 15 ++++++++------- Include/internal/pycore_interp_structs.h | 9 +++++---- Include/internal/pycore_optimizer.h | 5 +++-- Include/internal/pycore_pylifecycle.h | 1 - Include/internal/pycore_runtime_structs.h | 4 ++-- Include/internal/pycore_typedefs.h | 18 ++++++++++++++++++ Makefile.pre.in | 1 + PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 +++ 14 files changed, 57 insertions(+), 28 deletions(-) create mode 100644 Include/internal/pycore_typedefs.h diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 5618539..436e5dc 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -12,9 +12,10 @@ extern "C" { #include "pycore_interp.h" // PyInterpreterState.eval_frame #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_typedefs.h" // _PyInterpreterFrame + /* Forward declarations */ -struct pyruntimestate; struct _ceval_runtime_state; // Export for '_lsprof' shared extension @@ -109,7 +110,7 @@ extern _PyPerf_Callbacks _Py_perfmap_jit_callbacks; #endif static inline PyObject* -_PyEval_EvalFrame(PyThreadState *tstate, struct _PyInterpreterFrame *frame, int throwflag) +_PyEval_EvalFrame(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag) { EVAL_CALL_STAT_INC(EVAL_CALL_TOTAL); if (tstate->interp->eval_frame == NULL) { @@ -256,7 +257,7 @@ static inline int _Py_ReachedRecursionLimit(PyThreadState *tstate) { static inline void _Py_LeaveRecursiveCall(void) { } -extern struct _PyInterpreterFrame* _PyEval_GetFrame(void); +extern _PyInterpreterFrame* _PyEval_GetFrame(void); PyAPI_FUNC(PyObject *)_Py_MakeCoro(PyFunctionObject *func); diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index fc395d8..31a9872 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -13,6 +13,7 @@ extern "C" { #include "pycore_code.h" // STATS #include "pycore_stackref.h" // _PyStackRef #include "pycore_stats.h" +#include "pycore_typedefs.h" // _PyInterpreterFrame /* See InternalDocs/frames.md for an explanation of the frame stack * including explanation of the PyFrameObject and _PyInterpreterFrame @@ -22,7 +23,7 @@ extern "C" { struct _frame { PyObject_HEAD PyFrameObject *f_back; /* previous frame, or NULL */ - struct _PyInterpreterFrame *f_frame; /* points to the frame data */ + _PyInterpreterFrame *f_frame; /* points to the frame data */ PyObject *f_trace; /* Trace function */ int f_lineno; /* Current line number. Only valid if non-zero */ char f_trace_lines; /* Emit per-line trace events? */ @@ -61,7 +62,7 @@ enum _frameowner { FRAME_OWNED_BY_CSTACK = 4, }; -typedef struct _PyInterpreterFrame { +struct _PyInterpreterFrame { _PyStackRef f_executable; /* Deferred or strong reference (code object or None) */ struct _PyInterpreterFrame *previous; _PyStackRef f_funcobj; /* Deferred or strong reference. Only valid if not on C stack */ @@ -85,7 +86,7 @@ typedef struct _PyInterpreterFrame { #endif /* Locals and stack */ _PyStackRef localsplus[1]; -} _PyInterpreterFrame; +}; #define _PyInterpreterFrame_LASTI(IF) \ ((int)((IF)->instr_ptr - _PyFrame_GetBytecode((IF)))) diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index 107a861..c33b98c 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -8,8 +8,9 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_runtime_structs.h" #include "pycore_pystate.h" +#include "pycore_runtime_structs.h" +#include "pycore_typedefs.h" // _PyInterpreterFrame /* Get an object's GC head */ @@ -348,7 +349,7 @@ extern void _Py_RunGC(PyThreadState *tstate); union _PyStackRef; // GC visit callback for tracked interpreter frames -extern int _PyGC_VisitFrameStack(struct _PyInterpreterFrame *frame, visitproc visit, void *arg); +extern int _PyGC_VisitFrameStack(_PyInterpreterFrame *frame, visitproc visit, void *arg); extern int _PyGC_VisitStackRef(union _PyStackRef *ref, visitproc visit, void *arg); // Like Py_VISIT but for _PyStackRef fields diff --git a/Include/internal/pycore_genobject.h b/Include/internal/pycore_genobject.h index f6d7e6d..b0472c5 100644 --- a/Include/internal/pycore_genobject.h +++ b/Include/internal/pycore_genobject.h @@ -9,6 +9,8 @@ extern "C" { #endif #include "pycore_frame.h" +#include "pycore_typedefs.h" // _PyInterpreterFrame + /* _PyGenObject_HEAD defines the initial segment of generator and coroutine objects. */ @@ -27,7 +29,7 @@ extern "C" { char prefix##_running_async; \ /* The frame */ \ int8_t prefix##_frame_state; \ - struct _PyInterpreterFrame prefix##_iframe; \ + _PyInterpreterFrame prefix##_iframe; \ struct _PyGenObject { /* The gi_ prefix is intended to remind of generator-iterator. */ diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h index 25ec8ce..368dafb 100644 --- a/Include/internal/pycore_initconfig.h +++ b/Include/internal/pycore_initconfig.h @@ -8,8 +8,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -/* Forward declaration */ -struct pyruntimestate; +#include "pycore_typedefs.h" // _PyRuntimeState /* --- PyStatus ----------------------------------------------- */ @@ -177,7 +176,7 @@ extern PyStatus _PyConfig_InitPathConfig( extern PyStatus _PyConfig_InitImportConfig(PyConfig *config); extern PyStatus _PyConfig_Read(PyConfig *config, int compute_path_config); extern PyStatus _PyConfig_Write(const PyConfig *config, - struct pyruntimestate *runtime); + _PyRuntimeState *runtime); extern PyStatus _PyConfig_SetPyArgv( PyConfig *config, const _PyArgv *args); diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index 0e85f97..7658adc 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -6,6 +6,7 @@ #endif #include "pycore_structs.h" // _Py_CODEUNIT +#include "pycore_typedefs.h" // _PyInterpreterFrame #ifdef __cplusplus extern "C" { @@ -34,32 +35,32 @@ int _PyMonitoring_GetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringE extern int _Py_call_instrumentation(PyThreadState *tstate, int event, - struct _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); + _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); extern int -_Py_call_instrumentation_line(PyThreadState *tstate, struct _PyInterpreterFrame* frame, +_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev); extern int _Py_call_instrumentation_instruction( - PyThreadState *tstate, struct _PyInterpreterFrame* frame, _Py_CODEUNIT *instr); + PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr); _Py_CODEUNIT * _Py_call_instrumentation_jump( _Py_CODEUNIT *instr, PyThreadState *tstate, int event, - struct _PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest); + _PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest); extern int _Py_call_instrumentation_arg(PyThreadState *tstate, int event, - struct _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg); + _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg); extern int _Py_call_instrumentation_2args(PyThreadState *tstate, int event, - struct _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); + _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); extern void _Py_call_instrumentation_exc2(PyThreadState *tstate, int event, - struct _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); + _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1); extern int _Py_Instrumentation_GetLine(PyCodeObject *code, int index); diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index ec788de..bdeb7f0 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -4,10 +4,11 @@ extern "C" { #endif -#include "pycore_structs.h" -#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR -#include "pycore_llist.h" #include "pycore_ast_state.h" // struct ast_state +#include "pycore_llist.h" +#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR +#include "pycore_structs.h" +#include "pycore_typedefs.h" // _PyRuntimeState /* This file contains the struct definitions for interpreter state @@ -802,7 +803,7 @@ struct _is { /* Reference to the _PyRuntime global variable. This field exists to not have to pass runtime in addition to tstate to a function. Get runtime from tstate: tstate->interp->runtime. */ - struct pyruntimestate *runtime; + _PyRuntimeState *runtime; /* Set by Py_EndInterpreter(). diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 7986116..03c2708 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -8,6 +8,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_typedefs.h" // _PyInterpreterFrame #include "pycore_uop_ids.h" #include @@ -117,7 +118,7 @@ PyAPI_FUNC(void) _Py_Executors_InvalidateCold(PyInterpreterState *interp); #define TRACE_STACK_SIZE 5 -int _Py_uop_analyze_and_optimize(struct _PyInterpreterFrame *frame, +int _Py_uop_analyze_and_optimize(_PyInterpreterFrame *frame, _PyUOpInstruction *trace, int trace_len, int curr_stackentries, _PyBloomFilter *dependencies); @@ -291,7 +292,7 @@ extern int _Py_uop_frame_pop(JitOptContext *ctx); PyAPI_FUNC(PyObject *) _Py_uop_symbols_test(PyObject *self, PyObject *ignored); -PyAPI_FUNC(int) _PyOptimizer_Optimize(struct _PyInterpreterFrame *frame, _Py_CODEUNIT *start, _PyExecutorObject **exec_ptr, int chain_depth); +PyAPI_FUNC(int) _PyOptimizer_Optimize(_PyInterpreterFrame *frame, _Py_CODEUNIT *start, _PyExecutorObject **exec_ptr, int chain_depth); static inline int is_terminator(const _PyUOpInstruction *uop) { diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index a5f9418..53ffe7f 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -12,7 +12,6 @@ extern "C" { /* Forward declarations */ struct _PyArgv; -struct pyruntimestate; extern int _Py_SetFileSystemEncoding( const char *encoding, diff --git a/Include/internal/pycore_runtime_structs.h b/Include/internal/pycore_runtime_structs.h index 2ea1d79..81f53af 100644 --- a/Include/internal/pycore_runtime_structs.h +++ b/Include/internal/pycore_runtime_structs.h @@ -143,7 +143,7 @@ struct _Py_static_objects { That data is exported by the internal API as a global variable (_PyRuntime, defined near the top of pylifecycle.c). */ -typedef struct pyruntimestate { +struct pyruntimestate { /* This field must be first to facilitate locating it by out of process * debuggers. Out of process debuggers will use the offsets contained in this * field to be able to locate other fields in several interpreter structures @@ -307,7 +307,7 @@ typedef struct pyruntimestate { PyInterpreterState _main_interpreter; // _main_interpreter should be the last field of _PyRuntimeState. // See https://github.com/python/cpython/issues/127117. -} _PyRuntimeState; +}; diff --git a/Include/internal/pycore_typedefs.h b/Include/internal/pycore_typedefs.h new file mode 100644 index 0000000..d330cc4 --- /dev/null +++ b/Include/internal/pycore_typedefs.h @@ -0,0 +1,18 @@ +#ifndef Py_INTERNAL_TYPEDEFS_H +#define Py_INTERNAL_TYPEDEFS_H + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _PyInterpreterFrame _PyInterpreterFrame; +typedef struct pyruntimestate _PyRuntimeState; + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_TYPEDEFS_H diff --git a/Makefile.pre.in b/Makefile.pre.in index 05ff1b9..0763128 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1316,6 +1316,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_tracemalloc.h \ $(srcdir)/Include/internal/pycore_tstate.h \ $(srcdir)/Include/internal/pycore_tuple.h \ + $(srcdir)/Include/internal/pycore_typedefs.h \ $(srcdir)/Include/internal/pycore_uniqueid.h \ $(srcdir)/Include/internal/pycore_typeobject.h \ $(srcdir)/Include/internal/pycore_typevarobject.h \ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 3a06d71..2a245e9 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -311,6 +311,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 14eebd9..28cd3ec 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -843,6 +843,9 @@ Include\internal + + Include\internal + Include\internal -- cgit v0.12