Skip to content

Commit 91a8e00

Browse files
gh-81057: Move More Globals to _PyRuntimeState (gh-100092)
#81057
1 parent d47ffeb commit 91a8e00

14 files changed

+66
-56
lines changed

Include/internal/pycore_dtoa.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Bigint {
2525
#ifdef Py_USING_MEMORY_DEBUGGER
2626

2727
struct _dtoa_runtime_state {
28-
int _not_used;
28+
int _not_used;
2929
};
3030
#define _dtoa_runtime_state_INIT {0}
3131

@@ -41,9 +41,12 @@ struct _dtoa_runtime_state {
4141
((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
4242

4343
struct _dtoa_runtime_state {
44-
struct Bigint *freelist[Bigint_Kmax+1];
45-
double preallocated[Bigint_PREALLOC_SIZE];
46-
double *preallocated_next;
44+
/* p5s is a linked list of powers of 5 of the form 5**(2**i), i >= 2 */
45+
// XXX This should be freed during runtime fini.
46+
struct Bigint *p5s;
47+
struct Bigint *freelist[Bigint_Kmax+1];
48+
double preallocated[Bigint_PREALLOC_SIZE];
49+
double *preallocated_next;
4750
};
4851
#define _dtoa_runtime_state_INIT(runtime) \
4952
{ \

Include/internal/pycore_obmalloc.h

+1
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@ struct _obmalloc_usage {
658658

659659

660660
struct _obmalloc_state {
661+
int dump_debug_stats;
661662
struct _obmalloc_pools pools;
662663
struct _obmalloc_mgmt mgmt;
663664
struct _obmalloc_usage usage;

Include/internal/pycore_obmalloc_init.h

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ extern "C" {
5656

5757
#define _obmalloc_state_INIT(obmalloc) \
5858
{ \
59+
.dump_debug_stats = -1, \
5960
.pools = { \
6061
.used = _obmalloc_pools_INIT(obmalloc.pools), \
6162
}, \

Include/internal/pycore_parser.h

+20
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,31 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE define"
99
#endif
1010

11+
12+
#include "pycore_pyarena.h" // PyArena
13+
14+
15+
#ifdef Py_DEBUG
16+
#define _PYPEGEN_NSTATISTICS 2000
17+
#endif
18+
19+
struct _parser_runtime_state {
20+
#ifdef Py_DEBUG
21+
long memo_statistics[_PYPEGEN_NSTATISTICS];
22+
#else
23+
int _not_used;
24+
#endif
25+
};
26+
27+
28+
1129
extern struct _mod* _PyParser_ASTFromString(
1230
const char *str,
1331
PyObject* filename,
1432
int mode,
1533
PyCompilerFlags *flags,
1634
PyArena *arena);
35+
1736
extern struct _mod* _PyParser_ASTFromFile(
1837
FILE *fp,
1938
PyObject *filename_ob,
@@ -25,6 +44,7 @@ extern struct _mod* _PyParser_ASTFromFile(
2544
int *errcode,
2645
PyArena *arena);
2746

47+
2848
#ifdef __cplusplus
2949
}
3050
#endif

Include/internal/pycore_runtime.h

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ extern "C" {
1717
#include "pycore_global_objects.h" // struct _Py_global_objects
1818
#include "pycore_import.h" // struct _import_runtime_state
1919
#include "pycore_interp.h" // PyInterpreterState
20+
#include "pycore_parser.h" // struct _parser_runtime_state
2021
#include "pycore_pymem.h" // struct _pymem_allocators
2122
#include "pycore_pyhash.h" // struct pyhash_runtime_state
2223
#include "pycore_obmalloc.h" // struct obmalloc_state
@@ -129,6 +130,10 @@ typedef struct pyruntimestate {
129130

130131
unsigned long main_thread;
131132

133+
PyWideStringList orig_argv;
134+
135+
struct _parser_runtime_state parser;
136+
132137
#define NEXITFUNCS 32
133138
void (*exitfuncs[NEXITFUNCS])(void);
134139
int nexitfuncs;

Include/internal/pycore_unicodeobject.h

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

1111
#include "pycore_fileutils.h" // _Py_error_handler
12+
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
1213

1314
void _PyUnicode_ExactDealloc(PyObject *op);
1415

@@ -52,6 +53,8 @@ struct _Py_unicode_ids {
5253
struct _Py_unicode_state {
5354
struct _Py_unicode_fs_codec fs_codec;
5455

56+
_PyUnicode_Name_CAPI *ucnhash_capi;
57+
5558
// Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId()
5659
struct _Py_unicode_ids ids;
5760
};

Modules/_io/bufferedio.c

+12-12
Original file line numberDiff line numberDiff line change
@@ -746,26 +746,26 @@ _buffered_init(buffered *self)
746746
int
747747
_PyIO_trap_eintr(void)
748748
{
749-
static PyObject *eintr_int = NULL;
750749
PyObject *typ, *val, *tb;
751750
PyOSErrorObject *env_err;
752-
753-
if (eintr_int == NULL) {
754-
eintr_int = PyLong_FromLong(EINTR);
755-
assert(eintr_int != NULL);
756-
}
757751
if (!PyErr_ExceptionMatches(PyExc_OSError))
758752
return 0;
759753
PyErr_Fetch(&typ, &val, &tb);
760754
PyErr_NormalizeException(&typ, &val, &tb);
761755
env_err = (PyOSErrorObject *) val;
762756
assert(env_err != NULL);
763-
if (env_err->myerrno != NULL &&
764-
PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
765-
Py_DECREF(typ);
766-
Py_DECREF(val);
767-
Py_XDECREF(tb);
768-
return 1;
757+
if (env_err->myerrno != NULL) {
758+
assert(EINTR > 0 && EINTR < INT_MAX);
759+
assert(PyLong_CheckExact(env_err->myerrno));
760+
int overflow;
761+
int myerrno = PyLong_AsLongAndOverflow(env_err->myerrno, &overflow);
762+
PyErr_Clear();
763+
if (myerrno == EINTR) {
764+
Py_DECREF(typ);
765+
Py_DECREF(val);
766+
Py_XDECREF(tb);
767+
return 1;
768+
}
769769
}
770770
/* This silences any error set by PyObject_RichCompareBool() */
771771
PyErr_Restore(typ, val, tb);

Objects/obmalloc.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -908,11 +908,12 @@ new_arena(void)
908908
struct arena_object* arenaobj;
909909
uint excess; /* number of bytes above pool alignment */
910910
void *address;
911-
static int debug_stats = -1;
912911

912+
int debug_stats = _PyRuntime.obmalloc.dump_debug_stats;
913913
if (debug_stats == -1) {
914914
const char *opt = Py_GETENV("PYTHONMALLOCSTATS");
915915
debug_stats = (opt != NULL && *opt != '\0');
916+
_PyRuntime.obmalloc.dump_debug_stats = debug_stats;
916917
}
917918
if (debug_stats) {
918919
_PyObject_DebugMallocStats(stderr);

Objects/unicodeobject.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -5697,8 +5697,6 @@ PyUnicode_AsUTF16String(PyObject *unicode)
56975697

56985698
/* --- Unicode Escape Codec ----------------------------------------------- */
56995699

5700-
static _PyUnicode_Name_CAPI *ucnhash_capi = NULL;
5701-
57025700
PyObject *
57035701
_PyUnicode_DecodeUnicodeEscapeInternal(const char *s,
57045702
Py_ssize_t size,
@@ -5711,6 +5709,8 @@ _PyUnicode_DecodeUnicodeEscapeInternal(const char *s,
57115709
const char *end;
57125710
PyObject *errorHandler = NULL;
57135711
PyObject *exc = NULL;
5712+
_PyUnicode_Name_CAPI *ucnhash_capi;
5713+
PyInterpreterState *interp = _PyInterpreterState_Get();
57145714

57155715
// so we can remember if we've seen an invalid escape char or not
57165716
*first_invalid_escape = NULL;
@@ -5858,6 +5858,7 @@ _PyUnicode_DecodeUnicodeEscapeInternal(const char *s,
58585858

58595859
/* \N{name} */
58605860
case 'N':
5861+
ucnhash_capi = interp->unicode.ucnhash_capi;
58615862
if (ucnhash_capi == NULL) {
58625863
/* load the unicode data module */
58635864
ucnhash_capi = (_PyUnicode_Name_CAPI *)PyCapsule_Import(
@@ -5869,6 +5870,7 @@ _PyUnicode_DecodeUnicodeEscapeInternal(const char *s,
58695870
);
58705871
goto onError;
58715872
}
5873+
interp->unicode.ucnhash_capi = ucnhash_capi;
58725874
}
58735875

58745876
message = "malformed \\N character escape";
@@ -15128,10 +15130,10 @@ _PyUnicode_Fini(PyInterpreterState *interp)
1512815130
assert(get_interned_dict() == NULL);
1512915131
// bpo-47182: force a unicodedata CAPI capsule re-import on
1513015132
// subsequent initialization of main interpreter.
15131-
ucnhash_capi = NULL;
1513215133
}
1513315134

1513415135
_PyUnicode_FiniEncodings(&state->fs_codec);
15136+
interp->unicode.ucnhash_capi = NULL;
1513515137

1513615138
unicode_clear_identifiers(state);
1513715139
}

Parser/pegen.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,8 @@ _PyPegen_fill_token(Parser *p)
246246
// The array counts the number of tokens skipped by memoization,
247247
// indexed by type.
248248

249-
#define NSTATISTICS 2000
250-
static long memo_statistics[NSTATISTICS];
249+
#define NSTATISTICS _PYPEGEN_NSTATISTICS
250+
#define memo_statistics _PyRuntime.parser.memo_statistics
251251

252252
void
253253
_PyPegen_clear_memo_statistics()

Python/dtoa.c

+2-6
Original file line numberDiff line numberDiff line change
@@ -673,10 +673,6 @@ mult(Bigint *a, Bigint *b)
673673

674674
#ifndef Py_USING_MEMORY_DEBUGGER
675675

676-
/* p5s is a linked list of powers of 5 of the form 5**(2**i), i >= 2 */
677-
678-
static Bigint *p5s;
679-
680676
/* multiply the Bigint b by 5**k. Returns a pointer to the result, or NULL on
681677
failure; if the returned pointer is distinct from b then the original
682678
Bigint b will have been Bfree'd. Ignores the sign of b. */
@@ -696,15 +692,15 @@ pow5mult(Bigint *b, int k)
696692

697693
if (!(k >>= 2))
698694
return b;
699-
p5 = p5s;
695+
p5 = _PyRuntime.dtoa.p5s;
700696
if (!p5) {
701697
/* first time */
702698
p5 = i2b(625);
703699
if (p5 == NULL) {
704700
Bfree(b);
705701
return NULL;
706702
}
707-
p5s = p5;
703+
_PyRuntime.dtoa.p5s = p5;
708704
p5->next = 0;
709705
}
710706
for(;;) {

Python/initconfig.c

+6-8
Original file line numberDiff line numberDiff line change
@@ -595,17 +595,13 @@ _Py_ClearStandardStreamEncoding(void)
595595

596596
/* --- Py_GetArgcArgv() ------------------------------------------- */
597597

598-
/* For Py_GetArgcArgv(); set by _Py_SetArgcArgv() */
599-
static PyWideStringList orig_argv = {.length = 0, .items = NULL};
600-
601-
602598
void
603599
_Py_ClearArgcArgv(void)
604600
{
605601
PyMemAllocatorEx old_alloc;
606602
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
607603

608-
_PyWideStringList_Clear(&orig_argv);
604+
_PyWideStringList_Clear(&_PyRuntime.orig_argv);
609605

610606
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
611607
}
@@ -620,7 +616,9 @@ _Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)
620616
PyMemAllocatorEx old_alloc;
621617
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
622618

623-
res = _PyWideStringList_Copy(&orig_argv, &argv_list);
619+
// XXX _PyRuntime.orig_argv only gets cleared by Py_Main(),
620+
// so it it currently leaks for embedders.
621+
res = _PyWideStringList_Copy(&_PyRuntime.orig_argv, &argv_list);
624622

625623
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
626624
return res;
@@ -631,8 +629,8 @@ _Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)
631629
void
632630
Py_GetArgcArgv(int *argc, wchar_t ***argv)
633631
{
634-
*argc = (int)orig_argv.length;
635-
*argv = orig_argv.items;
632+
*argc = (int)_PyRuntime.orig_argv.length;
633+
*argv = _PyRuntime.orig_argv.items;
636634
}
637635

638636

Tools/c-analyzer/cpython/globals-to-fix.tsv

-9
Original file line numberDiff line numberDiff line change
@@ -305,20 +305,12 @@ Objects/sliceobject.c - _Py_EllipsisObject -
305305
##-----------------------
306306
## effectively-const but initialized lazily
307307

308-
## idempotent
309-
Python/dtoa.c - p5s -
310-
Objects/obmalloc.c new_arena debug_stats -
311-
312308
## others
313309
Python/perf_trampoline.c - perf_map_file -
314-
Objects/unicodeobject.c - ucnhash_capi -
315310

316311
##-----------------------
317312
## state
318313

319-
## local buffer
320-
Python/suggestions.c levenshtein_distance buffer -
321-
322314
## other
323315
Objects/object.c - _Py_RefTotal -
324316
Python/perf_trampoline.c - perf_status -
@@ -398,7 +390,6 @@ Modules/faulthandler.c - old_stack -
398390
##-----------------------
399391
## initialized once
400392

401-
Modules/_io/bufferedio.c _PyIO_trap_eintr eintr_int -
402393
Modules/posixmodule.c os_dup2_impl dup3_works -
403394
Modules/posixmodule.c - structseq_new -
404395
Modules/posixmodule.c - ticks_per_second -

Tools/c-analyzer/cpython/ignored.tsv

-11
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ Parser/myreadline.c - PyOS_ReadlineFunctionPointer -
8787

8888
Python/initconfig.c - _Py_StandardStreamEncoding -
8989
Python/initconfig.c - _Py_StandardStreamErrors -
90-
# XXX This only gets cleared by Py_Main().
91-
Python/initconfig.c - orig_argv -
9290

9391
##-----------------------
9492
## public C-API
@@ -143,15 +141,6 @@ Python/pylifecycle.c - runtime_initialized -
143141
Modules/syslogmodule.c - S_ident_o -
144142
Modules/syslogmodule.c - S_log_open -
145143

146-
##-----------------------
147-
## *not* tied to init/fini cycle
148-
149-
# These do not ge reset with each init/fini cycle.
150-
# XXX These should probably be tied to init/fini. Move to _PyRuntimeState?
151-
152-
# special-use diagnistic state
153-
Parser/pegen.c - memo_statistics -
154-
155144
##-----------------------
156145
## one-off temporary state
157146

0 commit comments

Comments
 (0)