Skip to content

Commit 3c57971

Browse files
gh-81057: Move Globals in Core Code to _PyRuntimeState (gh-99496)
This is the first of several changes to consolidate non-object globals in core code. #81057
1 parent 73943cb commit 3c57971

17 files changed

+236
-168
lines changed

Include/internal/pycore_dtoa.h

+43
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#ifndef Py_INTERNAL_DTOA_H
2+
#define Py_INTERNAL_DTOA_H
13
#ifdef __cplusplus
24
extern "C" {
35
#endif
@@ -11,6 +13,46 @@ extern "C" {
1113

1214
#if _PY_SHORT_FLOAT_REPR == 1
1315

16+
typedef uint32_t ULong;
17+
18+
struct
19+
Bigint {
20+
struct Bigint *next;
21+
int k, maxwds, sign, wds;
22+
ULong x[1];
23+
};
24+
25+
#ifdef Py_USING_MEMORY_DEBUGGER
26+
27+
struct _dtoa_runtime_state {
28+
int _not_used;
29+
};
30+
#define _dtoa_runtime_state_INIT {0}
31+
32+
#else // !Py_USING_MEMORY_DEBUGGER
33+
34+
/* The size of the Bigint freelist */
35+
#define Bigint_Kmax 7
36+
37+
#ifndef PRIVATE_MEM
38+
#define PRIVATE_MEM 2304
39+
#endif
40+
#define Bigint_PREALLOC_SIZE \
41+
((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
42+
43+
struct _dtoa_runtime_state {
44+
struct Bigint *freelist[Bigint_Kmax+1];
45+
double preallocated[Bigint_PREALLOC_SIZE];
46+
double *preallocated_next;
47+
};
48+
#define _dtoa_runtime_state_INIT(runtime) \
49+
{ \
50+
.preallocated_next = runtime.dtoa.preallocated, \
51+
}
52+
53+
#endif // !Py_USING_MEMORY_DEBUGGER
54+
55+
1456
/* These functions are used by modules compiled as C extension like math:
1557
they must be exported. */
1658

@@ -26,3 +68,4 @@ PyAPI_FUNC(double) _Py_dg_infinity(int sign);
2668
#ifdef __cplusplus
2769
}
2870
#endif
71+
#endif /* !Py_INTERNAL_DTOA_H */

Include/internal/pycore_interp.h

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern "C" {
2626
#include "pycore_unicodeobject.h" // struct _Py_unicode_state
2727
#include "pycore_warnings.h" // struct _warnings_runtime_state
2828

29+
2930
struct _pending_calls {
3031
PyThread_type_lock lock;
3132
/* Request for running pending calls. */

Include/internal/pycore_pylifecycle.h

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc);
3333

3434
/* Various one-time initializers */
3535

36+
extern void _Py_InitVersion(void);
3637
extern PyStatus _PyImport_Init(void);
3738
extern PyStatus _PyFaulthandler_Init(int enable);
3839
extern int _PyTraceMalloc_Init(int enable);

Include/internal/pycore_pymem.h

-2
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ struct _PyTraceMalloc_Config {
113113
.tracing = 0, \
114114
.max_nframe = 1}
115115

116-
PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config;
117-
118116
#ifdef __cplusplus
119117
}
120118
#endif

Include/internal/pycore_runtime.h

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

1111
#include "pycore_atomic.h" /* _Py_atomic_address */
12+
#include "pycore_dtoa.h" // struct _dtoa_runtime_state
1213
#include "pycore_gil.h" // struct _gil_runtime_state
1314
#include "pycore_global_objects.h" // struct _Py_global_objects
1415
#include "pycore_import.h" // struct _import_runtime_state
@@ -18,7 +19,8 @@ extern "C" {
1819
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids
1920

2021
struct _getargs_runtime_state {
21-
PyThread_type_lock mutex;
22+
PyThread_type_lock mutex;
23+
struct _PyArg_Parser *static_parsers;
2224
};
2325

2426
/* ceval state */
@@ -125,6 +127,10 @@ typedef struct pyruntimestate {
125127
struct _ceval_runtime_state ceval;
126128
struct _gilstate_runtime_state gilstate;
127129
struct _getargs_runtime_state getargs;
130+
struct {
131+
struct _PyTraceMalloc_Config config;
132+
} tracemalloc;
133+
struct _dtoa_runtime_state dtoa;
128134

129135
PyPreConfig preconfig;
130136

Include/internal/pycore_runtime_init.h

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ extern "C" {
3636
until _PyInterpreterState_Enable() is called. */ \
3737
.next_id = -1, \
3838
}, \
39+
.tracemalloc = { \
40+
.config = _PyTraceMalloc_Config_INIT, \
41+
}, \
42+
.dtoa = _dtoa_runtime_state_INIT(runtime), \
3943
.types = { \
4044
.next_version_tag = 1, \
4145
}, \

Modules/_tracemalloc.c

+26-24
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ module _tracemalloc
1616
[clinic start generated code]*/
1717
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/
1818

19+
#define tracemalloc_config _PyRuntime.tracemalloc.config
20+
1921
_Py_DECLARE_STR(anon_unknown, "<unknown>");
2022

2123
/* Trace memory blocks allocated by PyMem_RawMalloc() */
@@ -407,7 +409,7 @@ traceback_get_frames(traceback_t *traceback)
407409
if (pyframe == NULL) {
408410
break;
409411
}
410-
if (traceback->nframe < _Py_tracemalloc_config.max_nframe) {
412+
if (traceback->nframe < tracemalloc_config.max_nframe) {
411413
tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
412414
assert(traceback->frames[traceback->nframe].filename != NULL);
413415
traceback->nframe++;
@@ -505,7 +507,7 @@ tracemalloc_get_traces_table(unsigned int domain)
505507
static void
506508
tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
507509
{
508-
assert(_Py_tracemalloc_config.tracing);
510+
assert(tracemalloc_config.tracing);
509511

510512
_Py_hashtable_t *traces = tracemalloc_get_traces_table(domain);
511513
if (!traces) {
@@ -529,7 +531,7 @@ static int
529531
tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
530532
size_t size)
531533
{
532-
assert(_Py_tracemalloc_config.tracing);
534+
assert(tracemalloc_config.tracing);
533535

534536
traceback_t *traceback = traceback_new();
535537
if (traceback == NULL) {
@@ -863,13 +865,13 @@ tracemalloc_clear_traces(void)
863865
static int
864866
tracemalloc_init(void)
865867
{
866-
if (_Py_tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
868+
if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
867869
PyErr_SetString(PyExc_RuntimeError,
868870
"the tracemalloc module has been unloaded");
869871
return -1;
870872
}
871873

872-
if (_Py_tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
874+
if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
873875
return 0;
874876

875877
PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
@@ -919,17 +921,17 @@ tracemalloc_init(void)
919921
tracemalloc_empty_traceback.frames[0].lineno = 0;
920922
tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
921923

922-
_Py_tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
924+
tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
923925
return 0;
924926
}
925927

926928

927929
static void
928930
tracemalloc_deinit(void)
929931
{
930-
if (_Py_tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
932+
if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
931933
return;
932-
_Py_tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
934+
tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
933935

934936
tracemalloc_stop();
935937

@@ -969,12 +971,12 @@ tracemalloc_start(int max_nframe)
969971
return -1;
970972
}
971973

972-
if (_Py_tracemalloc_config.tracing) {
974+
if (tracemalloc_config.tracing) {
973975
/* hook already installed: do nothing */
974976
return 0;
975977
}
976978

977-
_Py_tracemalloc_config.max_nframe = max_nframe;
979+
tracemalloc_config.max_nframe = max_nframe;
978980

979981
/* allocate a buffer to store a new traceback */
980982
size = TRACEBACK_SIZE(max_nframe);
@@ -1010,7 +1012,7 @@ tracemalloc_start(int max_nframe)
10101012
PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
10111013

10121014
/* everything is ready: start tracing Python memory allocations */
1013-
_Py_tracemalloc_config.tracing = 1;
1015+
tracemalloc_config.tracing = 1;
10141016

10151017
return 0;
10161018
}
@@ -1019,11 +1021,11 @@ tracemalloc_start(int max_nframe)
10191021
static void
10201022
tracemalloc_stop(void)
10211023
{
1022-
if (!_Py_tracemalloc_config.tracing)
1024+
if (!tracemalloc_config.tracing)
10231025
return;
10241026

10251027
/* stop tracing Python memory allocations */
1026-
_Py_tracemalloc_config.tracing = 0;
1028+
tracemalloc_config.tracing = 0;
10271029

10281030
/* unregister the hook on memory allocators */
10291031
#ifdef TRACE_RAW_MALLOC
@@ -1051,7 +1053,7 @@ static PyObject *
10511053
_tracemalloc_is_tracing_impl(PyObject *module)
10521054
/*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
10531055
{
1054-
return PyBool_FromLong(_Py_tracemalloc_config.tracing);
1056+
return PyBool_FromLong(tracemalloc_config.tracing);
10551057
}
10561058

10571059

@@ -1065,7 +1067,7 @@ static PyObject *
10651067
_tracemalloc_clear_traces_impl(PyObject *module)
10661068
/*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
10671069
{
1068-
if (!_Py_tracemalloc_config.tracing)
1070+
if (!tracemalloc_config.tracing)
10691071
Py_RETURN_NONE;
10701072

10711073
set_reentrant(1);
@@ -1345,7 +1347,7 @@ _tracemalloc__get_traces_impl(PyObject *module)
13451347
if (get_traces.list == NULL)
13461348
goto error;
13471349

1348-
if (!_Py_tracemalloc_config.tracing)
1350+
if (!tracemalloc_config.tracing)
13491351
return get_traces.list;
13501352

13511353
/* the traceback hash table is used temporarily to intern traceback tuple
@@ -1418,7 +1420,7 @@ static traceback_t*
14181420
tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
14191421
{
14201422

1421-
if (!_Py_tracemalloc_config.tracing)
1423+
if (!tracemalloc_config.tracing)
14221424
return NULL;
14231425

14241426
trace_t *trace;
@@ -1498,7 +1500,7 @@ _PyMem_DumpTraceback(int fd, const void *ptr)
14981500
traceback_t *traceback;
14991501
int i;
15001502

1501-
if (!_Py_tracemalloc_config.tracing) {
1503+
if (!tracemalloc_config.tracing) {
15021504
PUTS(fd, "Enable tracemalloc to get the memory block "
15031505
"allocation traceback\n\n");
15041506
return;
@@ -1572,7 +1574,7 @@ static PyObject *
15721574
_tracemalloc_get_traceback_limit_impl(PyObject *module)
15731575
/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
15741576
{
1575-
return PyLong_FromLong(_Py_tracemalloc_config.max_nframe);
1577+
return PyLong_FromLong(tracemalloc_config.max_nframe);
15761578
}
15771579

15781580

@@ -1630,7 +1632,7 @@ _tracemalloc_get_traced_memory_impl(PyObject *module)
16301632
{
16311633
Py_ssize_t size, peak_size;
16321634

1633-
if (!_Py_tracemalloc_config.tracing)
1635+
if (!tracemalloc_config.tracing)
16341636
return Py_BuildValue("ii", 0, 0);
16351637

16361638
TABLES_LOCK();
@@ -1654,7 +1656,7 @@ static PyObject *
16541656
_tracemalloc_reset_peak_impl(PyObject *module)
16551657
/*[clinic end generated code: output=140c2870f691dbb2 input=18afd0635066e9ce]*/
16561658
{
1657-
if (!_Py_tracemalloc_config.tracing) {
1659+
if (!tracemalloc_config.tracing) {
16581660
Py_RETURN_NONE;
16591661
}
16601662

@@ -1735,7 +1737,7 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
17351737
int res;
17361738
PyGILState_STATE gil_state;
17371739

1738-
if (!_Py_tracemalloc_config.tracing) {
1740+
if (!tracemalloc_config.tracing) {
17391741
/* tracemalloc is not tracing: do nothing */
17401742
return -2;
17411743
}
@@ -1754,7 +1756,7 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
17541756
int
17551757
PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
17561758
{
1757-
if (!_Py_tracemalloc_config.tracing) {
1759+
if (!tracemalloc_config.tracing) {
17581760
/* tracemalloc is not tracing: do nothing */
17591761
return -2;
17601762
}
@@ -1777,7 +1779,7 @@ _PyTraceMalloc_NewReference(PyObject *op)
17771779
{
17781780
assert(PyGILState_Check());
17791781

1780-
if (!_Py_tracemalloc_config.tracing) {
1782+
if (!tracemalloc_config.tracing) {
17811783
/* tracemalloc is not tracing: do nothing */
17821784
return -1;
17831785
}

Modules/getbuildinfo.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,18 @@
3131
#define GITBRANCH ""
3232
#endif
3333

34+
static int initialized = 0;
35+
static char buildinfo[50 + sizeof(GITVERSION) +
36+
((sizeof(GITTAG) > sizeof(GITBRANCH)) ?
37+
sizeof(GITTAG) : sizeof(GITBRANCH))];
38+
3439
const char *
3540
Py_GetBuildInfo(void)
3641
{
37-
static char buildinfo[50 + sizeof(GITVERSION) +
38-
((sizeof(GITTAG) > sizeof(GITBRANCH)) ?
39-
sizeof(GITTAG) : sizeof(GITBRANCH))];
42+
if (initialized) {
43+
return buildinfo;
44+
}
45+
initialized = 1;
4046
const char *revision = _Py_gitversion();
4147
const char *sep = *revision ? ":" : "";
4248
const char *gitid = _Py_gitidentifier();

Objects/object.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2001,7 +2001,7 @@ _PyTypes_FiniTypes(PyInterpreterState *interp)
20012001
void
20022002
_Py_NewReference(PyObject *op)
20032003
{
2004-
if (_Py_tracemalloc_config.tracing) {
2004+
if (_PyRuntime.tracemalloc.config.tracing) {
20052005
_PyTraceMalloc_NewReference(op);
20062006
}
20072007
#ifdef Py_REF_DEBUG

Objects/obmalloc.c

-6
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,6 @@ _PyMem_ArenaFree(void *Py_UNUSED(ctx), void *ptr,
201201
#endif
202202

203203

204-
/* bpo-35053: Declare tracemalloc configuration here rather than
205-
Modules/_tracemalloc.c because _tracemalloc can be compiled as dynamic
206-
library, whereas _Py_NewReference() requires it. */
207-
struct _PyTraceMalloc_Config _Py_tracemalloc_config = _PyTraceMalloc_Config_INIT;
208-
209-
210204
#define _PyMem_Raw (_PyRuntime.allocators.standard.raw)
211205
#define _PyMem (_PyRuntime.allocators.standard.mem)
212206
#define _PyObject (_PyRuntime.allocators.standard.obj)

Parser/action_helpers.c

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ _create_dummy_identifier(Parser *p)
1212
void *
1313
_PyPegen_dummy_name(Parser *p, ...)
1414
{
15+
// XXX This leaks memory from the initial arena.
1516
static void *cache = NULL;
1617

1718
if (cache != NULL) {

0 commit comments

Comments
 (0)