Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-45953: Statically initialize all the non-object PyInterpreterState fields we can. #30589

Merged
5 changes: 5 additions & 0 deletions Include/internal/pycore_ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ extern "C" {
struct pyruntimestate;
struct _ceval_runtime_state;

#ifndef Py_DEFAULT_RECURSION_LIMIT
# define Py_DEFAULT_RECURSION_LIMIT 1000
#endif

#include "pycore_interp.h" // PyInterpreterState.eval_frame
#include "pycore_pystate.h" // _PyThreadState_GET()


extern void _Py_FinishPendingCalls(PyThreadState *tstate);
extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *);
extern void _PyEval_InitState(struct _ceval_state *, PyThread_type_lock);
Expand Down
2 changes: 2 additions & 0 deletions Include/internal/pycore_gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct _gc_runtime_state {
/* Current call-stack depth of tp_dealloc calls. */
int trash_delete_nesting;

/* Is automatic collection enabled? */
int enabled;
int debug;
/* linked lists of container objects */
Expand Down Expand Up @@ -161,6 +162,7 @@ struct _gc_runtime_state {
Py_ssize_t long_lived_pending;
};


extern void _PyGC_InitState(struct _gc_runtime_state *);

extern Py_ssize_t _PyGC_CollectNoFail(PyThreadState *tstate);
Expand Down
27 changes: 27 additions & 0 deletions Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,36 @@ extern "C" {
._main_interpreter = _PyInterpreterState_INIT, \
}

#ifdef HAVE_DLOPEN
# include <dlfcn.h>
# if HAVE_DECL_RTLD_NOW
# define _Py_DLOPEN_FLAGS RTLD_NOW
# else
# define _Py_DLOPEN_FLAGS RTLD_LAZY
# endif
# define DLOPENFLAGS_INIT .dlopenflags = _Py_DLOPEN_FLAGS,
#else
# define _Py_DLOPEN_FLAGS 0
# define DLOPENFLAGS_INIT
#endif

#define _PyInterpreterState_INIT \
{ \
._static = 1, \
.id_refcount = -1, \
DLOPENFLAGS_INIT \
.ceval = { \
.recursion_limit = Py_DEFAULT_RECURSION_LIMIT, \
}, \
.gc = { \
.enabled = 1, \
.generations = { \
/* .head is set in _PyGC_InitState(). */ \
{ .threshold = 700, }, \
{ .threshold = 10, }, \
{ .threshold = 10, }, \
}, \
}, \
._initial_thread = _PyThreadState_INIT, \
}

Expand Down
26 changes: 11 additions & 15 deletions Modules/gcmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,24 +139,20 @@ get_gc_state(void)
void
_PyGC_InitState(GCState *gcstate)
{
gcstate->enabled = 1; /* automatic collection enabled? */

#define _GEN_HEAD(n) GEN_HEAD(gcstate, n)
struct gc_generation generations[NUM_GENERATIONS] = {
/* PyGC_Head, threshold, count */
{{(uintptr_t)_GEN_HEAD(0), (uintptr_t)_GEN_HEAD(0)}, 700, 0},
{{(uintptr_t)_GEN_HEAD(1), (uintptr_t)_GEN_HEAD(1)}, 10, 0},
{{(uintptr_t)_GEN_HEAD(2), (uintptr_t)_GEN_HEAD(2)}, 10, 0},
};
#define INIT_HEAD(GEN) \
do { \
GEN.head._gc_next = (uintptr_t)&GEN.head; \
GEN.head._gc_prev = (uintptr_t)&GEN.head; \
} while (0)

for (int i = 0; i < NUM_GENERATIONS; i++) {
gcstate->generations[i] = generations[i];
assert(gcstate->generations[i].count == 0);
INIT_HEAD(gcstate->generations[i]);
};
gcstate->generation0 = GEN_HEAD(gcstate, 0);
struct gc_generation permanent_generation = {
{(uintptr_t)&gcstate->permanent_generation.head,
(uintptr_t)&gcstate->permanent_generation.head}, 0, 0
};
gcstate->permanent_generation = permanent_generation;
INIT_HEAD(gcstate->permanent_generation);

#undef INIT_HEAD
}


Expand Down
6 changes: 0 additions & 6 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,10 +737,6 @@ Py_MakePendingCalls(void)

/* The interpreter's recursion limit */

#ifndef Py_DEFAULT_RECURSION_LIMIT
# define Py_DEFAULT_RECURSION_LIMIT 1000
#endif

void
_PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
{
Expand All @@ -752,8 +748,6 @@ _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
void
_PyEval_InitState(struct _ceval_state *ceval, PyThread_type_lock pending_lock)
{
ceval->recursion_limit = Py_DEFAULT_RECURSION_LIMIT;

struct _pending_calls *pending = &ceval->pending;
assert(pending->lock == NULL);

Expand Down
9 changes: 0 additions & 9 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,6 @@ init_interpreter(PyInterpreterState *interp,

assert(id > 0 || (id == 0 && interp == runtime->interpreters.main));
interp->id = id;
interp->id_refcount = -1;

assert(runtime->interpreters.head == interp);
assert(next != NULL || (interp == runtime->interpreters.main));
Expand All @@ -291,14 +290,6 @@ init_interpreter(PyInterpreterState *interp,
_PyGC_InitState(&interp->gc);
PyConfig_InitPythonConfig(&interp->config);
_PyType_InitCache(interp);
interp->eval_frame = NULL;
#ifdef HAVE_DLOPEN
#if HAVE_DECL_RTLD_NOW
interp->dlopenflags = RTLD_NOW;
#else
interp->dlopenflags = RTLD_LAZY;
#endif
#endif

interp->_initialized = 1;
}
Expand Down