]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-81057: Move Globals in Core Code to _PyRuntimeState (gh-99496)
authorEric Snow <ericsnowcurrently@gmail.com>
Tue, 15 Nov 2022 16:45:11 +0000 (09:45 -0700)
committerGitHub <noreply@github.com>
Tue, 15 Nov 2022 16:45:11 +0000 (09:45 -0700)
This is the first of several changes to consolidate non-object globals in core code.

https://github.com/python/cpython/issues/81057

17 files changed:
Include/internal/pycore_dtoa.h
Include/internal/pycore_interp.h
Include/internal/pycore_pylifecycle.h
Include/internal/pycore_pymem.h
Include/internal/pycore_runtime.h
Include/internal/pycore_runtime_init.h
Modules/_tracemalloc.c
Modules/getbuildinfo.c
Objects/object.c
Objects/obmalloc.c
Parser/action_helpers.c
Python/dtoa.c
Python/getargs.c
Python/getversion.c
Python/pylifecycle.c
Tools/c-analyzer/cpython/globals-to-fix.tsv
Tools/c-analyzer/cpython/ignored.tsv

index c77cf6e46cc3c369c8df96104fd1d860b970dff3..fdc6e74ecd25e3ce11d18a3a367b950b00f4be72 100644 (file)
@@ -1,3 +1,5 @@
+#ifndef Py_INTERNAL_DTOA_H
+#define Py_INTERNAL_DTOA_H
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -11,6 +13,46 @@ extern "C" {
 
 #if _PY_SHORT_FLOAT_REPR == 1
 
+typedef uint32_t ULong;
+
+struct
+Bigint {
+    struct Bigint *next;
+    int k, maxwds, sign, wds;
+    ULong x[1];
+};
+
+#ifdef Py_USING_MEMORY_DEBUGGER
+
+struct _dtoa_runtime_state {
+        int _not_used;
+};
+#define _dtoa_runtime_state_INIT {0}
+
+#else  // !Py_USING_MEMORY_DEBUGGER
+
+/* The size of the Bigint freelist */
+#define Bigint_Kmax 7
+
+#ifndef PRIVATE_MEM
+#define PRIVATE_MEM 2304
+#endif
+#define Bigint_PREALLOC_SIZE \
+    ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
+
+struct _dtoa_runtime_state {
+        struct Bigint *freelist[Bigint_Kmax+1];
+        double preallocated[Bigint_PREALLOC_SIZE];
+        double *preallocated_next;
+};
+#define _dtoa_runtime_state_INIT(runtime) \
+    { \
+        .preallocated_next = runtime.dtoa.preallocated, \
+    }
+
+#endif  // !Py_USING_MEMORY_DEBUGGER
+
+
 /* These functions are used by modules compiled as C extension like math:
    they must be exported. */
 
@@ -26,3 +68,4 @@ PyAPI_FUNC(double) _Py_dg_infinity(int sign);
 #ifdef __cplusplus
 }
 #endif
+#endif /* !Py_INTERNAL_DTOA_H */
index 7c998ac770c8b66b02e81b6f3a34523f79736384..a13bc32e11449075ccc1e83c314239525ff88fc6 100644 (file)
@@ -26,6 +26,7 @@ extern "C" {
 #include "pycore_unicodeobject.h" // struct _Py_unicode_state
 #include "pycore_warnings.h"      // struct _warnings_runtime_state
 
+
 struct _pending_calls {
     PyThread_type_lock lock;
     /* Request for running pending calls. */
index 85bf166d92fd47a12d9c43cdf51223be54f98b64..359b809d5870a1cde08fd908c42e1ed500c7dafe 100644 (file)
@@ -33,6 +33,7 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc);
 
 /* Various one-time initializers */
 
+extern void _Py_InitVersion(void);
 extern PyStatus _PyImport_Init(void);
 extern PyStatus _PyFaulthandler_Init(int enable);
 extern int _PyTraceMalloc_Init(int enable);
index b042a4cb268e54c91b51b5b98b7a2529cb2f115f..5749af7465f6f0681a083dfd9313cbc0e5e868b4 100644 (file)
@@ -113,8 +113,6 @@ struct _PyTraceMalloc_Config {
      .tracing = 0, \
      .max_nframe = 1}
 
-PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config;
-
 #ifdef __cplusplus
 }
 #endif
