Skip to content

Commit a1aeec6

Browse files
authored
pythonGH-131238: Core header refactor (pythonGH-131250)
* Moves most structs in pycore_ header files into pycore_structs.h and pycore_runtime_structs.h * Removes many cross-header dependencies
1 parent 3ae67ba commit a1aeec6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1481
-1356
lines changed

Include/cpython/code.h

+1-52
Original file line numberDiff line numberDiff line change
@@ -8,70 +8,19 @@
88
extern "C" {
99
#endif
1010

11-
/* Total tool ids available */
12-
#define _PY_MONITORING_TOOL_IDS 8
13-
/* Count of all local monitoring events */
14-
#define _PY_MONITORING_LOCAL_EVENTS 11
15-
/* Count of all "real" monitoring events (not derived from other events) */
16-
#define _PY_MONITORING_UNGROUPED_EVENTS 16
17-
/* Count of all monitoring events */
18-
#define _PY_MONITORING_EVENTS 19
19-
20-
/* Tables of which tools are active for each monitored event. */
21-
typedef struct _Py_LocalMonitors {
22-
uint8_t tools[_PY_MONITORING_LOCAL_EVENTS];
23-
} _Py_LocalMonitors;
24-
25-
typedef struct _Py_GlobalMonitors {
26-
uint8_t tools[_PY_MONITORING_UNGROUPED_EVENTS];
27-
} _Py_GlobalMonitors;
28-
29-
3011
typedef struct {
3112
PyObject *_co_code;
3213
PyObject *_co_varnames;
3314
PyObject *_co_cellvars;
3415
PyObject *_co_freevars;
3516
} _PyCoCached;
3617

37-
/* Ancillary data structure used for instrumentation.
38-
Line instrumentation creates this with sufficient
39-
space for one entry per code unit. The total size
40-
of the data will be `bytes_per_entry * Py_SIZE(code)` */
41-
typedef struct {
42-
uint8_t bytes_per_entry;
43-
uint8_t data[1];
44-
} _PyCoLineInstrumentationData;
45-
46-
4718
typedef struct {
4819
int size;
4920
int capacity;
5021
struct _PyExecutorObject *executors[1];
5122
} _PyExecutorArray;
5223

53-
/* Main data structure used for instrumentation.
54-
* This is allocated when needed for instrumentation
55-
*/
56-
typedef struct {
57-
/* Monitoring specific to this code object */
58-
_Py_LocalMonitors local_monitors;
59-
/* Monitoring that is active on this code object */
60-
_Py_LocalMonitors active_monitors;
61-
/* The tools that are to be notified for events for the matching code unit */
62-
uint8_t *tools;
63-
/* The version of tools when they instrument the code */
64-
uintptr_t tool_versions[_PY_MONITORING_TOOL_IDS];
65-
/* Information to support line events */
66-
_PyCoLineInstrumentationData *lines;
67-
/* The tools that are to be notified for line events for the matching code unit */
68-
uint8_t *line_tools;
69-
/* Information to support instruction events */
70-
/* The underlying instructions, which can themselves be instrumented */
71-
uint8_t *per_instruction_opcodes;
72-
/* The tools that are to be notified for instruction events for the matching code unit */
73-
uint8_t *per_instruction_tools;
74-
} _PyCoMonitoringData;
7524

7625
#ifdef Py_GIL_DISABLED
7726

@@ -151,7 +100,7 @@ typedef struct {
151100
_PyExecutorArray *co_executors; /* executors from optimizer */ \
152101
_PyCoCached *_co_cached; /* cached co_* attributes */ \
153102
uintptr_t _co_instrumentation_version; /* current instrumentation version */ \
154-
_PyCoMonitoringData *_co_monitoring; /* Monitoring data */ \
103+
struct _PyCoMonitoringData *_co_monitoring; /* Monitoring data */ \
155104
Py_ssize_t _co_unique_id; /* ID used for per-thread refcounting */ \
156105
int _co_firsttraceable; /* index of first traceable instruction */ \
157106
/* Scratch space for extra data relating to the code object. \

Include/cpython/object.h

-1
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,6 @@ PyAPI_FUNC(int) PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *
512512
PyAPI_FUNC(int) _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict);
513513
PyAPI_FUNC(void) PyObject_ClearManagedDict(PyObject *obj);
514514

515-
#define TYPE_MAX_WATCHERS 8
516515

517516
typedef int(*PyType_WatchCallback)(PyTypeObject *);
518517
PyAPI_FUNC(int) PyType_AddWatcher(PyType_WatchCallback callback);

Include/internal/pycore_atexit.h

-38
Original file line numberDiff line numberDiff line change
@@ -12,44 +12,6 @@ extern "C" {
1212
#endif
1313

1414

15-
//###############
16-
// runtime atexit
17-
18-
typedef void (*atexit_callbackfunc)(void);
19-
20-
struct _atexit_runtime_state {
21-
PyMutex mutex;
22-
#define NEXITFUNCS 32
23-
atexit_callbackfunc callbacks[NEXITFUNCS];
24-
int ncallbacks;
25-
};
26-
27-
28-
//###################
29-
// interpreter atexit
30-
31-
typedef void (*atexit_datacallbackfunc)(void *);
32-
33-
typedef struct atexit_callback {
34-
atexit_datacallbackfunc func;
35-
void *data;
36-
struct atexit_callback *next;
37-
} atexit_callback;
38-
39-
struct atexit_state {
40-
#ifdef Py_GIL_DISABLED
41-
PyMutex ll_callbacks_lock;
42-
#endif
43-
atexit_callback *ll_callbacks;
44-
45-
// XXX The rest of the state could be moved to the atexit module state
46-
// and a low-level callback added for it during module exec.
47-
// For the moment we leave it here.
48-
49-
// List containing tuples with callback information.
50-
// e.g. [(func, args, kwargs), ...]
51-
PyObject *callbacks;
52-
};
5315

5416
#ifdef Py_GIL_DISABLED
5517
# define _PyAtExit_LockCallbacks(state) PyMutex_Lock(&state->ll_callbacks_lock);

Include/internal/pycore_backoff.h

+1-8
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,7 @@ extern "C" {
1010
#endif
1111

1212
#include <assert.h>
13-
#include <stdbool.h>
14-
#include <stdint.h>
15-
16-
17-
typedef struct {
18-
uint16_t value_and_backoff;
19-
} _Py_BackoffCounter;
20-
13+
#include "pycore_structs.h" // _Py_BackoffCounter
2114

2215
/* 16-bit countdown counters using exponential backoff.
2316

Include/internal/pycore_ceval_state.h

-85
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,6 @@ extern "C" {
1212
#include "pycore_gil.h" // struct _gil_runtime_state
1313

1414

15-
typedef int (*_Py_pending_call_func)(void *);
16-
17-
struct _pending_call {
18-
_Py_pending_call_func func;
19-
void *arg;
20-
int flags;
21-
};
22-
23-
#define PENDINGCALLSARRAYSIZE 300
24-
2515
#define MAXPENDINGCALLS PENDINGCALLSARRAYSIZE
2616
/* For interpreter-level pending calls, we want to avoid spending too
2717
much time on pending calls in any one thread, so we apply a limit. */
@@ -40,69 +30,6 @@ struct _pending_call {
4030
pending calls for the main thread. */
4131
#define MAXPENDINGCALLSLOOP_MAIN 0
4232

43-
struct _pending_calls {
44-
PyThreadState *handling_thread;
45-
PyMutex mutex;
46-
/* Request for running pending calls. */
47-
int32_t npending;
48-
/* The maximum allowed number of pending calls.
49-
If the queue fills up to this point then _PyEval_AddPendingCall()
50-
will return _Py_ADD_PENDING_FULL. */
51-
int32_t max;
52-
/* We don't want a flood of pending calls to interrupt any one thread
53-
for too long, so we keep a limit on the number handled per pass.
54-
A value of 0 means there is no limit (other than the maximum
55-
size of the list of pending calls). */
56-
int32_t maxloop;
57-
struct _pending_call calls[PENDINGCALLSARRAYSIZE];
58-
int first;
59-
int next;
60-
};
61-
62-
63-
typedef enum {
64-
PERF_STATUS_FAILED = -1, // Perf trampoline is in an invalid state
65-
PERF_STATUS_NO_INIT = 0, // Perf trampoline is not initialized
66-
PERF_STATUS_OK = 1, // Perf trampoline is ready to be executed
67-
} perf_status_t;
68-
69-
#ifdef PY_HAVE_PERF_TRAMPOLINE
70-
struct code_arena_st;
71-
72-
struct trampoline_api_st {
73-
void* (*init_state)(void);
74-
void (*write_state)(void* state, const void *code_addr,
75-
unsigned int code_size, PyCodeObject* code);
76-
int (*free_state)(void* state);
77-
void *state;
78-
Py_ssize_t code_padding;
79-
};
80-
#endif
81-
82-
83-
struct _ceval_runtime_state {
84-
struct {
85-
#ifdef PY_HAVE_PERF_TRAMPOLINE
86-
perf_status_t status;
87-
int perf_trampoline_type;
88-
Py_ssize_t extra_code_index;
89-
struct code_arena_st *code_arena;
90-
struct trampoline_api_st trampoline_api;
91-
FILE *map_file;
92-
Py_ssize_t persist_after_fork;
93-
#else
94-
int _not_used;
95-
#endif
96-
} perf;
97-
/* Pending calls to be made only on the main thread. */
98-
// The signal machinery falls back on this
99-
// so it must be especially stable and efficient.
100-
// For example, we use a preallocated array
101-
// for the list of pending calls.
102-
struct _pending_calls pending_mainthread;
103-
PyMutex sys_trace_profile_mutex;
104-
};
105-
10633

10734
#ifdef PY_HAVE_PERF_TRAMPOLINE
10835
# define _PyEval_RUNTIME_PERF_INIT \
@@ -116,18 +43,6 @@ struct _ceval_runtime_state {
11643
#endif
11744

11845

119-
struct _ceval_state {
120-
/* This variable holds the global instrumentation version. When a thread is
121-
running, this value is overlaid onto PyThreadState.eval_breaker so that
122-
changes in the instrumentation version will trigger the eval breaker. */
123-
uintptr_t instrumentation_version;
124-
int recursion_limit;
125-
struct _gil_runtime_state *gil;
126-
int own_gil;
127-
struct _pending_calls pending;
128-
};
129-
130-
13146
#ifdef __cplusplus
13247
}
13348
#endif

Include/internal/pycore_code.h

+1-32
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,13 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE define"
99
#endif
1010

11+
#include "pycore_structs.h" // _Py_CODEUNIT
1112
#include "pycore_stackref.h" // _PyStackRef
1213
#include "pycore_lock.h" // PyMutex
1314
#include "pycore_backoff.h" // _Py_BackoffCounter
1415
#include "pycore_tstate.h" // _PyThreadStateImpl
1516

1617

17-
/* Each instruction in a code object is a fixed-width value,
18-
* currently 2 bytes: 1-byte opcode + 1-byte oparg. The EXTENDED_ARG
19-
* opcode allows for larger values but the current limit is 3 uses
20-
* of EXTENDED_ARG (see Python/compile.c), for a maximum
21-
* 32-bit value. This aligns with the note in Python/compile.c
22-
* (compiler_addop_i_line) indicating that the max oparg value is
23-
* 2**32 - 1, rather than INT_MAX.
24-
*/
25-
26-
typedef union {
27-
uint16_t cache;
28-
struct {
29-
uint8_t code;
30-
uint8_t arg;
31-
} op;
32-
_Py_BackoffCounter counter; // First cache entry of specializable op
33-
} _Py_CODEUNIT;
34-
3518
#define _PyCode_CODE(CO) _Py_RVALUE((_Py_CODEUNIT *)(CO)->co_code_adaptive)
3619
#define _PyCode_NBYTES(CO) (Py_SIZE(CO) * (Py_ssize_t)sizeof(_Py_CODEUNIT))
3720

@@ -67,16 +50,10 @@ _py_set_opcode(_Py_CODEUNIT *word, uint8_t opcode)
6750
#define _PyCode_HAS_INSTRUMENTATION(CODE) \
6851
(CODE->_co_instrumentation_version > 0)
6952

70-
struct _py_code_state {
71-
PyMutex mutex;
72-
// Interned constants from code objects. Used by the free-threaded build.
73-
struct _Py_hashtable_t *constants;
74-
};
7553

7654
extern PyStatus _PyCode_Init(PyInterpreterState *interp);
7755
extern void _PyCode_Fini(PyInterpreterState *interp);
7856

79-
#define CODE_MAX_WATCHERS 8
8057

8158
/* PEP 659
8259
* Specialization and quickening structs and helper functions
@@ -185,14 +162,6 @@ typedef struct {
185162

186163
#define INLINE_CACHE_ENTRIES_CONTAINS_OP CACHE_ENTRIES(_PyContainsOpCache)
187164

188-
// Borrowed references to common callables:
189-
struct callable_cache {
190-
PyObject *isinstance;
191-
PyObject *len;
192-
PyObject *list_append;
193-
PyObject *object__getattribute__;
194-
};
195-
196165
/* "Locals plus" for a code object is the set of locals + cell vars +
197166
* free vars. This relates to variable names as well as offsets into
198167
* the "fast locals" storage array of execution frames. The compiler

Include/internal/pycore_codecs.h

+1-21
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ extern "C" {
99
#endif
1010

1111
#include "pycore_lock.h" // PyMutex
12+
#include "pycore_runtime_structs.h" // struct codecs_state
1213

1314
/* Initialize codecs-related state for the given interpreter, including
1415
registering the first codec search function. Must be called before any other
@@ -70,27 +71,6 @@ extern PyObject* _PyCodecInfo_GetIncrementalEncoder(
7071
PyObject *codec_info,
7172
const char *errors);
7273

73-
// Per-interpreter state used by codecs.c.
74-
struct codecs_state {
75-
// A list of callable objects used to search for codecs.
76-
PyObject *search_path;
77-
78-
// A dict mapping codec names to codecs returned from a callable in
79-
// search_path.
80-
PyObject *search_cache;
81-
82-
// A dict mapping error handling strategies to functions to implement them.
83-
PyObject *error_registry;
84-
85-
#ifdef Py_GIL_DISABLED
86-
// Used to safely delete a specific item from search_path.
87-
PyMutex search_path_mutex;
88-
#endif
89-
90-
// Whether or not the rest of the state is initialized.
91-
int initialized;
92-
};
93-
9474
#ifdef __cplusplus
9575
}
9676
#endif

Include/internal/pycore_context.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
# error "this header requires Py_BUILD_CORE define"
66
#endif
77

8-
#include "pycore_hamt.h" // PyHamtObject
9-
10-
#define CONTEXT_MAX_WATCHERS 8
8+
#include "pycore_structs.h"
119

1210
extern PyTypeObject _PyContextTokenMissing_Type;
1311

0 commit comments

Comments
 (0)