Skip to content

Commit 60d2b16

Browse files
committed
Move observability-relevant structure fields to top
Some structures have fields that are used by out-of-process tools, like Austin. Having these fields defined after some more complex structures makes it hard to maintain these tools. With this change, we move the declaration of the most useful fields to the top of the structure definition. This reduces the amount of irrelevant information that the mentioned tools have to replicate to retrieve the actually useful data
1 parent 94a1eea commit 60d2b16

File tree

3 files changed

+43
-31
lines changed

3 files changed

+43
-31
lines changed

Include/internal/pycore_frame.h

+9-5
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,20 @@ enum _frameowner {
4949
typedef struct _PyInterpreterFrame {
5050
PyCodeObject *f_code; /* Strong reference */
5151
struct _PyInterpreterFrame *previous;
52-
PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
53-
PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
54-
PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */
55-
PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
56-
PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
5752
// NOTE: This is not necessarily the last instruction started in the given
5853
// frame. Rather, it is the code unit *prior to* the *next* instruction. For
5954
// example, it may be an inline CACHE entry, an instruction we just jumped
6055
// over, or (in the case of a newly-created frame) a totally invalid value:
6156
_Py_CODEUNIT *prev_instr;
57+
58+
/* The fields above this line are declared as early as possible to
59+
facilitate out-of-process observability tools. */
60+
61+
PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
62+
PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
63+
PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */
64+
PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
65+
PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
6266
int stacktop; /* Offset of TOS from localsplus */
6367
/* The return_offset determines where a `RETURN` should go in the caller,
6468
* relative to `prev_instr`.

Include/internal/pycore_interp.h

+22-18
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ struct _Py_long_state {
4747
The PyInterpreterState typedef is in Include/pytypedefs.h.
4848
*/
4949
struct _is {
50-
51-
struct _ceval_state ceval;
5250
PyInterpreterState *next;
5351

5452
uint64_t monitoring_version;
@@ -72,6 +70,28 @@ struct _is {
7270
Get runtime from tstate: tstate->interp->runtime. */
7371
struct pyruntimestate *runtime;
7472

73+
struct _gc_runtime_state gc;
74+
75+
/* The following fields are here to avoid allocation during init.
76+
The data is exposed through PyInterpreterState pointer fields.
77+
These fields should not be accessed directly outside of init.
78+
79+
All other PyInterpreterState pointer fields are populated when
80+
needed and default to NULL.
81+
82+
For now there are some exceptions to that rule, which require
83+
allocation during init. These will be addressed on a case-by-case
84+
basis. Also see _PyRuntimeState regarding the various mutex fields.
85+
*/
86+
87+
/* The per-interpreter GIL, which might not be used. */
88+
struct _gil_runtime_state _gil;
89+
90+
/* The fields above this line are declared as early as possible to
91+
facilitate out-of-process observability tools. */
92+
93+
struct _ceval_state ceval;
94+
7595
int64_t id;
7696
int64_t id_refcount;
7797
int requires_idref;
@@ -93,7 +113,6 @@ struct _is {
93113

94114
struct _obmalloc_state obmalloc;
95115

96-
struct _gc_runtime_state gc;
97116

98117
struct _import_state imports;
99118

@@ -176,21 +195,6 @@ struct _is {
176195
struct _Py_interp_cached_objects cached_objects;
177196
struct _Py_interp_static_objects static_objects;
178197

179-
/* The following fields are here to avoid allocation during init.
180-
The data is exposed through PyInterpreterState pointer fields.
181-
These fields should not be accessed directly outside of init.
182-
183-
All other PyInterpreterState pointer fields are populated when
184-
needed and default to NULL.
185-
186-
For now there are some exceptions to that rule, which require
187-
allocation during init. These will be addressed on a case-by-case
188-
basis. Also see _PyRuntimeState regarding the various mutex fields.
189-
*/
190-
191-
/* The per-interpreter GIL, which might not be used. */
192-
struct _gil_runtime_state _gil;
193-
194198
/* the initial PyInterpreterState.threads.head */
195199
PyThreadState _initial_thread;
196200
};

Include/internal/pycore_runtime.h

+12-8
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,6 @@ typedef struct pyruntimestate {
8484
to access it, don't access it directly. */
8585
_Py_atomic_address _finalizing;
8686

87-
struct _pymem_allocators allocators;
88-
struct _obmalloc_global_state obmalloc;
89-
struct pyhash_runtime_state pyhash_state;
90-
struct _time_runtime_state time;
91-
struct _pythread_runtime_state threads;
92-
struct _signals_runtime_state signals;
93-
9487
struct pyinterpreters {
9588
PyThread_type_lock mutex;
9689
/* The linked list of interpreters, newest first. */
@@ -109,13 +102,24 @@ typedef struct pyruntimestate {
109102
using a Python int. */
110103
int64_t next_id;
111104
} interpreters;
105+
106+
unsigned long main_thread;
107+
108+
/* The fields above this line are declared as early as possible to
109+
facilitate out-of-process observability tools. */
110+
112111
// XXX Remove this field once we have a tp_* slot.
113112
struct _xidregistry {
114113
PyThread_type_lock mutex;
115114
struct _xidregitem *head;
116115
} xidregistry;
117116

118-
unsigned long main_thread;
117+
struct _pymem_allocators allocators;
118+
struct _obmalloc_global_state obmalloc;
119+
struct pyhash_runtime_state pyhash_state;
120+
struct _time_runtime_state time;
121+
struct _pythread_runtime_state threads;
122+
struct _signals_runtime_state signals;
119123

120124
/* Used for the thread state bound to the current thread. */
121125
Py_tss_t autoTSSkey;

0 commit comments

Comments
 (0)