index 6bcb35b35610f0acb1c79e1acc66794d11c3ea65..8b2b9d7a85b231cf6c328d9f8dba304aa134473a 100644 (file)
@@ -9,6 +9,7 @@ extern "C" {
 #endif
 
 #include "pycore_atomic.h"          /* _Py_atomic_address */
+#include "pycore_dtoa.h"            // struct _dtoa_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
@@ -18,7 +19,8 @@ extern "C" {
 #include "pycore_unicodeobject.h"   // struct _Py_unicode_runtime_ids
 
 struct _getargs_runtime_state {
-   PyThread_type_lock mutex;
+    PyThread_type_lock mutex;
+    struct _PyArg_Parser *static_parsers;
 };
 
 /* ceval state */
@@ -125,6 +127,10 @@ typedef struct pyruntimestate {
     struct _ceval_runtime_state ceval;
     struct _gilstate_runtime_state gilstate;
     struct _getargs_runtime_state getargs;
+    struct {
+        struct _PyTraceMalloc_Config config;
+    } tracemalloc;
+    struct _dtoa_runtime_state dtoa;
 
     PyPreConfig preconfig;
 
index 62d50631d33b07119a730e0b32da233f88686f35..6bdee36a851c28e2a2e377e776ed45b384a37696 100644 (file)
@@ -36,6 +36,10 @@ extern "C" {
               until _PyInterpreterState_Enable() is called. */ \
             .next_id = -1, \
         }, \
+        .tracemalloc = { \
+            .config = _PyTraceMalloc_Config_INIT, \
+        }, \
+        .dtoa = _dtoa_runtime_state_INIT(runtime), \
         .types = { \
             .next_version_tag = 1, \
         }, \
index fe73d63d411f5f4b8cd67c9148ce63b5b3e4038f..0d70f0cf34c8d6f037de1267d4752c603949d4cd 100644 (file)
@@ -16,6 +16,8 @@ module _tracemalloc
 [clinic start generated code]*/
 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/
 
+#define tracemalloc_config _PyRuntime.tracemalloc.config
+
 _Py_DECLARE_STR(anon_unknown, "<unknown>");
 
 /* Trace memory blocks allocated by PyMem_RawMalloc() */
@@ -407,7 +409,7 @@ traceback_get_frames(traceback_t *traceback)
         if (pyframe == NULL) {
             break;
         }
-        if (traceback->nframe < _Py_tracemalloc_config.max_nframe) {
+        if (traceback->nframe < tracemalloc_config.max_nframe) {
             tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
             assert(traceback->frames[traceback->nframe].filename != NULL);
             traceback->nframe++;
@@ -505,7 +507,7 @@ tracemalloc_get_traces_table(unsigned int domain)
 static void
 tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
 {
-    assert(_Py_tracemalloc_config.tracing);
+    assert(tracemalloc_config.tracing);
 
     _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain);
     if (!traces) {
@@ -529,7 +531,7 @@ static int
 tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
                       size_t size)
 {
-    assert(_Py_tracemalloc_config.tracing);
+    assert(tracemalloc_config.tracing);
 
     traceback_t *traceback = traceback_new();
     if (traceback == NULL) {
@@ -863,13 +865,13 @@ tracemalloc_clear_traces(void)
 static int
 tracemalloc_init(void)
 {
-    if (_Py_tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
+    if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
         PyErr_SetString(PyExc_RuntimeError,
                         "the tracemalloc module has been unloaded");
         return -1;
     }
 
-    if (_Py_tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
+    if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
         return 0;
 
     PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
@@ -919,7 +921,7 @@ tracemalloc_init(void)
     tracemalloc_empty_traceback.frames[0].lineno = 0;
     tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
 
-    _Py_tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
+    tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
     return 0;
 }
 
@@ -927,9 +929,9 @@ tracemalloc_init(void)
 static void
 tracemalloc_deinit(void)
 {
-    if (_Py_tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
+    if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
         return;
-    _Py_tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
+    tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
 
     tracemalloc_stop();
 
@@ -969,12 +971,12 @@ tracemalloc_start(int max_nframe)
         return -1;
     }
 
-    if (_Py_tracemalloc_config.tracing) {
+    if (tracemalloc_config.tracing) {
         /* hook already installed: do nothing */
         return 0;
     }
 
-    _Py_tracemalloc_config.max_nframe = max_nframe;
+    tracemalloc_config.max_nframe = max_nframe;
 
     /* allocate a buffer to store a new traceback */
     size = TRACEBACK_SIZE(max_nframe);
@@ -1010,7 +1012,7 @@ tracemalloc_start(int max_nframe)
     PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
 
     /* everything is ready: start tracing Python memory allocations */
-    _Py_tracemalloc_config.tracing = 1;
+    tracemalloc_config.tracing = 1;
 
     return 0;
 }
@@ -1019,11 +1021,11 @@ tracemalloc_start(int max_nframe)
 static void
 tracemalloc_stop(void)
 {
-    if (!_Py_tracemalloc_config.tracing)
+    if (!tracemalloc_config.tracing)
         return;
 
     /* stop tracing Python memory allocations */
-    _Py_tracemalloc_config.tracing = 0;
+    tracemalloc_config.tracing = 0;
 
     /* unregister the hook on memory allocators */
 #ifdef TRACE_RAW_MALLOC
@@ -1051,7 +1053,7 @@ static PyObject *
 _tracemalloc_is_tracing_impl(PyObject *module)
 /*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
 {
-    return PyBool_FromLong(_Py_tracemalloc_config.tracing);
+    return PyBool_FromLong(tracemalloc_config.tracing);
 }
 
 
@@ -1065,7 +1067,7 @@ static PyObject *
 _tracemalloc_clear_traces_impl(PyObject *module)
 /*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
 {
-    if (!_Py_tracemalloc_config.tracing)
+    if (!tracemalloc_config.tracing)
         Py_RETURN_NONE;
 
     set_reentrant(1);
@@ -1345,7 +1347,7 @@ _tracemalloc__get_traces_impl(PyObject *module)
     if (get_traces.list == NULL)
         goto error;
 
-    if (!_Py_tracemalloc_config.tracing)
+    if (!tracemalloc_config.tracing)
         return get_traces.list;
 
     /* the traceback hash table is used temporarily to intern traceback tuple
@@ -1418,7 +1420,7 @@ static traceback_t*
 tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
 {
 
-    if (!_Py_tracemalloc_config.tracing)
+    if (!tracemalloc_config.tracing)
         return NULL;
 
     trace_t *trace;
@@ -1498,7 +1500,7 @@ _PyMem_DumpTraceback(int fd, const void *ptr)
     traceback_t *traceback;
     int i;
 
-    if (!_Py_tracemalloc_config.tracing) {
+    if (!tracemalloc_config.tracing) {
         PUTS(fd, "Enable tracemalloc to get the memory block "
                  "allocation traceback\n\n");
         return;
@@ -1572,7 +1574,7 @@ static PyObject *
 _tracemalloc_get_traceback_limit_impl(PyObject *module)
 /*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
 {
-    return PyLong_FromLong(_Py_tracemalloc_config.max_nframe);
+    return PyLong_FromLong(tracemalloc_config.max_nframe);
 }
 
 
@@ -1630,7 +1632,7 @@ _tracemalloc_get_traced_memory_impl(PyObject *module)
 {
     Py_ssize_t size, peak_size;
 
-    if (!_Py_tracemalloc_config.tracing)
+    if (!tracemalloc_config.tracing)
         return Py_BuildValue("ii", 0, 0);
 
     TABLES_LOCK();
@@ -1654,7 +1656,7 @@ static PyObject *
 _tracemalloc_reset_peak_impl(PyObject *module)
 /*[clinic end generated code: output=140c2870f691dbb2 input=18afd0635066e9ce]*/
 {
-    if (!_Py_tracemalloc_config.tracing) {
+    if (!tracemalloc_config.tracing) {
         Py_RETURN_NONE;
     }
 
@@ -1735,7 +1737,7 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
     int res;
     PyGILState_STATE gil_state;
 
-    if (!_Py_tracemalloc_config.tracing) {
+    if (!tracemalloc_config.tracing) {
         /* tracemalloc is not tracing: do nothing */
         return -2;
     }
@@ -1754,7 +1756,7 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
 int
 PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
 {
-    if (!_Py_tracemalloc_config.tracing) {
+    if (!tracemalloc_config.tracing) {
         /* tracemalloc is not tracing: do nothing */
         return -2;
     }
@@ -1777,7 +1779,7 @@ _PyTraceMalloc_NewReference(PyObject *op)
 {
     assert(PyGILState_Check());
 
-    if (!_Py_tracemalloc_config.tracing) {
+    if (!tracemalloc_config.tracing) {
         /* tracemalloc is not tracing: do nothing */
         return -1;
     }
index 7cb7397a22c8ab74fbbd509ac7cf22e96672cd49..a24750b76c09bc291223e6fc9151630de4f899e2 100644 (file)
 #define GITBRANCH ""
 #endif
 
+static int initialized = 0;
+static char buildinfo[50 + sizeof(GITVERSION) +
+                      ((sizeof(GITTAG) > sizeof(GITBRANCH)) ?
+                       sizeof(GITTAG) : sizeof(GITBRANCH))];
+
 const char *
 Py_GetBuildInfo(void)
 {
-    static char buildinfo[50 + sizeof(GITVERSION) +
-                          ((sizeof(GITTAG) > sizeof(GITBRANCH)) ?
-                           sizeof(GITTAG) : sizeof(GITBRANCH))];
+    if (initialized) {
+        return buildinfo;
+    }
+    initialized = 1;
     const char *revision = _Py_gitversion();
     const char *sep = *revision ? ":" : "";
     const char *gitid = _Py_gitidentifier();
index 01eede94d58b5d9f7ce011918b3af1a3457ecfc1..a499cb32b22f587d0fb4a3d8785d263285ab30c2 100644 (file)
@@ -2001,7 +2001,7 @@ _PyTypes_FiniTypes(PyInterpreterState *interp)
 void
 _Py_NewReference(PyObject *op)
 {
-    if (_Py_tracemalloc_config.tracing) {
+    if (_PyRuntime.tracemalloc.config.tracing) {
         _PyTraceMalloc_NewReference(op);
     }
 #ifdef Py_REF_DEBUG
index 481cbde9fd31703908704b9850bb06fc476746ec..4c08bc214cd27a12b4c34f9f44b01502f5187217 100644 (file)
@@ -201,12 +201,6 @@ _PyMem_ArenaFree(void *Py_UNUSED(ctx), void *ptr,
 #endif
 
 
-/* bpo-35053: Declare tracemalloc configuration here rather than
-   Modules/_tracemalloc.c because _tracemalloc can be compiled as dynamic
-   library, whereas _Py_NewReference() requires it. */
-struct _PyTraceMalloc_Config _Py_tracemalloc_config = _PyTraceMalloc_Config_INIT;
-
-
 #define _PyMem_Raw (_PyRuntime.allocators.standard.raw)
 #define _PyMem (_PyRuntime.allocators.standard.mem)
 #define _PyObject (_PyRuntime.allocators.standard.obj)
index d1be679aff2e7b0b2f4f6b3c6c65c1f16d3e7cc8..27c093332f6725eccb78f6c2bb6cf2218c9b9def 100644 (file)
@@ -12,6 +12,7 @@ _create_dummy_identifier(Parser *p)
 void *
 _PyPegen_dummy_name(Parser *p, ...)
 {
+    // XXX This leaks memory from the initial arena.
     static void *cache = NULL;
 
     if (cache != NULL) {
index 733e70bc7916984628d0e4601b60aeeb319c47d3..1b47d83bf77a24225a0900e572fca599638cbedf 100644 (file)
 
 #include "Python.h"
 #include "pycore_dtoa.h"          // _PY_SHORT_FLOAT_REPR
+#include "pycore_runtime.h"       // _PyRuntime
 #include <stdlib.h>               // exit()
 
 /* if _PY_SHORT_FLOAT_REPR == 0, then don't even try to compile
 #endif
 
 
-typedef uint32_t ULong;
+// ULong is defined in pycore_dtoa.h.
 typedef int32_t Long;
 typedef uint64_t ULLong;
 
@@ -171,12 +172,6 @@ typedef uint64_t ULLong;
 #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
 #endif
 
-#ifndef PRIVATE_MEM
-#define PRIVATE_MEM 2304
-#endif
-#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
-static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -298,8 +293,6 @@ BCinfo {
 
 #define FFFFFFFF 0xffffffffUL
 
-#define Kmax 7
-
 /* struct Bigint is used to represent arbitrary-precision integers.  These
    integers are stored in sign-magnitude format, with the magnitude stored as
    an array of base 2**32 digits.  Bigints are always normalized: if x is a
@@ -322,13 +315,7 @@ BCinfo {
        significant (x[0]) to most significant (x[wds-1]).
 */
 
-struct
-Bigint {
-    struct Bigint *next;
-    int k, maxwds, sign, wds;
-    ULong x[1];
-};
-
+// struct Bigint is defined in pycore_dtoa.h.
 typedef struct Bigint Bigint;
 
 #ifndef Py_USING_MEMORY_DEBUGGER
@@ -352,7 +339,9 @@ typedef struct Bigint Bigint;
    Bfree to PyMem_Free.  Investigate whether this has any significant
    performance on impact. */
 
-static Bigint *freelist[Kmax+1];
+#define freelist _PyRuntime.dtoa.freelist
+#define private_mem _PyRuntime.dtoa.preallocated
+#define pmem_next _PyRuntime.dtoa.preallocated_next
 
 /* Allocate space for a Bigint with up to 1<<k digits */
 
@@ -363,13 +352,15 @@ Balloc(int k)
     Bigint *rv;
     unsigned int len;
 
-    if (k <= Kmax && (rv = freelist[k]))
+    if (k <= Bigint_Kmax && (rv = freelist[k]))
         freelist[k] = rv->next;
     else {
         x = 1 << k;
         len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
             /sizeof(double);
-        if (k <= Kmax && pmem_next - private_mem + len <= (Py_ssize_t)PRIVATE_mem) {
+        if (k <= Bigint_Kmax &&
+            pmem_next - private_mem + len <= (Py_ssize_t)Bigint_PREALLOC_SIZE
+        ) {
             rv = (Bigint*)pmem_next;
             pmem_next += len;
         }
@@ -391,7 +382,7 @@ static void
 Bfree(Bigint *v)
 {
     if (v) {
-        if (v->k > Kmax)
+        if (v->k > Bigint_Kmax)
             FREE((void*)v);
         else {
             v->next = freelist[v->k];
@@ -400,6 +391,10 @@ Bfree(Bigint *v)
     }
 }
 
+#undef pmem_next
+#undef private_mem
+#undef freelist
+
 #else
 
 /* Alternative versions of Balloc and Bfree that use PyMem_Malloc and
index 703462242a0585938bcf0951e129a8150999b669..748209d7d713f8a8affdb10490198614ac2f7005 100644 (file)
@@ -1846,9 +1846,6 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
 }
 
 
-/* List of static parsers. */
-static struct _PyArg_Parser *static_arg_parsers = NULL;
-
 static int
 scan_keywords(const char * const *keywords, int *ptotal, int *pposonly)
 {
@@ -2024,8 +2021,8 @@ _parser_init(struct _PyArg_Parser *parser)
     parser->initialized = owned ? 1 : -1;
 
     assert(parser->next == NULL);
-    parser->next = static_arg_parsers;
-    static_arg_parsers = parser;
+    parser->next = _PyRuntime.getargs.static_parsers;
+    _PyRuntime.getargs.static_parsers = parser;
     return 1;
 }
 
@@ -2930,14 +2927,14 @@ _PyArg_NoKwnames(const char *funcname, PyObject *kwnames)
 void
 _PyArg_Fini(void)
 {
-    struct _PyArg_Parser *tmp, *s = static_arg_parsers;
+    struct _PyArg_Parser *tmp, *s = _PyRuntime.getargs.static_parsers;
     while (s) {
         tmp = s->next;
         s->next = NULL;
         parser_clear(s);
         s = tmp;
     }
-    static_arg_parsers = NULL;
+    _PyRuntime.getargs.static_parsers = NULL;
 }
 
 #ifdef __cplusplus
index 46910451fdf859f1836e4a1148adc3588dbb3712..5db836ab4bfd6d4beb8411fccd0d46a0743ac579 100644 (file)
@@ -5,12 +5,23 @@
 
 #include "patchlevel.h"
 
-const char *
-Py_GetVersion(void)
+static int initialized = 0;
+static char version[250];
+
+void _Py_InitVersion(void)
 {
-    static char version[250];
+    if (initialized) {
+        return;
+    }
+    initialized = 1;
     PyOS_snprintf(version, sizeof(version), "%.80s (%.80s) %.80s",
                   PY_VERSION, Py_GetBuildInfo(), Py_GetCompiler());
+}
+
+const char *
+Py_GetVersion(void)
+{
+    _Py_InitVersion();
     return version;
 }
 
index 44f844249b13b972a4e3955d21c5afa9c10e1118..7ca284ef1efb9dd8c0da069ef51a9dced993c48a 100644 (file)
@@ -600,6 +600,8 @@ pycore_init_runtime(_PyRuntimeState *runtime,
      */
     _PyRuntimeState_SetFinalizing(runtime, NULL);
 
+    _Py_InitVersion();
+
     status = _Py_HashRandomization_Init(config);
     if (_PyStatus_EXCEPTION(status)) {
         return status;
index b60f16db9a28acd37e0770857fbffaa6942a6274..b4ac9120d98bb075826a417fa30dc9defbeb40e2 100644 (file)
@@ -311,110 +311,22 @@ Python/hamt.c    -       _empty_hamt     -
 # global non-objects to fix in core code
 
 #-----------------------
-# initialized/set once
+# effectively-const but initialized lazily
 
-# pre-allocated buffer
-Modules/getbuildinfo.c Py_GetBuildInfo buildinfo       -
-
-# during init
-Objects/unicodeobject.c        -       bloom_linebreak -
-Python/bootstrap_hash.c        -       _Py_HashSecret_Initialized      -
-Python/bootstrap_hash.c        py_getrandom    getrandom_works -
-Python/initconfig.c    -       _Py_global_config_int_max_str_digits    -
-Python/initconfig.c    -       Py_DebugFlag    -
-Python/initconfig.c    -       Py_UTF8Mode     -
-Python/initconfig.c    -       Py_DebugFlag    -
-Python/initconfig.c    -       Py_VerboseFlag  -
-Python/initconfig.c    -       Py_QuietFlag    -
-Python/initconfig.c    -       Py_InteractiveFlag      -
-Python/initconfig.c    -       Py_InspectFlag  -
-Python/initconfig.c    -       Py_OptimizeFlag -
-Python/initconfig.c    -       Py_NoSiteFlag   -
-Python/initconfig.c    -       Py_BytesWarningFlag     -
-Python/initconfig.c    -       Py_FrozenFlag   -
-Python/initconfig.c    -       Py_IgnoreEnvironmentFlag        -
-Python/initconfig.c    -       Py_DontWriteBytecodeFlag        -
-Python/initconfig.c    -       Py_NoUserSiteDirectory  -
-Python/initconfig.c    -       Py_UnbufferedStdioFlag  -
-Python/initconfig.c    -       Py_HashRandomizationFlag        -
-Python/initconfig.c    -       Py_IsolatedFlag -
-Python/initconfig.c    -       Py_LegacyWindowsFSEncodingFlag  -
-Python/initconfig.c    -       Py_LegacyWindowsStdioFlag       -
-Python/initconfig.c    -       orig_argv       -
-Python/pyhash.c        -       _Py_HashSecret  -
-Python/pylifecycle.c   -       runtime_initialized     -
-Python/sysmodule.c     -       _PySys_ImplCacheTag     -
-Python/sysmodule.c     -       _PySys_ImplName -
-Python/sysmodule.c     -       _preinit_warnoptions    -
-Python/sysmodule.c     -       _preinit_xoptions       -
-Python/thread.c        -       initialized     -
-Python/thread_pthread.h        -       condattr_monotonic      -
-Python/thread_pthread.h        init_condattr   ca      -
-
-# set by embedders during init
-Python/initconfig.c    -       _Py_StandardStreamEncoding      -
-Python/initconfig.c    -       _Py_StandardStreamErrors        -
-
-# lazy
-Objects/floatobject.c  -       double_format   -
-Objects/floatobject.c  -       float_format    -
-Objects/longobject.c   long_from_non_binary_base       log_base_BASE   -
-Objects/longobject.c   long_from_non_binary_base       convwidth_base  -
-Objects/longobject.c   long_from_non_binary_base       convmultmax_base        -
-Python/perf_trampoline.c       -       perf_map_file   -
-Objects/unicodeobject.c        -       ucnhash_capi    -
-Parser/action_helpers.c        _PyPegen_dummy_name     cache   -
+# idempotent
 Python/dtoa.c  -       p5s     -
-Python/fileutils.c     -       _Py_open_cloexec_works  -
-Python/fileutils.c     -       force_ascii     -
-Python/fileutils.c     set_inheritable ioctl_works     -
+Objects/obmalloc.c     new_arena       debug_stats     -
 
-#-----------------------
-# unlikely to change after init (or main thread)
-
-# through C-API
-Python/frozen.c        -       PyImport_FrozenModules  -
-Python/frozen.c        -       _PyImport_FrozenAliases -
-Python/frozen.c        -       _PyImport_FrozenBootstrap       -
-Python/frozen.c        -       _PyImport_FrozenStdlib  -
-Python/frozen.c        -       _PyImport_FrozenTest    -
-Python/preconfig.c     -       Py_FileSystemDefaultEncoding    -
-Python/preconfig.c     -       Py_HasFileSystemDefaultEncoding -
-Python/preconfig.c     -       Py_FileSystemDefaultEncodeErrors        -
-Python/preconfig.c     -       _Py_HasFileSystemDefaultEncodeErrors    -
-
-# REPL
-Parser/myreadline.c    -       _PyOS_ReadlineLock      -
-Parser/myreadline.c    -       _PyOS_ReadlineTState    -
-Parser/myreadline.c    -       PyOS_InputHook  -
-Parser/myreadline.c    -       PyOS_ReadlineFunctionPointer    -
-
-# handling C argv
-Python/getopt.c        -       _PyOS_optarg    -
-Python/getopt.c        -       _PyOS_opterr    -
-Python/getopt.c        -       _PyOS_optind    -
-Python/getopt.c        -       opt_ptr -
-Python/pathconfig.c    -       _Py_path_config -
+# others
+Python/perf_trampoline.c       -       perf_map_file   -
+Objects/unicodeobject.c        -       ucnhash_capi    -
 
 #-----------------------
 # state
 
-# object allocator
-Objects/obmalloc.c     -       _Py_tracemalloc_config  -
-Objects/obmalloc.c     new_arena       debug_stats     -
-
-# pre-allocated memory
-Python/dtoa.c  -       freelist        -
-Python/dtoa.c  -       private_mem     -
-
 # local buffer
-Python/getversion.c    Py_GetVersion   version -
 Python/suggestions.c   levenshtein_distance    buffer  -
 
-# linked list
-Python/dtoa.c  -       pmem_next       -
-Python/getargs.c       -       static_arg_parsers      -
-
 # other
 Objects/dictobject.c   -       _pydict_global_version  -
 Objects/dictobject.c   -       next_dict_keys_version  -
index 414e68df60dac9e1cc35ee8dc072b4939b3ff087..0a6f3ec8152dd3c6c804f4a7c87019ed3cac5a3b 100644 (file)
@@ -4,22 +4,111 @@ filename     funcname        name    reason
 ##################################
 # mutable but known to be safe
 
-Python/import.c        -       inittab_copy    -
-Python/import.c        -       PyImport_Inittab        -
 Python/pylifecycle.c   -       _PyRuntime      -
 
 # All uses of _PyArg_Parser are handled in c-analyzr/cpython/_analyzer.py.
 
 #-----------------------
-# others
+# legacy config flags
+
+Python/initconfig.c    -       Py_UTF8Mode     -
+Python/initconfig.c    -       Py_DebugFlag    -
+Python/initconfig.c    -       Py_VerboseFlag  -
+Python/initconfig.c    -       Py_QuietFlag    -
+Python/initconfig.c    -       Py_InteractiveFlag      -
+Python/initconfig.c    -       Py_InspectFlag  -
+Python/initconfig.c    -       Py_OptimizeFlag -
+Python/initconfig.c    -       Py_NoSiteFlag   -
+Python/initconfig.c    -       Py_BytesWarningFlag     -
+Python/initconfig.c    -       Py_FrozenFlag   -
+Python/initconfig.c    -       Py_IgnoreEnvironmentFlag        -
+Python/initconfig.c    -       Py_DontWriteBytecodeFlag        -
+Python/initconfig.c    -       Py_NoUserSiteDirectory  -
+Python/initconfig.c    -       Py_UnbufferedStdioFlag  -
+Python/initconfig.c    -       Py_HashRandomizationFlag        -
+Python/initconfig.c    -       Py_IsolatedFlag -
+Python/initconfig.c    -       Py_LegacyWindowsFSEncodingFlag  -
+Python/initconfig.c    -       Py_LegacyWindowsStdioFlag       -
+
+#-----------------------
+# effectively const, initialized before init
+
+Python/frozen.c        -       PyImport_FrozenModules  -
+Python/import.c        -       inittab_copy    -
+Python/import.c        -       PyImport_Inittab        -
+
+#-----------------------
+# effectively const, initialized before/during init
+
+Modules/getbuildinfo.c -       buildinfo       -
+Modules/getbuildinfo.c -       initialized     -
+Python/getversion.c    -       initialized     -
+Python/getversion.c    -       version -
+
+#-----------------------
+# effectively const, initialized during init
+
+Objects/floatobject.c  -       double_format   -
+Objects/floatobject.c  -       float_format    -
+Objects/unicodeobject.c        -       bloom_linebreak -
+Python/bootstrap_hash.c        py_getrandom    getrandom_works -
+Python/bootstrap_hash.c        -       _Py_HashSecret_Initialized      -
+Python/fileutils.c     -       _Py_open_cloexec_works  -
+Python/fileutils.c     -       force_ascii     -
+Python/fileutils.c     set_inheritable ioctl_works     -
+Python/import.c        import_find_and_load    header  -
+Python/initconfig.c    -       orig_argv       -
+Python/preconfig.c     -       Py_FileSystemDefaultEncoding    -
+Python/preconfig.c     -       Py_HasFileSystemDefaultEncoding -
+Python/preconfig.c     -       Py_FileSystemDefaultEncodeErrors        -
+Python/preconfig.c     -       _Py_HasFileSystemDefaultEncodeErrors    -
+Python/pyhash.c        -       _Py_HashSecret  -
+Python/pylifecycle.c   -       runtime_initialized     -
+Python/sysmodule.c     -       _preinit_warnoptions    -
+Python/sysmodule.c     -       _preinit_xoptions       -
+Python/thread.c        -       initialized     -
+Python/thread_pthread.h        -       condattr_monotonic      -
+Python/thread_pthread.h        init_condattr   ca      -
+
+# set by embedders during init
+Python/initconfig.c    -       _Py_StandardStreamEncoding      -
+Python/initconfig.c    -       _Py_StandardStreamErrors        -
+
+#-----------------------
+# effectively const but initialized lazily
+# XXX Move them to _PyRuntimeState?
+
+# idempotent
+Objects/longobject.c   long_from_non_binary_base       log_base_BASE   -
+Objects/longobject.c   long_from_non_binary_base       convwidth_base  -
+Objects/longobject.c   long_from_non_binary_base       convmultmax_base        -
+Parser/action_helpers.c        _PyPegen_dummy_name     cache   -
+
+#-----------------------
+# used only in the main thread
+
+# REPL
+Parser/myreadline.c    -       _PyOS_ReadlineLock      -
+Parser/myreadline.c    -       _PyOS_ReadlineTState    -
+Parser/myreadline.c    -       PyOS_InputHook  -
+Parser/myreadline.c    -       PyOS_ReadlineFunctionPointer    -
+
+# handling C argv
+Python/getopt.c        -       _PyOS_optarg    -
+Python/getopt.c        -       _PyOS_opterr    -
+Python/getopt.c        -       _PyOS_optind    -
+Python/getopt.c        -       opt_ptr -
+Python/pathconfig.c    -       _Py_path_config -
+
+
+##################################
+# The analyzer should have ignored these.
+# XXX Fix the analyzer.
 
-# XXX The analyzer should have ignored these.
 Modules/_io/_iomodule.c        -       _PyIO_Module    -
 Modules/_sqlite/module.c       -       _sqlite3module  -
 
-##################################
 # forward/extern references
-# XXX The analyzer should have ignored these.
 
 Include/py_curses.h    -       PyCurses_API    -
 Include/pydecimal.h    -       _decimal_api    -
@@ -474,7 +563,6 @@ Objects/obmalloc.c  -       _PyMem_Debug    -
 Objects/obmalloc.c     -       _PyMem_Raw      -
 Objects/obmalloc.c     -       _PyObject       -
 Objects/obmalloc.c     -       usedpools       -
-Python/perf_trampoline.c       -       _Py_perfmap_callbacks   -
 Objects/typeobject.c   -       name_op -
 Objects/typeobject.c   -       slotdefs        -
 Objects/unicodeobject.c        -       stripfuncnames  -
@@ -499,10 +587,15 @@ Python/frozen.c   -       aliases -
 Python/frozen.c        -       bootstrap_modules       -
 Python/frozen.c        -       stdlib_modules  -
 Python/frozen.c        -       test_modules    -
+Python/frozen.c        -       _PyImport_FrozenAliases -
+Python/frozen.c        -       _PyImport_FrozenBootstrap       -
+Python/frozen.c        -       _PyImport_FrozenStdlib  -
+Python/frozen.c        -       _PyImport_FrozenTest    -
 Python/getopt.c        -       longopts        -
 Python/import.c        -       _PyImport_Inittab       -
 Python/import.c        -       _PySys_ImplCacheTag     -
 Python/opcode_targets.h        -       opcode_targets  -
+Python/perf_trampoline.c       -       _Py_perfmap_callbacks   -
 Python/pyhash.c        -       PyHash_Func     -
 Python/pylifecycle.c   -       _C_LOCALE_WARNING       -
 Python/pylifecycle.c   -       _PyOS_mystrnicmp_hack   -
@@ -512,4 +605,6 @@ Python/specialize.c -       adaptive_opcodes        -
 Python/specialize.c    -       cache_requirements      -
 Python/specialize.c    -       compare_masks   -
 Python/stdlib_module_names.h   -       _Py_stdlib_module_names -
+Python/sysmodule.c     -       _PySys_ImplCacheTag     -
+Python/sysmodule.c     -       _PySys_ImplName -
 Python/sysmodule.c     -       whatstrings     -