]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Move observability-relevant structure fields to the top (#105271)
authorGabriele N. Tornetta <P403n1x87@users.noreply.github.com>
Thu, 8 Jun 2023 10:41:24 +0000 (11:41 +0100)
committerGitHub <noreply@github.com>
Thu, 8 Jun 2023 10:41:24 +0000 (11:41 +0100)
Include/internal/pycore_frame.h
Include/internal/pycore_interp.h
Include/internal/pycore_runtime.h

index a72e03f1438fc888e646bf9a449376ade8c647ee..0c72de60753187f43cbbeb11409b668499f69cc8 100644 (file)
@@ -49,16 +49,20 @@ enum _frameowner {
 typedef struct _PyInterpreterFrame {
     PyCodeObject *f_code; /* Strong reference */
     struct _PyInterpreterFrame *previous;
-    PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
-    PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
-    PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */
-    PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
-    PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
     // NOTE: This is not necessarily the last instruction started in the given
     // frame. Rather, it is the code unit *prior to* the *next* instruction. For
     // example, it may be an inline CACHE entry, an instruction we just jumped
     // over, or (in the case of a newly-created frame) a totally invalid value:
     _Py_CODEUNIT *prev_instr;
+
+    /* The fields above this line are declared as early as possible to
+       facilitate out-of-process observability tools. */
+
+    PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
+    PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
+    PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */
+    PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
+    PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
     int stacktop;  /* Offset of TOS from localsplus  */
     /* The return_offset determines where a `RETURN` should go in the caller,
      * relative to `prev_instr`.
index a6f4677920ab7e626bbb5dcce6fa75e8503667cd..90580b70ede1e078e69e7e56dffd26781fd51dad 100644 (file)
@@ -47,13 +47,35 @@ struct _Py_long_state {
    The PyInterpreterState typedef is in Include/pytypedefs.h.
    */
 struct _is {
-
-    struct _ceval_state ceval;
     PyInterpreterState *next;
 
+    int64_t id;
+    int64_t id_refcount;
+    int requires_idref;
+    PyThread_type_lock id_mutex;
+
+    /* Has been initialized to a safe state.
+
+       In order to be effective, this must be set to 0 during or right
+       after allocation. */
+    int _initialized;
+    int finalizing;
+
     uint64_t monitoring_version;
     uint64_t last_restart_version;
 
+    /* The fields above this line are declared as early as possible to
+       facilitate out-of-process observability tools. */
+
+    /* Set by Py_EndInterpreter().
+
+       Use _PyInterpreterState_GetFinalizing()
+       and _PyInterpreterState_SetFinalizing()
+       to access it, don't access it directly. */
+    _Py_atomic_address _finalizing;
+
+    PyCodeObject *interpreter_trampoline;
+
     struct pythreads {
         uint64_t next_unique_id;
         /* The linked list of threads, newest first. */
@@ -72,30 +94,22 @@ struct _is {
        Get runtime from tstate: tstate->interp->runtime. */
     struct pyruntimestate *runtime;
 
-    int64_t id;
-    int64_t id_refcount;
-    int requires_idref;
-    PyThread_type_lock id_mutex;
-
-    /* Has been initialized to a safe state.
-
-       In order to be effective, this must be set to 0 during or right
-       after allocation. */
-    int _initialized;
-    int finalizing;
-
-    /* Set by Py_EndInterpreter().
+    struct _gc_runtime_state gc;
 
-       Use _PyInterpreterState_GetFinalizing()
-       and _PyInterpreterState_SetFinalizing()
-       to access it, don't access it directly. */
-    _Py_atomic_address _finalizing;
+    /* The following fields are here to avoid allocation during init.
+       The data is exposed through PyInterpreterState pointer fields.
+       These fields should not be accessed directly outside of init.
 
-    struct _obmalloc_state obmalloc;
+       All other PyInterpreterState pointer fields are populated when
+       needed and default to NULL.
 
-    struct _gc_runtime_state gc;
+       For now there are some exceptions to that rule, which require
+       allocation during init.  These will be addressed on a case-by-case
+       basis.  Also see _PyRuntimeState regarding the various mutex fields.
+       */
 
-    struct _import_state imports;
+    /* The per-interpreter GIL, which might not be used. */
+    struct _gil_runtime_state _gil;
 
     // Dictionary of the sys module
     PyObject *sysdict;
@@ -133,6 +147,12 @@ struct _is {
     struct _warnings_runtime_state warnings;
     struct atexit_state atexit;
 
+    struct _ceval_state ceval;
+
+    struct _obmalloc_state obmalloc;
+
+    struct _import_state imports;
+
     PyObject *audit_hooks;
     PyType_WatchCallback type_watchers[TYPE_MAX_WATCHERS];
     PyCode_WatchCallback code_watchers[CODE_MAX_WATCHERS];
@@ -159,7 +179,6 @@ struct _is {
     struct ast_state ast;
     struct types_state types;
     struct callable_cache callable_cache;
-    PyCodeObject *interpreter_trampoline;
     _PyOptimizerObject *optimizer;
     uint16_t optimizer_resume_threshold;
     uint16_t optimizer_backedge_threshold;
@@ -176,21 +195,6 @@ struct _is {
     struct _Py_interp_cached_objects cached_objects;
     struct _Py_interp_static_objects static_objects;
 
-    /* The following fields are here to avoid allocation during init.
-       The data is exposed through PyInterpreterState pointer fields.
-       These fields should not be accessed directly outside of init.
-
-       All other PyInterpreterState pointer fields are populated when
-       needed and default to NULL.
-
-       For now there are some exceptions to that rule, which require
-       allocation during init.  These will be addressed on a case-by-case
-       basis.  Also see _PyRuntimeState regarding the various mutex fields.
-       */
-
-    /* The per-interpreter GIL, which might not be used. */
-    struct _gil_runtime_state _gil;
-
     /* the initial PyInterpreterState.threads.head */
     PyThreadState _initial_thread;
 };
index 6e06e874711bc2b3ccfacc879c7994c5b04480f0..6e8f16a611d75e396b50725e5df5ffac727f831f 100644 (file)
@@ -84,13 +84,6 @@ typedef struct pyruntimestate {
        to access it, don't access it directly. */
     _Py_atomic_address _finalizing;
 
-    struct _pymem_allocators allocators;
-    struct _obmalloc_global_state obmalloc;
-    struct pyhash_runtime_state pyhash_state;
-    struct _time_runtime_state time;
-    struct _pythread_runtime_state threads;
-    struct _signals_runtime_state signals;
-
     struct pyinterpreters {
         PyThread_type_lock mutex;
         /* The linked list of interpreters, newest first. */
@@ -109,13 +102,24 @@ typedef struct pyruntimestate {
            using a Python int. */
         int64_t next_id;
     } interpreters;
+
+    unsigned long main_thread;
+
+    /* The fields above this line are declared as early as possible to
+       facilitate out-of-process observability tools. */
+
     // XXX Remove this field once we have a tp_* slot.
     struct _xidregistry {
         PyThread_type_lock mutex;
         struct _xidregitem *head;
     } xidregistry;
 
-    unsigned long main_thread;
+    struct _pymem_allocators allocators;
+    struct _obmalloc_global_state obmalloc;
+    struct pyhash_runtime_state pyhash_state;
+    struct _time_runtime_state time;
+    struct _pythread_runtime_state threads;
+    struct _signals_runtime_state signals;
 
     /* Used for the thread state bound to the current thread. */
     Py_tss_t autoTSSkey;