Skip to content

Commit

Permalink
gh-81057: Move Globals in Core Code to _PyRuntimeState (gh-99496)
Browse files Browse the repository at this point in the history
This is the first of several changes to consolidate non-object globals in core code.

#81057
  • Loading branch information
ericsnowcurrently authored Nov 15, 2022
1 parent 73943cb commit 3c57971
Show file tree
Hide file tree
Showing 17 changed files with 236 additions and 168 deletions.
43 changes: 43 additions & 0 deletions Include/internal/pycore_dtoa.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#ifndef Py_INTERNAL_DTOA_H
#define Py_INTERNAL_DTOA_H
#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -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. */

Expand All @@ -26,3 +68,4 @@ PyAPI_FUNC(double) _Py_dg_infinity(int sign);
#ifdef __cplusplus
}
#endif
#endif /* !Py_INTERNAL_DTOA_H */
1 change: 1 addition & 0 deletions Include/internal/pycore_interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 0 additions & 2 deletions Include/internal/pycore_pymem.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ struct _PyTraceMalloc_Config {
.tracing = 0, \
.max_nframe = 1}

PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config;

#ifdef __cplusplus
}
#endif
Expand Down
8 changes: 7 additions & 1 deletion Include/internal/pycore_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 */
Expand Down Expand Up @@ -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;

Expand Down
4 changes: 4 additions & 0 deletions Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
}, \
Expand Down
50 changes: 26 additions & 24 deletions Modules/_tracemalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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() */
Expand Down Expand Up @@ -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++;
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -919,17 +921,17 @@ 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;
}


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();

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand All @@ -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
Expand Down Expand Up @@ -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);
}


Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}


Expand Down Expand Up @@ -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();
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
12 changes: 9 additions & 3 deletions Modules/getbuildinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@
#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();
Expand Down
2 changes: 1 addition & 1 deletion Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 0 additions & 6 deletions Objects/obmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions Parser/action_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit 3c57971

Please sign in to comment.