]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-81057: Move Ceval Trampoline Globals to _PyRuntimeState (gh-100083)
authorEric Snow <ericsnowcurrently@gmail.com>
Fri, 9 Dec 2022 00:17:20 +0000 (17:17 -0700)
committerGitHub <noreply@github.com>
Fri, 9 Dec 2022 00:17:20 +0000 (17:17 -0700)
https://github.com/python/cpython/issues/81057

Include/internal/pycore_ceval_state.h [new file with mode: 0644]
Include/internal/pycore_interp.h
Include/internal/pycore_runtime.h
Include/internal/pycore_runtime_init.h
Makefile.pre.in
PCbuild/pythoncore.vcxproj
PCbuild/pythoncore.vcxproj.filters
Python/perf_trampoline.c
Tools/c-analyzer/cpython/globals-to-fix.tsv

diff --git a/Include/internal/pycore_ceval_state.h b/Include/internal/pycore_ceval_state.h
new file mode 100644 (file)
index 0000000..9ba42eb
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef Py_INTERNAL_CEVAL_STATE_H
+#define Py_INTERNAL_CEVAL_STATE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+
+#include "pycore_atomic.h"          /* _Py_atomic_address */
+#include "pycore_gil.h"             // struct _gil_runtime_state
+
+
+typedef enum {
+    PERF_STATUS_FAILED = -1,  // Perf trampoline is in an invalid state
+    PERF_STATUS_NO_INIT = 0,  // Perf trampoline is not initialized
+    PERF_STATUS_OK = 1,       // Perf trampoline is ready to be executed
+} perf_status_t;
+
+
+#ifdef PY_HAVE_PERF_TRAMPOLINE
+struct code_arena_st;
+
+struct trampoline_api_st {
+    void* (*init_state)(void);
+    void (*write_state)(void* state, const void *code_addr,
+                        unsigned int code_size, PyCodeObject* code);
+    int (*free_state)(void* state);
+    void *state;
+};
+#endif
+
+struct _ceval_runtime_state {
+    struct {
+#ifdef PY_HAVE_PERF_TRAMPOLINE
+        perf_status_t status;
+        Py_ssize_t extra_code_index;
+        struct code_arena_st *code_arena;
+        struct trampoline_api_st trampoline_api;
+        FILE *map_file;
+#else
+        int _not_used;
+#endif
+    } perf;
+    /* Request for checking signals. It is shared by all interpreters (see
+       bpo-40513). Any thread of any interpreter can receive a signal, but only
+       the main thread of the main interpreter can handle signals: see
+       _Py_ThreadCanHandleSignals(). */
+    _Py_atomic_int signals_pending;
+    struct _gil_runtime_state gil;
+};
+
+#ifdef PY_HAVE_PERF_TRAMPOLINE
+# define _PyEval_RUNTIME_PERF_INIT \
+    { \
+        .status = PERF_STATUS_NO_INIT, \
+        .extra_code_index = -1, \
+    }
+#else
+# define _PyEval_RUNTIME_PERF_INIT {0}
+#endif
+
+
+struct _pending_calls {
+    int busy;
+    PyThread_type_lock lock;
+    /* Request for running pending calls. */
+    _Py_atomic_int calls_to_do;
+    /* Request for looking at the `async_exc` field of the current
+       thread state.
+       Guarded by the GIL. */
+    int async_exc;
+#define NPENDINGCALLS 32
+    struct {
+        int (*func)(void *);
+        void *arg;
+    } calls[NPENDINGCALLS];
+    int first;
+    int last;
+};
+
+struct _ceval_state {
+    int recursion_limit;
+    /* This single variable consolidates all requests to break out of
+       the fast path in the eval loop. */
+    _Py_atomic_int eval_breaker;
+    /* Request for dropping the GIL */
+    _Py_atomic_int gil_drop_request;
+    /* The GC is ready to be executed */
+    _Py_atomic_int gc_scheduled;
+    struct _pending_calls pending;
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_CEVAL_STATE_H */
index b5c46773c90fd3d708d4f2b1b74e7eecba8f7f44..ffda1351952d2aba7d9b0a3299ac08b1ee85f42f 100644 (file)
@@ -12,6 +12,7 @@ extern "C" {
 
 #include "pycore_atomic.h"        // _Py_atomic_address
 #include "pycore_ast_state.h"     // struct ast_state
+#include "pycore_ceval_state.h"   // struct _ceval_state
 #include "pycore_code.h"          // struct callable_cache
 #include "pycore_context.h"       // struct _Py_context_state
 #include "pycore_dict_state.h"    // struct _Py_dict_state
@@ -28,37 +29,6 @@ extern "C" {
 #include "pycore_warnings.h"      // struct _warnings_runtime_state
 
 
-struct _pending_calls {
-    int busy;
-    PyThread_type_lock lock;
-    /* Request for running pending calls. */
-    _Py_atomic_int calls_to_do;
-    /* Request for looking at the `async_exc` field of the current
-       thread state.
-       Guarded by the GIL. */
-    int async_exc;
-#define NPENDINGCALLS 32
-    struct {
-        int (*func)(void *);
-        void *arg;
-    } calls[NPENDINGCALLS];
-    int first;
-    int last;
-};
-
-struct _ceval_state {
-    int recursion_limit;
-    /* This single variable consolidates all requests to break out of
-       the fast path in the eval loop. */
-    _Py_atomic_int eval_breaker;
-    /* Request for dropping the GIL */
-    _Py_atomic_int gil_drop_request;
-    /* The GC is ready to be executed */
-    _Py_atomic_int gc_scheduled;
-    struct _pending_calls pending;
-};
-
-
 // atexit state
 typedef struct {
     PyObject *func;
index 458493eac70fe20920647a39c0db45ee5b0b6395..ac89c7d378e26f4b3b3badcd8211ce02f50ea27a 100644 (file)
@@ -9,11 +9,11 @@ extern "C" {
 #endif
 
 #include "pycore_atomic.h"          /* _Py_atomic_address */
+#include "pycore_ceval_state.h"     // struct _ceval_runtime_state
 #include "pycore_dict_state.h"      // struct _Py_dict_runtime_state
 #include "pycore_dtoa.h"            // struct _dtoa_runtime_state
 #include "pycore_floatobject.h"     // struct _Py_float_runtime_state
 #include "pycore_function.h"        // struct _func_runtime_state
-#include "pycore_gil.h"             // struct _gil_runtime_state
 #include "pycore_global_objects.h"  // struct _Py_global_objects
 #include "pycore_import.h"          // struct _import_runtime_state
 #include "pycore_interp.h"          // PyInterpreterState
@@ -31,15 +31,6 @@ struct _getargs_runtime_state {
 
 /* ceval state */
 
-struct _ceval_runtime_state {
-    /* Request for checking signals. It is shared by all interpreters (see
-       bpo-40513). Any thread of any interpreter can receive a signal, but only
-       the main thread of the main interpreter can handle signals: see
-       _Py_ThreadCanHandleSignals(). */
-    _Py_atomic_int signals_pending;
-    struct _gil_runtime_state gil;
-};
-
 /* GIL state */
 
 struct _gilstate_runtime_state {
index ab53876e355fd8d2c606875f67b7921ef48ca92f..b569e5833f1da67a92732a45e96b5c938064456f 100644 (file)
@@ -41,6 +41,9 @@ extern "C" {
                 .header = 1, \
             }, \
         }, \
+        .ceval = { \
+            .perf = _PyEval_RUNTIME_PERF_INIT, \
+        }, \
         .gilstate = { \
             .check_enabled = 1, \
             /* A TSS key must be initialized with Py_tss_NEEDS_INIT \
index c21826fbb94f2da112a0072417774baa93286807..312031999df00290546dc5b1af28c0abde499366 100644 (file)
@@ -1623,6 +1623,7 @@ PYTHON_HEADERS= \
                $(srcdir)/Include/internal/pycore_bytesobject.h \
                $(srcdir)/Include/internal/pycore_call.h \
                $(srcdir)/Include/internal/pycore_ceval.h \
+               $(srcdir)/Include/internal/pycore_ceval_state.h \
                $(srcdir)/Include/internal/pycore_code.h \
                $(srcdir)/Include/internal/pycore_compile.h \
                $(srcdir)/Include/internal/pycore_condvar.h \
index f9f0c191b5eb6dd79b749f6973070358b91316da..58ea6ae7b4aa17e75f3ff69419b22c133007b9cc 100644 (file)
     <ClInclude Include="..\Include\internal\pycore_bytesobject.h" />
     <ClInclude Include="..\Include\internal\pycore_call.h" />
     <ClInclude Include="..\Include\internal\pycore_ceval.h" />
+    <ClInclude Include="..\Include\internal\pycore_ceval_state.h" />
     <ClInclude Include="..\Include\internal\pycore_code.h" />
     <ClInclude Include="..\Include\internal\pycore_compile.h" />
     <ClInclude Include="..\Include\internal\pycore_condvar.h" />
index e683650ad7da0e2e5dd4e6fbf610b7c679084572..96c3bd6c30e973e553140b603075090574039fc2 100644 (file)
     <ClInclude Include="..\Include\internal\pycore_ceval.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
+    <ClInclude Include="..\Include\internal\pycore_ceval_state.h">
+      <Filter>Include\internal</Filter>
+    </ClInclude>
     <ClInclude Include="..\Include\internal\pycore_code.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
index 161e0ef74cf1dad438572cbcf9a920d8bb3ec549..1957ab82c3395127ec312d2f166cdc10176eb424 100644 (file)
@@ -134,11 +134,6 @@ any DWARF information available for them).
 #include "pycore_frame.h"
 #include "pycore_interp.h"
 
-typedef enum {
-    PERF_STATUS_FAILED = -1,  // Perf trampoline is in an invalid state
-    PERF_STATUS_NO_INIT = 0,  // Perf trampoline is not initialized
-    PERF_STATUS_OK = 1,       // Perf trampoline is ready to be executed
-} perf_status_t;
 
 #ifdef PY_HAVE_PERF_TRAMPOLINE
 
@@ -190,24 +185,13 @@ struct code_arena_st {
 };
 
 typedef struct code_arena_st code_arena_t;
-
-struct trampoline_api_st {
-    void* (*init_state)(void);
-    void (*write_state)(void* state, const void *code_addr,
-                        unsigned int code_size, PyCodeObject* code);
-    int (*free_state)(void* state);
-    void *state;
-};
-
 typedef struct trampoline_api_st trampoline_api_t;
 
-
-static perf_status_t perf_status = PERF_STATUS_NO_INIT;
-static Py_ssize_t extra_code_index = -1;
-static code_arena_t *code_arena;
-static trampoline_api_t trampoline_api;
-
-static FILE *perf_map_file;
+#define perf_status _PyRuntime.ceval.perf.status
+#define extra_code_index _PyRuntime.ceval.perf.extra_code_index
+#define perf_code_arena _PyRuntime.ceval.perf.code_arena
+#define trampoline_api _PyRuntime.ceval.perf.trampoline_api
+#define perf_map_file _PyRuntime.ceval.perf.map_file
 
 static void *
 perf_map_get_file(void)
@@ -344,17 +328,17 @@ new_code_arena(void)
     new_arena->size = mem_size;
     new_arena->size_left = mem_size;
     new_arena->code_size = code_size;
-    new_arena->prev = code_arena;
-    code_arena = new_arena;
+    new_arena->prev = perf_code_arena;
+    perf_code_arena = new_arena;
     return 0;
 }
 
 static void
 free_code_arenas(void)
 {
-    code_arena_t *cur = code_arena;
+    code_arena_t *cur = perf_code_arena;
     code_arena_t *prev;
-    code_arena = NULL;  // invalid static pointer
+    perf_code_arena = NULL;  // invalid static pointer
     while (cur) {
         munmap(cur->start_addr, cur->size);
         prev = cur->prev;
@@ -375,14 +359,14 @@ code_arena_new_code(code_arena_t *code_arena)
 static inline py_trampoline
 compile_trampoline(void)
 {
-    if ((code_arena == NULL) ||
-        (code_arena->size_left <= code_arena->code_size)) {
+    if ((perf_code_arena == NULL) ||
+        (perf_code_arena->size_left <= perf_code_arena->code_size)) {
         if (new_code_arena() < 0) {
             return NULL;
         }
     }
-    assert(code_arena->size_left <= code_arena->size);
-    return code_arena_new_code(code_arena);
+    assert(perf_code_arena->size_left <= perf_code_arena->size);
+    return code_arena_new_code(perf_code_arena);
 }
 
 static PyObject *
@@ -405,7 +389,7 @@ py_trampoline_evaluator(PyThreadState *ts, _PyInterpreterFrame *frame,
             goto default_eval;
         }
         trampoline_api.write_state(trampoline_api.state, new_trampoline,
-                                   code_arena->code_size, co);
+                                   perf_code_arena->code_size, co);
         _PyCode_SetExtra((PyObject *)co, extra_code_index,
                          (void *)new_trampoline);
         f = new_trampoline;
index 3f6e1c7405354c981541ec06cd8595218a2e7bc7..f774cdeab3863728edf57aad43a7283781903569 100644 (file)
@@ -302,21 +302,10 @@ Objects/sliceobject.c     -       _Py_EllipsisObject      -
 ##################################
 ## global non-objects to fix in core code
 
-##-----------------------
-## effectively-const but initialized lazily
-
-## others
-Python/perf_trampoline.c       -       perf_map_file   -
-
 ##-----------------------
 ## state
 
-## other
 Objects/object.c       -       _Py_RefTotal    -
-Python/perf_trampoline.c       -       perf_status     -
-Python/perf_trampoline.c       -       extra_code_index        -
-Python/perf_trampoline.c       -       code_arena      -
-Python/perf_trampoline.c       -       trampoline_api  -
 Python/thread_pthread_stubs.h  -       py_tls_entries  -
 
 
@@ -374,9 +363,8 @@ Modules/itertoolsmodule.c   -       teedataobject_type      -
 Modules/itertoolsmodule.c      -       ziplongest_type -
 
 ##-----------------------
-## other
-
 ## state
+
 Modules/faulthandler.c -       fatal_error     -
 Modules/faulthandler.c -       thread  -
 Modules/faulthandler.c -       user_signals    -